2 * Copyright 2015 Advanced Micro Devices, Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
23 #include "linux/delay.h"
24 #include <linux/types.h>
25 #include <linux/kernel.h>
26 #include <linux/slab.h>
27 #include <drm/amdgpu_drm.h>
28 #include "cgs_common.h"
29 #include "power_state.h"
31 #include "pppcielanes.h"
33 #include "ppatomctrl.h"
36 #define VOLTAGE_SCALE 4
38 extern int cz_hwmgr_init(struct pp_hwmgr
*hwmgr
);
39 extern int tonga_hwmgr_init(struct pp_hwmgr
*hwmgr
);
40 extern int fiji_hwmgr_init(struct pp_hwmgr
*hwmgr
);
41 extern int polaris10_hwmgr_init(struct pp_hwmgr
*hwmgr
);
42 extern int iceland_hwmgr_init(struct pp_hwmgr
*hwmgr
);
44 static int hwmgr_set_features_platform_caps(struct pp_hwmgr
*hwmgr
)
46 if (amdgpu_sclk_deep_sleep_en
)
47 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
,
48 PHM_PlatformCaps_SclkDeepSleep
);
50 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
51 PHM_PlatformCaps_SclkDeepSleep
);
53 if (amdgpu_powercontainment
)
54 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
,
55 PHM_PlatformCaps_PowerContainment
);
57 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
,
58 PHM_PlatformCaps_PowerContainment
);
63 int hwmgr_init(struct amd_pp_init
*pp_init
, struct pp_instance
*handle
)
65 struct pp_hwmgr
*hwmgr
;
67 if ((handle
== NULL
) || (pp_init
== NULL
))
70 hwmgr
= kzalloc(sizeof(struct pp_hwmgr
), GFP_KERNEL
);
74 handle
->hwmgr
= hwmgr
;
75 hwmgr
->smumgr
= handle
->smu_mgr
;
76 hwmgr
->device
= pp_init
->device
;
77 hwmgr
->chip_family
= pp_init
->chip_family
;
78 hwmgr
->chip_id
= pp_init
->chip_id
;
79 hwmgr
->hw_revision
= pp_init
->rev_id
;
80 hwmgr
->sub_sys_id
= pp_init
->sub_sys_id
;
81 hwmgr
->sub_vendor_id
= pp_init
->sub_vendor_id
;
82 hwmgr
->usec_timeout
= AMD_MAX_USEC_TIMEOUT
;
83 hwmgr
->power_source
= PP_PowerSource_AC
;
85 hwmgr_set_features_platform_caps(hwmgr
);
87 switch (hwmgr
->chip_family
) {
88 case AMDGPU_FAMILY_CZ
:
91 case AMDGPU_FAMILY_VI
:
92 switch (hwmgr
->chip_id
) {
94 iceland_hwmgr_init(hwmgr
);
97 tonga_hwmgr_init(hwmgr
);
100 fiji_hwmgr_init(hwmgr
);
104 polaris10_hwmgr_init(hwmgr
);
114 phm_init_dynamic_caps(hwmgr
);
119 int hwmgr_fini(struct pp_hwmgr
*hwmgr
)
121 if (hwmgr
== NULL
|| hwmgr
->ps
== NULL
)
125 kfree(hwmgr
->hardcode_pp_table
);
127 kfree(hwmgr
->backend
);
129 kfree(hwmgr
->start_thermal_controller
.function_list
);
131 kfree(hwmgr
->set_temperature_range
.function_list
);
138 int hw_init_power_state_table(struct pp_hwmgr
*hwmgr
)
142 unsigned int table_entries
;
143 struct pp_power_state
*state
;
146 if (hwmgr
->hwmgr_func
->get_num_of_pp_table_entries
== NULL
)
149 if (hwmgr
->hwmgr_func
->get_power_state_size
== NULL
)
152 hwmgr
->num_ps
= table_entries
= hwmgr
->hwmgr_func
->get_num_of_pp_table_entries(hwmgr
);
154 hwmgr
->ps_size
= size
= hwmgr
->hwmgr_func
->get_power_state_size(hwmgr
) +
155 sizeof(struct pp_power_state
);
157 hwmgr
->ps
= kzalloc(size
* table_entries
, GFP_KERNEL
);
159 if (hwmgr
->ps
== NULL
)
164 for (i
= 0; i
< table_entries
; i
++) {
165 result
= hwmgr
->hwmgr_func
->get_pp_table_entry(hwmgr
, i
, state
);
167 if (state
->classification
.flags
& PP_StateClassificationFlag_Boot
) {
168 hwmgr
->boot_ps
= state
;
169 hwmgr
->current_ps
= hwmgr
->request_ps
= state
;
172 state
->id
= i
+ 1; /* assigned unique num for every power state id */
174 if (state
->classification
.flags
& PP_StateClassificationFlag_Uvd
)
175 hwmgr
->uvd_ps
= state
;
176 state
= (struct pp_power_state
*)((unsigned long)state
+ size
);
184 * Returns once the part of the register indicated by the mask has
185 * reached the given value.
187 int phm_wait_on_register(struct pp_hwmgr
*hwmgr
, uint32_t index
,
188 uint32_t value
, uint32_t mask
)
193 if (hwmgr
== NULL
|| hwmgr
->device
== NULL
) {
194 printk(KERN_ERR
"[ powerplay ] Invalid Hardware Manager!");
198 for (i
= 0; i
< hwmgr
->usec_timeout
; i
++) {
199 cur_value
= cgs_read_register(hwmgr
->device
, index
);
200 if ((cur_value
& mask
) == (value
& mask
))
205 /* timeout means wrong logic*/
206 if (i
== hwmgr
->usec_timeout
)
215 * Returns once the part of the register indicated by the mask has
216 * reached the given value.The indirect space is described by giving
217 * the memory-mapped index of the indirect index register.
219 void phm_wait_on_indirect_register(struct pp_hwmgr
*hwmgr
,
220 uint32_t indirect_port
,
225 if (hwmgr
== NULL
|| hwmgr
->device
== NULL
) {
226 printk(KERN_ERR
"[ powerplay ] Invalid Hardware Manager!");
230 cgs_write_register(hwmgr
->device
, indirect_port
, index
);
231 phm_wait_on_register(hwmgr
, indirect_port
+ 1, mask
, value
);
236 bool phm_cf_want_uvd_power_gating(struct pp_hwmgr
*hwmgr
)
238 return phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
, PHM_PlatformCaps_UVDPowerGating
);
241 bool phm_cf_want_vce_power_gating(struct pp_hwmgr
*hwmgr
)
243 return phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
, PHM_PlatformCaps_VCEPowerGating
);
247 int phm_trim_voltage_table(struct pp_atomctrl_voltage_table
*vol_table
)
252 struct pp_atomctrl_voltage_table
*table
;
254 PP_ASSERT_WITH_CODE((NULL
!= vol_table
),
255 "Voltage Table empty.", return -EINVAL
);
257 table
= kzalloc(sizeof(struct pp_atomctrl_voltage_table
),
263 table
->mask_low
= vol_table
->mask_low
;
264 table
->phase_delay
= vol_table
->phase_delay
;
266 for (i
= 0; i
< vol_table
->count
; i
++) {
267 vvalue
= vol_table
->entries
[i
].value
;
270 for (j
= 0; j
< table
->count
; j
++) {
271 if (vvalue
== table
->entries
[j
].value
) {
278 table
->entries
[table
->count
].value
= vvalue
;
279 table
->entries
[table
->count
].smio_low
=
280 vol_table
->entries
[i
].smio_low
;
285 memcpy(vol_table
, table
, sizeof(struct pp_atomctrl_voltage_table
));
291 int phm_get_svi2_mvdd_voltage_table(struct pp_atomctrl_voltage_table
*vol_table
,
292 phm_ppt_v1_clock_voltage_dependency_table
*dep_table
)
297 PP_ASSERT_WITH_CODE((0 != dep_table
->count
),
298 "Voltage Dependency Table empty.", return -EINVAL
);
300 PP_ASSERT_WITH_CODE((NULL
!= vol_table
),
301 "vol_table empty.", return -EINVAL
);
303 vol_table
->mask_low
= 0;
304 vol_table
->phase_delay
= 0;
305 vol_table
->count
= dep_table
->count
;
307 for (i
= 0; i
< dep_table
->count
; i
++) {
308 vol_table
->entries
[i
].value
= dep_table
->entries
[i
].mvdd
;
309 vol_table
->entries
[i
].smio_low
= 0;
312 result
= phm_trim_voltage_table(vol_table
);
313 PP_ASSERT_WITH_CODE((0 == result
),
314 "Failed to trim MVDD table.", return result
);
319 int phm_get_svi2_vddci_voltage_table(struct pp_atomctrl_voltage_table
*vol_table
,
320 phm_ppt_v1_clock_voltage_dependency_table
*dep_table
)
325 PP_ASSERT_WITH_CODE((0 != dep_table
->count
),
326 "Voltage Dependency Table empty.", return -EINVAL
);
328 PP_ASSERT_WITH_CODE((NULL
!= vol_table
),
329 "vol_table empty.", return -EINVAL
);
331 vol_table
->mask_low
= 0;
332 vol_table
->phase_delay
= 0;
333 vol_table
->count
= dep_table
->count
;
335 for (i
= 0; i
< dep_table
->count
; i
++) {
336 vol_table
->entries
[i
].value
= dep_table
->entries
[i
].vddci
;
337 vol_table
->entries
[i
].smio_low
= 0;
340 result
= phm_trim_voltage_table(vol_table
);
341 PP_ASSERT_WITH_CODE((0 == result
),
342 "Failed to trim VDDCI table.", return result
);
347 int phm_get_svi2_vdd_voltage_table(struct pp_atomctrl_voltage_table
*vol_table
,
348 phm_ppt_v1_voltage_lookup_table
*lookup_table
)
352 PP_ASSERT_WITH_CODE((0 != lookup_table
->count
),
353 "Voltage Lookup Table empty.", return -EINVAL
);
355 PP_ASSERT_WITH_CODE((NULL
!= vol_table
),
356 "vol_table empty.", return -EINVAL
);
358 vol_table
->mask_low
= 0;
359 vol_table
->phase_delay
= 0;
361 vol_table
->count
= lookup_table
->count
;
363 for (i
= 0; i
< vol_table
->count
; i
++) {
364 vol_table
->entries
[i
].value
= lookup_table
->entries
[i
].us_vdd
;
365 vol_table
->entries
[i
].smio_low
= 0;
371 void phm_trim_voltage_table_to_fit_state_table(uint32_t max_vol_steps
,
372 struct pp_atomctrl_voltage_table
*vol_table
)
374 unsigned int i
, diff
;
376 if (vol_table
->count
<= max_vol_steps
)
379 diff
= vol_table
->count
- max_vol_steps
;
381 for (i
= 0; i
< max_vol_steps
; i
++)
382 vol_table
->entries
[i
] = vol_table
->entries
[i
+ diff
];
384 vol_table
->count
= max_vol_steps
;
389 int phm_reset_single_dpm_table(void *table
,
390 uint32_t count
, int max
)
394 struct vi_dpm_table
*dpm_table
= (struct vi_dpm_table
*)table
;
396 PP_ASSERT_WITH_CODE(count
<= max
,
397 "Fatal error, can not set up single DPM table entries to exceed max number!",
400 dpm_table
->count
= count
;
401 for (i
= 0; i
< max
; i
++)
402 dpm_table
->dpm_level
[i
].enabled
= false;
407 void phm_setup_pcie_table_entry(
409 uint32_t index
, uint32_t pcie_gen
,
412 struct vi_dpm_table
*dpm_table
= (struct vi_dpm_table
*)table
;
413 dpm_table
->dpm_level
[index
].value
= pcie_gen
;
414 dpm_table
->dpm_level
[index
].param1
= pcie_lanes
;
415 dpm_table
->dpm_level
[index
].enabled
= 1;
418 int32_t phm_get_dpm_level_enable_mask_value(void *table
)
422 struct vi_dpm_table
*dpm_table
= (struct vi_dpm_table
*)table
;
424 for (i
= dpm_table
->count
; i
> 0; i
--) {
426 if (dpm_table
->dpm_level
[i
- 1].enabled
)
435 uint8_t phm_get_voltage_index(
436 struct phm_ppt_v1_voltage_lookup_table
*lookup_table
, uint16_t voltage
)
438 uint8_t count
= (uint8_t) (lookup_table
->count
);
441 PP_ASSERT_WITH_CODE((NULL
!= lookup_table
),
442 "Lookup Table empty.", return 0);
443 PP_ASSERT_WITH_CODE((0 != count
),
444 "Lookup Table empty.", return 0);
446 for (i
= 0; i
< lookup_table
->count
; i
++) {
447 /* find first voltage equal or bigger than requested */
448 if (lookup_table
->entries
[i
].us_vdd
>= voltage
)
451 /* voltage is bigger than max voltage in the table */
455 uint16_t phm_find_closest_vddci(struct pp_atomctrl_voltage_table
*vddci_table
, uint16_t vddci
)
459 for (i
= 0; i
< vddci_table
->count
; i
++) {
460 if (vddci_table
->entries
[i
].value
>= vddci
)
461 return vddci_table
->entries
[i
].value
;
464 PP_ASSERT_WITH_CODE(false,
465 "VDDCI is larger than max VDDCI in VDDCI Voltage Table!",
466 return vddci_table
->entries
[i
-1].value
);
469 int phm_find_boot_level(void *table
,
470 uint32_t value
, uint32_t *boot_level
)
472 int result
= -EINVAL
;
474 struct vi_dpm_table
*dpm_table
= (struct vi_dpm_table
*)table
;
476 for (i
= 0; i
< dpm_table
->count
; i
++) {
477 if (value
== dpm_table
->dpm_level
[i
].value
) {
486 int phm_get_sclk_for_voltage_evv(struct pp_hwmgr
*hwmgr
,
487 phm_ppt_v1_voltage_lookup_table
*lookup_table
,
488 uint16_t virtual_voltage_id
, int32_t *sclk
)
492 struct phm_ppt_v1_information
*table_info
=
493 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
495 PP_ASSERT_WITH_CODE(lookup_table
->count
!= 0, "Lookup table is empty", return -EINVAL
);
497 /* search for leakage voltage ID 0xff01 ~ 0xff08 and sckl */
498 for (entryId
= 0; entryId
< table_info
->vdd_dep_on_sclk
->count
; entryId
++) {
499 voltageId
= table_info
->vdd_dep_on_sclk
->entries
[entryId
].vddInd
;
500 if (lookup_table
->entries
[voltageId
].us_vdd
== virtual_voltage_id
)
504 PP_ASSERT_WITH_CODE(entryId
< table_info
->vdd_dep_on_sclk
->count
,
505 "Can't find requested voltage id in vdd_dep_on_sclk table!",
509 *sclk
= table_info
->vdd_dep_on_sclk
->entries
[entryId
].clk
;
515 * Initialize Dynamic State Adjustment Rule Settings
517 * @param hwmgr the address of the powerplay hardware manager.
519 int phm_initializa_dynamic_state_adjustment_rule_settings(struct pp_hwmgr
*hwmgr
)
522 struct phm_clock_voltage_dependency_table
*table_clk_vlt
;
523 struct phm_ppt_v1_information
*pptable_info
= (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
525 /* initialize vddc_dep_on_dal_pwrl table */
526 table_size
= sizeof(uint32_t) + 4 * sizeof(struct phm_clock_voltage_dependency_record
);
527 table_clk_vlt
= kzalloc(table_size
, GFP_KERNEL
);
529 if (NULL
== table_clk_vlt
) {
530 printk(KERN_ERR
"[ powerplay ] Can not allocate space for vddc_dep_on_dal_pwrl! \n");
533 table_clk_vlt
->count
= 4;
534 table_clk_vlt
->entries
[0].clk
= PP_DAL_POWERLEVEL_ULTRALOW
;
535 table_clk_vlt
->entries
[0].v
= 0;
536 table_clk_vlt
->entries
[1].clk
= PP_DAL_POWERLEVEL_LOW
;
537 table_clk_vlt
->entries
[1].v
= 720;
538 table_clk_vlt
->entries
[2].clk
= PP_DAL_POWERLEVEL_NOMINAL
;
539 table_clk_vlt
->entries
[2].v
= 810;
540 table_clk_vlt
->entries
[3].clk
= PP_DAL_POWERLEVEL_PERFORMANCE
;
541 table_clk_vlt
->entries
[3].v
= 900;
542 pptable_info
->vddc_dep_on_dal_pwrl
= table_clk_vlt
;
543 hwmgr
->dyn_state
.vddc_dep_on_dal_pwrl
= table_clk_vlt
;
549 int phm_hwmgr_backend_fini(struct pp_hwmgr
*hwmgr
)
551 if (NULL
!= hwmgr
->dyn_state
.vddc_dep_on_dal_pwrl
) {
552 kfree(hwmgr
->dyn_state
.vddc_dep_on_dal_pwrl
);
553 hwmgr
->dyn_state
.vddc_dep_on_dal_pwrl
= NULL
;
556 if (NULL
!= hwmgr
->backend
) {
557 kfree(hwmgr
->backend
);
558 hwmgr
->backend
= NULL
;
564 uint32_t phm_get_lowest_enabled_level(struct pp_hwmgr
*hwmgr
, uint32_t mask
)
568 while (0 == (mask
& (1 << level
)))
574 void phm_apply_dal_min_voltage_request(struct pp_hwmgr
*hwmgr
)
576 struct phm_ppt_v1_information
*table_info
=
577 (struct phm_ppt_v1_information
*)hwmgr
->pptable
;
578 struct phm_clock_voltage_dependency_table
*table
=
579 table_info
->vddc_dep_on_dal_pwrl
;
580 struct phm_ppt_v1_clock_voltage_dependency_table
*vddc_table
;
581 enum PP_DAL_POWERLEVEL dal_power_level
= hwmgr
->dal_power_level
;
582 uint32_t req_vddc
= 0, req_volt
, i
;
584 if (!table
|| table
->count
<= 0
585 || dal_power_level
< PP_DAL_POWERLEVEL_ULTRALOW
586 || dal_power_level
> PP_DAL_POWERLEVEL_PERFORMANCE
)
589 for (i
= 0; i
< table
->count
; i
++) {
590 if (dal_power_level
== table
->entries
[i
].clk
) {
591 req_vddc
= table
->entries
[i
].v
;
596 vddc_table
= table_info
->vdd_dep_on_sclk
;
597 for (i
= 0; i
< vddc_table
->count
; i
++) {
598 if (req_vddc
<= vddc_table
->entries
[i
].vddc
) {
599 req_volt
= (((uint32_t)vddc_table
->entries
[i
].vddc
) * VOLTAGE_SCALE
);
600 smum_send_msg_to_smc_with_parameter(hwmgr
->smumgr
,
601 PPSMC_MSG_VddC_Request
, req_volt
);
605 printk(KERN_ERR
"DAL requested level can not"
606 " found a available voltage in VDDC DPM Table \n");