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);
43 int hwmgr_init(struct amd_pp_init *pp_init, struct pp_instance *handle)
45 struct pp_hwmgr *hwmgr;
47 if ((handle == NULL) || (pp_init == NULL))
50 hwmgr = kzalloc(sizeof(struct pp_hwmgr), GFP_KERNEL);
54 handle->hwmgr = hwmgr;
55 hwmgr->smumgr = handle->smu_mgr;
56 hwmgr->device = pp_init->device;
57 hwmgr->chip_family = pp_init->chip_family;
58 hwmgr->chip_id = pp_init->chip_id;
59 hwmgr->hw_revision = pp_init->rev_id;
60 hwmgr->usec_timeout = AMD_MAX_USEC_TIMEOUT;
61 hwmgr->power_source = PP_PowerSource_AC;
62 hwmgr->powercontainment_enabled = pp_init->powercontainment_enabled;
64 switch (hwmgr->chip_family) {
65 case AMDGPU_FAMILY_CZ:
68 case AMDGPU_FAMILY_VI:
69 switch (hwmgr->chip_id) {
71 tonga_hwmgr_init(hwmgr);
74 fiji_hwmgr_init(hwmgr);
78 polaris10_hwmgr_init(hwmgr);
88 phm_init_dynamic_caps(hwmgr);
93 int hwmgr_fini(struct pp_hwmgr *hwmgr)
95 if (hwmgr == NULL || hwmgr->ps == NULL)
99 kfree(hwmgr->hardcode_pp_table);
101 kfree(hwmgr->backend);
103 kfree(hwmgr->start_thermal_controller.function_list);
105 kfree(hwmgr->set_temperature_range.function_list);
112 int hw_init_power_state_table(struct pp_hwmgr *hwmgr)
116 unsigned int table_entries;
117 struct pp_power_state *state;
120 if (hwmgr->hwmgr_func->get_num_of_pp_table_entries == NULL)
123 if (hwmgr->hwmgr_func->get_power_state_size == NULL)
126 hwmgr->num_ps = table_entries = hwmgr->hwmgr_func->get_num_of_pp_table_entries(hwmgr);
128 hwmgr->ps_size = size = hwmgr->hwmgr_func->get_power_state_size(hwmgr) +
129 sizeof(struct pp_power_state);
131 hwmgr->ps = kzalloc(size * table_entries, GFP_KERNEL);
133 if (hwmgr->ps == NULL)
138 for (i = 0; i < table_entries; i++) {
139 result = hwmgr->hwmgr_func->get_pp_table_entry(hwmgr, i, state);
141 if (state->classification.flags & PP_StateClassificationFlag_Boot) {
142 hwmgr->boot_ps = state;
143 hwmgr->current_ps = hwmgr->request_ps = state;
146 state->id = i + 1; /* assigned unique num for every power state id */
148 if (state->classification.flags & PP_StateClassificationFlag_Uvd)
149 hwmgr->uvd_ps = state;
150 state = (struct pp_power_state *)((unsigned long)state + size);
158 * Returns once the part of the register indicated by the mask has
159 * reached the given value.
161 int phm_wait_on_register(struct pp_hwmgr *hwmgr, uint32_t index,
162 uint32_t value, uint32_t mask)
167 if (hwmgr == NULL || hwmgr->device == NULL) {
168 printk(KERN_ERR "[ powerplay ] Invalid Hardware Manager!");
172 for (i = 0; i < hwmgr->usec_timeout; i++) {
173 cur_value = cgs_read_register(hwmgr->device, index);
174 if ((cur_value & mask) == (value & mask))
179 /* timeout means wrong logic*/
180 if (i == hwmgr->usec_timeout)
185 int phm_wait_for_register_unequal(struct pp_hwmgr *hwmgr,
186 uint32_t index, uint32_t value, uint32_t mask)
191 if (hwmgr == NULL || hwmgr->device == NULL) {
192 printk(KERN_ERR "[ powerplay ] Invalid Hardware Manager!");
196 for (i = 0; i < hwmgr->usec_timeout; i++) {
197 cur_value = cgs_read_register(hwmgr->device, index);
198 if ((cur_value & mask) != (value & mask))
203 /* timeout means wrong logic*/
204 if (i == hwmgr->usec_timeout)
211 * Returns once the part of the register indicated by the mask has
212 * reached the given value.The indirect space is described by giving
213 * the memory-mapped index of the indirect index register.
215 void phm_wait_on_indirect_register(struct pp_hwmgr *hwmgr,
216 uint32_t indirect_port,
221 if (hwmgr == NULL || hwmgr->device == NULL) {
222 printk(KERN_ERR "[ powerplay ] Invalid Hardware Manager!");
226 cgs_write_register(hwmgr->device, indirect_port, index);
227 phm_wait_on_register(hwmgr, indirect_port + 1, mask, value);
230 void phm_wait_for_indirect_register_unequal(struct pp_hwmgr *hwmgr,
231 uint32_t indirect_port,
236 if (hwmgr == NULL || hwmgr->device == NULL) {
237 printk(KERN_ERR "[ powerplay ] Invalid Hardware Manager!");
241 cgs_write_register(hwmgr->device, indirect_port, index);
242 phm_wait_for_register_unequal(hwmgr, indirect_port + 1,
246 bool phm_cf_want_uvd_power_gating(struct pp_hwmgr *hwmgr)
248 return phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_UVDPowerGating);
251 bool phm_cf_want_vce_power_gating(struct pp_hwmgr *hwmgr)
253 return phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_VCEPowerGating);
257 int phm_trim_voltage_table(struct pp_atomctrl_voltage_table *vol_table)
262 struct pp_atomctrl_voltage_table *table;
264 PP_ASSERT_WITH_CODE((NULL != vol_table),
265 "Voltage Table empty.", return -EINVAL);
267 table = kzalloc(sizeof(struct pp_atomctrl_voltage_table),
273 table->mask_low = vol_table->mask_low;
274 table->phase_delay = vol_table->phase_delay;
276 for (i = 0; i < vol_table->count; i++) {
277 vvalue = vol_table->entries[i].value;
280 for (j = 0; j < table->count; j++) {
281 if (vvalue == table->entries[j].value) {
288 table->entries[table->count].value = vvalue;
289 table->entries[table->count].smio_low =
290 vol_table->entries[i].smio_low;
295 memcpy(vol_table, table, sizeof(struct pp_atomctrl_voltage_table));
301 int phm_get_svi2_mvdd_voltage_table(struct pp_atomctrl_voltage_table *vol_table,
302 phm_ppt_v1_clock_voltage_dependency_table *dep_table)
307 PP_ASSERT_WITH_CODE((0 != dep_table->count),
308 "Voltage Dependency Table empty.", return -EINVAL);
310 PP_ASSERT_WITH_CODE((NULL != vol_table),
311 "vol_table empty.", return -EINVAL);
313 vol_table->mask_low = 0;
314 vol_table->phase_delay = 0;
315 vol_table->count = dep_table->count;
317 for (i = 0; i < dep_table->count; i++) {
318 vol_table->entries[i].value = dep_table->entries[i].mvdd;
319 vol_table->entries[i].smio_low = 0;
322 result = phm_trim_voltage_table(vol_table);
323 PP_ASSERT_WITH_CODE((0 == result),
324 "Failed to trim MVDD table.", return result);
329 int phm_get_svi2_vddci_voltage_table(struct pp_atomctrl_voltage_table *vol_table,
330 phm_ppt_v1_clock_voltage_dependency_table *dep_table)
335 PP_ASSERT_WITH_CODE((0 != dep_table->count),
336 "Voltage Dependency Table empty.", return -EINVAL);
338 PP_ASSERT_WITH_CODE((NULL != vol_table),
339 "vol_table empty.", return -EINVAL);
341 vol_table->mask_low = 0;
342 vol_table->phase_delay = 0;
343 vol_table->count = dep_table->count;
345 for (i = 0; i < dep_table->count; i++) {
346 vol_table->entries[i].value = dep_table->entries[i].vddci;
347 vol_table->entries[i].smio_low = 0;
350 result = phm_trim_voltage_table(vol_table);
351 PP_ASSERT_WITH_CODE((0 == result),
352 "Failed to trim VDDCI table.", return result);
357 int phm_get_svi2_vdd_voltage_table(struct pp_atomctrl_voltage_table *vol_table,
358 phm_ppt_v1_voltage_lookup_table *lookup_table)
362 PP_ASSERT_WITH_CODE((0 != lookup_table->count),
363 "Voltage Lookup Table empty.", return -EINVAL);
365 PP_ASSERT_WITH_CODE((NULL != vol_table),
366 "vol_table empty.", return -EINVAL);
368 vol_table->mask_low = 0;
369 vol_table->phase_delay = 0;
371 vol_table->count = lookup_table->count;
373 for (i = 0; i < vol_table->count; i++) {
374 vol_table->entries[i].value = lookup_table->entries[i].us_vdd;
375 vol_table->entries[i].smio_low = 0;
381 void phm_trim_voltage_table_to_fit_state_table(uint32_t max_vol_steps,
382 struct pp_atomctrl_voltage_table *vol_table)
384 unsigned int i, diff;
386 if (vol_table->count <= max_vol_steps)
389 diff = vol_table->count - max_vol_steps;
391 for (i = 0; i < max_vol_steps; i++)
392 vol_table->entries[i] = vol_table->entries[i + diff];
394 vol_table->count = max_vol_steps;
399 int phm_reset_single_dpm_table(void *table,
400 uint32_t count, int max)
404 struct vi_dpm_table *dpm_table = (struct vi_dpm_table *)table;
406 PP_ASSERT_WITH_CODE(count <= max,
407 "Fatal error, can not set up single DPM table entries to exceed max number!",
410 dpm_table->count = count;
411 for (i = 0; i < max; i++)
412 dpm_table->dpm_level[i].enabled = false;
417 void phm_setup_pcie_table_entry(
419 uint32_t index, uint32_t pcie_gen,
422 struct vi_dpm_table *dpm_table = (struct vi_dpm_table *)table;
423 dpm_table->dpm_level[index].value = pcie_gen;
424 dpm_table->dpm_level[index].param1 = pcie_lanes;
425 dpm_table->dpm_level[index].enabled = 1;
428 int32_t phm_get_dpm_level_enable_mask_value(void *table)
432 struct vi_dpm_table *dpm_table = (struct vi_dpm_table *)table;
434 for (i = dpm_table->count; i > 0; i--) {
436 if (dpm_table->dpm_level[i - 1].enabled)
445 uint8_t phm_get_voltage_index(
446 struct phm_ppt_v1_voltage_lookup_table *lookup_table, uint16_t voltage)
448 uint8_t count = (uint8_t) (lookup_table->count);
451 PP_ASSERT_WITH_CODE((NULL != lookup_table),
452 "Lookup Table empty.", return 0);
453 PP_ASSERT_WITH_CODE((0 != count),
454 "Lookup Table empty.", return 0);
456 for (i = 0; i < lookup_table->count; i++) {
457 /* find first voltage equal or bigger than requested */
458 if (lookup_table->entries[i].us_vdd >= voltage)
461 /* voltage is bigger than max voltage in the table */
465 uint16_t phm_find_closest_vddci(struct pp_atomctrl_voltage_table *vddci_table, uint16_t vddci)
469 for (i = 0; i < vddci_table->count; i++) {
470 if (vddci_table->entries[i].value >= vddci)
471 return vddci_table->entries[i].value;
474 PP_ASSERT_WITH_CODE(false,
475 "VDDCI is larger than max VDDCI in VDDCI Voltage Table!",
476 return vddci_table->entries[i-1].value);
479 int phm_find_boot_level(void *table,
480 uint32_t value, uint32_t *boot_level)
482 int result = -EINVAL;
484 struct vi_dpm_table *dpm_table = (struct vi_dpm_table *)table;
486 for (i = 0; i < dpm_table->count; i++) {
487 if (value == dpm_table->dpm_level[i].value) {
496 int phm_get_sclk_for_voltage_evv(struct pp_hwmgr *hwmgr,
497 phm_ppt_v1_voltage_lookup_table *lookup_table,
498 uint16_t virtual_voltage_id, int32_t *sclk)
502 struct phm_ppt_v1_information *table_info =
503 (struct phm_ppt_v1_information *)(hwmgr->pptable);
505 PP_ASSERT_WITH_CODE(lookup_table->count != 0, "Lookup table is empty", return -EINVAL);
507 /* search for leakage voltage ID 0xff01 ~ 0xff08 and sckl */
508 for (entryId = 0; entryId < table_info->vdd_dep_on_sclk->count; entryId++) {
509 voltageId = table_info->vdd_dep_on_sclk->entries[entryId].vddInd;
510 if (lookup_table->entries[voltageId].us_vdd == virtual_voltage_id)
514 PP_ASSERT_WITH_CODE(entryId < table_info->vdd_dep_on_sclk->count,
515 "Can't find requested voltage id in vdd_dep_on_sclk table!",
519 *sclk = table_info->vdd_dep_on_sclk->entries[entryId].clk;
525 * Initialize Dynamic State Adjustment Rule Settings
527 * @param hwmgr the address of the powerplay hardware manager.
529 int phm_initializa_dynamic_state_adjustment_rule_settings(struct pp_hwmgr *hwmgr)
532 struct phm_clock_voltage_dependency_table *table_clk_vlt;
533 struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
535 /* initialize vddc_dep_on_dal_pwrl table */
536 table_size = sizeof(uint32_t) + 4 * sizeof(struct phm_clock_voltage_dependency_record);
537 table_clk_vlt = kzalloc(table_size, GFP_KERNEL);
539 if (NULL == table_clk_vlt) {
540 printk(KERN_ERR "[ powerplay ] Can not allocate space for vddc_dep_on_dal_pwrl! \n");
543 table_clk_vlt->count = 4;
544 table_clk_vlt->entries[0].clk = PP_DAL_POWERLEVEL_ULTRALOW;
545 table_clk_vlt->entries[0].v = 0;
546 table_clk_vlt->entries[1].clk = PP_DAL_POWERLEVEL_LOW;
547 table_clk_vlt->entries[1].v = 720;
548 table_clk_vlt->entries[2].clk = PP_DAL_POWERLEVEL_NOMINAL;
549 table_clk_vlt->entries[2].v = 810;
550 table_clk_vlt->entries[3].clk = PP_DAL_POWERLEVEL_PERFORMANCE;
551 table_clk_vlt->entries[3].v = 900;
552 pptable_info->vddc_dep_on_dal_pwrl = table_clk_vlt;
553 hwmgr->dyn_state.vddc_dep_on_dal_pwrl = table_clk_vlt;
559 int phm_hwmgr_backend_fini(struct pp_hwmgr *hwmgr)
561 if (NULL != hwmgr->dyn_state.vddc_dep_on_dal_pwrl) {
562 kfree(hwmgr->dyn_state.vddc_dep_on_dal_pwrl);
563 hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL;
566 if (NULL != hwmgr->backend) {
567 kfree(hwmgr->backend);
568 hwmgr->backend = NULL;
574 uint32_t phm_get_lowest_enabled_level(struct pp_hwmgr *hwmgr, uint32_t mask)
578 while (0 == (mask & (1 << level)))
584 void phm_apply_dal_min_voltage_request(struct pp_hwmgr *hwmgr)
586 struct phm_ppt_v1_information *table_info =
587 (struct phm_ppt_v1_information *)hwmgr->pptable;
588 struct phm_clock_voltage_dependency_table *table =
589 table_info->vddc_dep_on_dal_pwrl;
590 struct phm_ppt_v1_clock_voltage_dependency_table *vddc_table;
591 enum PP_DAL_POWERLEVEL dal_power_level = hwmgr->dal_power_level;
592 uint32_t req_vddc = 0, req_volt, i;
594 if (!table || table->count <= 0
595 || dal_power_level < PP_DAL_POWERLEVEL_ULTRALOW
596 || dal_power_level > PP_DAL_POWERLEVEL_PERFORMANCE)
599 for (i = 0; i < table->count; i++) {
600 if (dal_power_level == table->entries[i].clk) {
601 req_vddc = table->entries[i].v;
606 vddc_table = table_info->vdd_dep_on_sclk;
607 for (i = 0; i < vddc_table->count; i++) {
608 if (req_vddc <= vddc_table->entries[i].vddc) {
609 req_volt = (((uint32_t)vddc_table->entries[i].vddc) * VOLTAGE_SCALE);
610 smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
611 PPSMC_MSG_VddC_Request, req_volt);
615 printk(KERN_ERR "DAL requested level can not"
616 " found a available voltage in VDDC DPM Table \n");