1 // SPDX-License-Identifier: GPL-2.0
3 * Intel Speed Select -- Enumerate and control features
4 * Copyright (c) 2019 Intel Corporation.
9 int isst_get_ctdp_levels(int cpu
, struct isst_pkg_ctdp
*pkg_dev
)
14 ret
= isst_send_mbox_command(cpu
, CONFIG_TDP
,
15 CONFIG_TDP_GET_LEVELS_INFO
, 0, 0, &resp
);
19 debug_printf("cpu:%d CONFIG_TDP_GET_LEVELS_INFO resp:%x\n", cpu
, resp
);
21 pkg_dev
->version
= resp
& 0xff;
22 pkg_dev
->levels
= (resp
>> 8) & 0xff;
23 pkg_dev
->current_level
= (resp
>> 16) & 0xff;
24 pkg_dev
->locked
= !!(resp
& BIT(24));
25 pkg_dev
->enabled
= !!(resp
& BIT(31));
30 int isst_get_ctdp_control(int cpu
, int config_index
,
31 struct isst_pkg_ctdp_level_info
*ctdp_level
)
36 ret
= isst_send_mbox_command(cpu
, CONFIG_TDP
,
37 CONFIG_TDP_GET_TDP_CONTROL
, 0,
42 ctdp_level
->fact_support
= resp
& BIT(0);
43 ctdp_level
->pbf_support
= !!(resp
& BIT(1));
44 ctdp_level
->fact_enabled
= !!(resp
& BIT(16));
45 ctdp_level
->pbf_enabled
= !!(resp
& BIT(17));
48 "cpu:%d CONFIG_TDP_GET_TDP_CONTROL resp:%x fact_support:%d pbf_support: %d fact_enabled:%d pbf_enabled:%d\n",
49 cpu
, resp
, ctdp_level
->fact_support
, ctdp_level
->pbf_support
,
50 ctdp_level
->fact_enabled
, ctdp_level
->pbf_enabled
);
55 int isst_get_tdp_info(int cpu
, int config_index
,
56 struct isst_pkg_ctdp_level_info
*ctdp_level
)
61 ret
= isst_send_mbox_command(cpu
, CONFIG_TDP
, CONFIG_TDP_GET_TDP_INFO
,
62 0, config_index
, &resp
);
66 ctdp_level
->pkg_tdp
= resp
& GENMASK(14, 0);
67 ctdp_level
->tdp_ratio
= (resp
& GENMASK(23, 16)) >> 16;
70 "cpu:%d ctdp:%d CONFIG_TDP_GET_TDP_INFO resp:%x tdp_ratio:%d pkg_tdp:%d\n",
71 cpu
, config_index
, resp
, ctdp_level
->tdp_ratio
,
76 int isst_get_pwr_info(int cpu
, int config_index
,
77 struct isst_pkg_ctdp_level_info
*ctdp_level
)
82 ret
= isst_send_mbox_command(cpu
, CONFIG_TDP
, CONFIG_TDP_GET_PWR_INFO
,
83 0, config_index
, &resp
);
87 ctdp_level
->pkg_max_power
= resp
& GENMASK(14, 0);
88 ctdp_level
->pkg_min_power
= (resp
& GENMASK(30, 16)) >> 16;
91 "cpu:%d ctdp:%d CONFIG_TDP_GET_PWR_INFO resp:%x pkg_max_power:%d pkg_min_power:%d\n",
92 cpu
, config_index
, resp
, ctdp_level
->pkg_max_power
,
93 ctdp_level
->pkg_min_power
);
98 int isst_get_tjmax_info(int cpu
, int config_index
,
99 struct isst_pkg_ctdp_level_info
*ctdp_level
)
104 ret
= isst_send_mbox_command(cpu
, CONFIG_TDP
, CONFIG_TDP_GET_TJMAX_INFO
,
105 0, config_index
, &resp
);
109 ctdp_level
->t_proc_hot
= resp
& GENMASK(7, 0);
112 "cpu:%d ctdp:%d CONFIG_TDP_GET_TJMAX_INFO resp:%x t_proc_hot:%d\n",
113 cpu
, config_index
, resp
, ctdp_level
->t_proc_hot
);
118 int isst_get_coremask_info(int cpu
, int config_index
,
119 struct isst_pkg_ctdp_level_info
*ctdp_level
)
124 ctdp_level
->cpu_count
= 0;
125 for (i
= 0; i
< 2; ++i
) {
126 unsigned long long mask
;
129 ret
= isst_send_mbox_command(cpu
, CONFIG_TDP
,
130 CONFIG_TDP_GET_CORE_MASK
, 0,
131 (i
<< 8) | config_index
, &resp
);
136 "cpu:%d ctdp:%d mask:%d CONFIG_TDP_GET_CORE_MASK resp:%x\n",
137 cpu
, config_index
, i
, resp
);
139 mask
= (unsigned long long)resp
<< (32 * i
);
140 set_cpu_mask_from_punit_coremask(cpu
, mask
,
141 ctdp_level
->core_cpumask_size
,
142 ctdp_level
->core_cpumask
,
144 ctdp_level
->cpu_count
+= cpu_count
;
145 debug_printf("cpu:%d ctdp:%d mask:%d cpu count:%d\n", cpu
,
146 config_index
, i
, ctdp_level
->cpu_count
);
152 int isst_get_get_trl(int cpu
, int level
, int avx_level
, int *trl
)
154 unsigned int req
, resp
;
157 req
= level
| (avx_level
<< 16);
158 ret
= isst_send_mbox_command(cpu
, CONFIG_TDP
,
159 CONFIG_TDP_GET_TURBO_LIMIT_RATIOS
, 0, req
,
165 "cpu:%d CONFIG_TDP_GET_TURBO_LIMIT_RATIOS req:%x resp:%x\n",
168 trl
[0] = resp
& GENMASK(7, 0);
169 trl
[1] = (resp
& GENMASK(15, 8)) >> 8;
170 trl
[2] = (resp
& GENMASK(23, 16)) >> 16;
171 trl
[3] = (resp
& GENMASK(31, 24)) >> 24;
173 req
= level
| BIT(8) | (avx_level
<< 16);
174 ret
= isst_send_mbox_command(cpu
, CONFIG_TDP
,
175 CONFIG_TDP_GET_TURBO_LIMIT_RATIOS
, 0, req
,
180 debug_printf("cpu:%d CONFIG_TDP_GET_TURBO_LIMIT req:%x resp:%x\n", cpu
,
183 trl
[4] = resp
& GENMASK(7, 0);
184 trl
[5] = (resp
& GENMASK(15, 8)) >> 8;
185 trl
[6] = (resp
& GENMASK(23, 16)) >> 16;
186 trl
[7] = (resp
& GENMASK(31, 24)) >> 24;
191 int isst_set_tdp_level_msr(int cpu
, int tdp_level
)
195 debug_printf("cpu: tdp_level via MSR %d\n", cpu
, tdp_level
);
197 if (isst_get_config_tdp_lock_status(cpu
)) {
198 debug_printf("cpu: tdp_locked %d\n", cpu
);
203 return -1; /* invalid value */
205 ret
= isst_send_msr_command(cpu
, 0x64b, 1,
206 (unsigned long long *)&tdp_level
);
210 debug_printf("cpu: tdp_level via MSR successful %d\n", cpu
, tdp_level
);
215 int isst_set_tdp_level(int cpu
, int tdp_level
)
220 ret
= isst_send_mbox_command(cpu
, CONFIG_TDP
, CONFIG_TDP_SET_LEVEL
, 0,
223 return isst_set_tdp_level_msr(cpu
, tdp_level
);
228 int isst_get_pbf_info(int cpu
, int level
, struct isst_pbf_info
*pbf_info
)
230 unsigned int req
, resp
;
233 pbf_info
->core_cpumask_size
= alloc_cpu_set(&pbf_info
->core_cpumask
);
235 for (i
= 0; i
< 2; ++i
) {
236 unsigned long long mask
;
239 ret
= isst_send_mbox_command(cpu
, CONFIG_TDP
,
240 CONFIG_TDP_PBF_GET_CORE_MASK_INFO
,
241 0, (i
<< 8) | level
, &resp
);
246 "cpu:%d CONFIG_TDP_PBF_GET_CORE_MASK_INFO resp:%x\n",
249 mask
= (unsigned long long)resp
<< (32 * i
);
250 set_cpu_mask_from_punit_coremask(cpu
, mask
,
251 pbf_info
->core_cpumask_size
,
252 pbf_info
->core_cpumask
,
257 ret
= isst_send_mbox_command(cpu
, CONFIG_TDP
,
258 CONFIG_TDP_PBF_GET_P1HI_P1LO_INFO
, 0, req
,
263 debug_printf("cpu:%d CONFIG_TDP_PBF_GET_P1HI_P1LO_INFO resp:%x\n", cpu
,
266 pbf_info
->p1_low
= resp
& 0xff;
267 pbf_info
->p1_high
= (resp
& GENMASK(15, 8)) >> 8;
270 ret
= isst_send_mbox_command(
271 cpu
, CONFIG_TDP
, CONFIG_TDP_PBF_GET_TDP_INFO
, 0, req
, &resp
);
275 debug_printf("cpu:%d CONFIG_TDP_PBF_GET_TDP_INFO resp:%x\n", cpu
, resp
);
277 pbf_info
->tdp
= resp
& 0xffff;
280 ret
= isst_send_mbox_command(
281 cpu
, CONFIG_TDP
, CONFIG_TDP_PBF_GET_TJ_MAX_INFO
, 0, req
, &resp
);
285 debug_printf("cpu:%d CONFIG_TDP_PBF_GET_TJ_MAX_INFO resp:%x\n", cpu
,
287 pbf_info
->t_control
= (resp
>> 8) & 0xff;
288 pbf_info
->t_prochot
= resp
& 0xff;
293 void isst_get_pbf_info_complete(struct isst_pbf_info
*pbf_info
)
295 free_cpu_set(pbf_info
->core_cpumask
);
298 int isst_set_pbf_fact_status(int cpu
, int pbf
, int enable
)
300 struct isst_pkg_ctdp pkg_dev
;
301 struct isst_pkg_ctdp_level_info ctdp_level
;
303 unsigned int req
= 0, resp
;
306 ret
= isst_get_ctdp_levels(cpu
, &pkg_dev
);
310 current_level
= pkg_dev
.current_level
;
312 ret
= isst_get_ctdp_control(cpu
, current_level
, &ctdp_level
);
317 if (ctdp_level
.fact_enabled
)
325 if (ctdp_level
.pbf_enabled
)
334 ret
= isst_send_mbox_command(cpu
, CONFIG_TDP
,
335 CONFIG_TDP_SET_TDP_CONTROL
, 0, req
, &resp
);
339 debug_printf("cpu:%d CONFIG_TDP_SET_TDP_CONTROL pbf/fact:%d req:%x\n",
345 int isst_get_fact_bucket_info(int cpu
, int level
,
346 struct isst_fact_bucket_info
*bucket_info
)
351 for (i
= 0; i
< 2; ++i
) {
354 ret
= isst_send_mbox_command(
356 CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES
, 0,
357 (i
<< 8) | level
, &resp
);
362 "cpu:%d CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES index:%d level:%d resp:%x\n",
363 cpu
, i
, level
, resp
);
365 for (j
= 0; j
< 4; ++j
) {
366 bucket_info
[j
+ (i
* 4)].high_priority_cores_count
=
367 (resp
>> (j
* 8)) & 0xff;
371 for (k
= 0; k
< 3; ++k
) {
372 for (i
= 0; i
< 2; ++i
) {
375 ret
= isst_send_mbox_command(
377 CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS
, 0,
378 (k
<< 16) | (i
<< 8) | level
, &resp
);
383 "cpu:%d CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS index:%d level:%d avx:%d resp:%x\n",
384 cpu
, i
, level
, k
, resp
);
386 for (j
= 0; j
< 4; ++j
) {
389 bucket_info
[j
+ (i
* 4)].sse_trl
=
390 (resp
>> (j
* 8)) & 0xff;
393 bucket_info
[j
+ (i
* 4)].avx_trl
=
394 (resp
>> (j
* 8)) & 0xff;
397 bucket_info
[j
+ (i
* 4)].avx512_trl
=
398 (resp
>> (j
* 8)) & 0xff;
410 int isst_get_fact_info(int cpu
, int level
, struct isst_fact_info
*fact_info
)
415 ret
= isst_send_mbox_command(cpu
, CONFIG_TDP
,
416 CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO
, 0,
421 debug_printf("cpu:%d CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO resp:%x\n",
424 fact_info
->lp_clipping_ratio_license_sse
= resp
& 0xff;
425 fact_info
->lp_clipping_ratio_license_avx2
= (resp
>> 8) & 0xff;
426 fact_info
->lp_clipping_ratio_license_avx512
= (resp
>> 16) & 0xff;
428 ret
= isst_get_fact_bucket_info(cpu
, level
, fact_info
->bucket_info
);
433 int isst_set_trl(int cpu
, unsigned long long trl
)
438 trl
= 0xFFFFFFFFFFFFFFFFULL
;
440 ret
= isst_send_msr_command(cpu
, 0x1AD, 1, &trl
);
447 int isst_set_trl_from_current_tdp(int cpu
, unsigned long long trl
)
449 unsigned long long msr_trl
;
455 struct isst_pkg_ctdp pkg_dev
;
459 ret
= isst_get_ctdp_levels(cpu
, &pkg_dev
);
463 ret
= isst_get_get_trl(cpu
, pkg_dev
.current_level
, 0, trl
);
468 for (i
= 0; i
< 8; ++i
) {
469 unsigned long long _trl
= trl
[i
];
471 msr_trl
|= (_trl
<< (i
* 8));
474 ret
= isst_send_msr_command(cpu
, 0x1AD, 1, &msr_trl
);
481 /* Return 1 if locked */
482 int isst_get_config_tdp_lock_status(int cpu
)
484 unsigned long long tdp_control
= 0;
487 ret
= isst_send_msr_command(cpu
, 0x64b, 0, &tdp_control
);
491 ret
= !!(tdp_control
& BIT(31));
496 void isst_get_process_ctdp_complete(int cpu
, struct isst_pkg_ctdp
*pkg_dev
)
500 if (!pkg_dev
->processed
)
503 for (i
= 0; i
< pkg_dev
->levels
; ++i
) {
504 struct isst_pkg_ctdp_level_info
*ctdp_level
;
506 ctdp_level
= &pkg_dev
->ctdp_level
[i
];
507 if (ctdp_level
->pbf_support
)
508 free_cpu_set(ctdp_level
->pbf_info
.core_cpumask
);
509 free_cpu_set(ctdp_level
->core_cpumask
);
513 int isst_get_process_ctdp(int cpu
, int tdp_level
, struct isst_pkg_ctdp
*pkg_dev
)
517 if (pkg_dev
->processed
)
520 ret
= isst_get_ctdp_levels(cpu
, pkg_dev
);
524 debug_printf("cpu: %d ctdp enable:%d current level: %d levels:%d\n",
525 cpu
, pkg_dev
->enabled
, pkg_dev
->current_level
,
528 for (i
= 0; i
<= pkg_dev
->levels
; ++i
) {
529 struct isst_pkg_ctdp_level_info
*ctdp_level
;
531 if (tdp_level
!= 0xff && i
!= tdp_level
)
534 debug_printf("cpu:%d Get Information for TDP level:%d\n", cpu
,
536 ctdp_level
= &pkg_dev
->ctdp_level
[i
];
538 ctdp_level
->level
= i
;
539 ctdp_level
->control_cpu
= cpu
;
540 ctdp_level
->pkg_id
= get_physical_package_id(cpu
);
541 ctdp_level
->die_id
= get_physical_die_id(cpu
);
543 ret
= isst_get_ctdp_control(cpu
, i
, ctdp_level
);
547 pkg_dev
->processed
= 1;
548 ctdp_level
->processed
= 1;
550 ret
= isst_get_tdp_info(cpu
, i
, ctdp_level
);
554 ret
= isst_get_pwr_info(cpu
, i
, ctdp_level
);
558 ret
= isst_get_tjmax_info(cpu
, i
, ctdp_level
);
562 ctdp_level
->core_cpumask_size
=
563 alloc_cpu_set(&ctdp_level
->core_cpumask
);
564 ret
= isst_get_coremask_info(cpu
, i
, ctdp_level
);
568 ret
= isst_get_get_trl(cpu
, i
, 0,
569 ctdp_level
->trl_sse_active_cores
);
573 ret
= isst_get_get_trl(cpu
, i
, 1,
574 ctdp_level
->trl_avx_active_cores
);
578 ret
= isst_get_get_trl(cpu
, i
, 2,
579 ctdp_level
->trl_avx_512_active_cores
);
583 if (ctdp_level
->pbf_support
) {
584 ret
= isst_get_pbf_info(cpu
, i
, &ctdp_level
->pbf_info
);
586 ctdp_level
->pbf_found
= 1;
589 if (ctdp_level
->fact_support
) {
590 ret
= isst_get_fact_info(cpu
, i
,
591 &ctdp_level
->fact_info
);
600 int isst_pm_qos_config(int cpu
, int enable_clos
, int priority_type
)
602 unsigned int req
, resp
;
605 ret
= isst_send_mbox_command(cpu
, CONFIG_CLOS
, CLOS_PM_QOS_CONFIG
, 0, 0,
610 debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", cpu
, resp
);
624 ret
= isst_send_mbox_command(cpu
, CONFIG_CLOS
, CLOS_PM_QOS_CONFIG
,
625 BIT(MBOX_CMD_WRITE_BIT
), req
, &resp
);
629 debug_printf("cpu:%d CLOS_PM_QOS_CONFIG priority type:%d req:%x\n", cpu
,
635 int isst_pm_get_clos(int cpu
, int clos
, struct isst_clos_config
*clos_config
)
640 ret
= isst_send_mbox_command(cpu
, CONFIG_CLOS
, CLOS_PM_CLOS
, clos
, 0,
645 clos_config
->pkg_id
= get_physical_package_id(cpu
);
646 clos_config
->die_id
= get_physical_die_id(cpu
);
648 clos_config
->epp
= resp
& 0x0f;
649 clos_config
->clos_prop_prio
= (resp
>> 4) & 0x0f;
650 clos_config
->clos_min
= (resp
>> 8) & 0xff;
651 clos_config
->clos_max
= (resp
>> 16) & 0xff;
652 clos_config
->clos_desired
= (resp
>> 24) & 0xff;
657 int isst_set_clos(int cpu
, int clos
, struct isst_clos_config
*clos_config
)
659 unsigned int req
, resp
;
663 req
= clos_config
->epp
& 0x0f;
664 req
|= (clos_config
->clos_prop_prio
& 0x0f) << 4;
665 req
|= (clos_config
->clos_min
& 0xff) << 8;
666 req
|= (clos_config
->clos_max
& 0xff) << 16;
667 req
|= (clos_config
->clos_desired
& 0xff) << 24;
669 param
= BIT(MBOX_CMD_WRITE_BIT
) | clos
;
671 ret
= isst_send_mbox_command(cpu
, CONFIG_CLOS
, CLOS_PM_CLOS
, param
, req
,
676 debug_printf("cpu:%d CLOS_PM_CLOS param:%x req:%x\n", cpu
, param
, req
);
681 int isst_clos_get_assoc_status(int cpu
, int *clos_id
)
687 core_id
= find_phy_core_num(cpu
);
690 ret
= isst_send_mbox_command(cpu
, CONFIG_CLOS
, CLOS_PQR_ASSOC
, param
, 0,
695 debug_printf("cpu:%d CLOS_PQR_ASSOC param:%x resp:%x\n", cpu
, param
,
697 *clos_id
= (resp
>> 16) & 0x03;
702 int isst_clos_associate(int cpu
, int clos_id
)
704 unsigned int req
, resp
;
708 req
= (clos_id
& 0x03) << 16;
709 core_id
= find_phy_core_num(cpu
);
710 param
= BIT(MBOX_CMD_WRITE_BIT
) | core_id
;
712 ret
= isst_send_mbox_command(cpu
, CONFIG_CLOS
, CLOS_PQR_ASSOC
, param
,
717 debug_printf("cpu:%d CLOS_PQR_ASSOC param:%x req:%x\n", cpu
, param
,