Merge branch 'drm-etnaviv-next' of git://git.pengutronix.de/git/lst/linux into drm...
[linux-2.6-block.git] / drivers / gpu / drm / amd / powerplay / hwmgr / tonga_hwmgr.c
CommitLineData
c82baa28 1/*
2 * Copyright 2015 Advanced Micro Devices, Inc.
3 *
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:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
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.
21 *
22 */
23#include <linux/module.h>
24#include <linux/slab.h>
c82baa28 25#include "linux/delay.h"
26#include "pp_acpi.h"
27#include "hwmgr.h"
28#include <atombios.h>
29#include "tonga_hwmgr.h"
30#include "pptable.h"
31#include "processpptables.h"
e1aa5715
RZ
32#include "process_pptables_v1_0.h"
33#include "pptable_v1_0.h"
c82baa28 34#include "pp_debug.h"
35#include "tonga_ppsmc.h"
36#include "cgs_common.h"
37#include "pppcielanes.h"
38#include "tonga_dyn_defaults.h"
39#include "smumgr.h"
40#include "tonga_smumgr.h"
0859ed3d 41#include "tonga_clockpowergating.h"
1e4854e9 42#include "tonga_thermal.h"
c82baa28 43
44#include "smu/smu_7_1_2_d.h"
45#include "smu/smu_7_1_2_sh_mask.h"
46
47#include "gmc/gmc_8_1_d.h"
48#include "gmc/gmc_8_1_sh_mask.h"
49
50#include "bif/bif_5_0_d.h"
51#include "bif/bif_5_0_sh_mask.h"
52
7e8d1fbd
AD
53#include "dce/dce_10_0_d.h"
54#include "dce/dce_10_0_sh_mask.h"
55
1e4854e9
RZ
56#include "cgs_linux.h"
57#include "eventmgr.h"
16881da6 58#include "amd_pcie_helpers.h"
1e4854e9 59
c82baa28 60#define MC_CG_ARB_FREQ_F0 0x0a
61#define MC_CG_ARB_FREQ_F1 0x0b
62#define MC_CG_ARB_FREQ_F2 0x0c
63#define MC_CG_ARB_FREQ_F3 0x0d
64
65#define MC_CG_SEQ_DRAMCONF_S0 0x05
66#define MC_CG_SEQ_DRAMCONF_S1 0x06
67#define MC_CG_SEQ_YCLK_SUSPEND 0x04
68#define MC_CG_SEQ_YCLK_RESUME 0x0a
69
70#define PCIE_BUS_CLK 10000
71#define TCLK (PCIE_BUS_CLK / 10)
72
73#define SMC_RAM_END 0x40000
74#define SMC_CG_IND_START 0xc0030000
75#define SMC_CG_IND_END 0xc0040000 /* First byte after SMC_CG_IND*/
76
77#define VOLTAGE_SCALE 4
78#define VOLTAGE_VID_OFFSET_SCALE1 625
79#define VOLTAGE_VID_OFFSET_SCALE2 100
80
81#define VDDC_VDDCI_DELTA 200
82#define VDDC_VDDGFX_DELTA 300
83
84#define MC_SEQ_MISC0_GDDR5_SHIFT 28
85#define MC_SEQ_MISC0_GDDR5_MASK 0xf0000000
86#define MC_SEQ_MISC0_GDDR5_VALUE 5
87
88typedef uint32_t PECI_RegistryValue;
89
90/* [2.5%,~2.5%] Clock stretched is multiple of 2.5% vs not and [Fmin, Fmax, LDO_REFSEL, USE_FOR_LOW_FREQ] */
f498d9ed 91static const uint16_t PP_ClockStretcherLookupTable[2][4] = {
c82baa28 92 {600, 1050, 3, 0},
93 {600, 1050, 6, 1} };
94
95/* [FF, SS] type, [] 4 voltage ranges, and [Floor Freq, Boundary Freq, VID min , VID max] */
f498d9ed 96static const uint32_t PP_ClockStretcherDDTTable[2][4][4] = {
c82baa28 97 { {265, 529, 120, 128}, {325, 650, 96, 119}, {430, 860, 32, 95}, {0, 0, 0, 31} },
98 { {275, 550, 104, 112}, {319, 638, 96, 103}, {360, 720, 64, 95}, {384, 768, 32, 63} } };
99
100/* [Use_For_Low_freq] value, [0%, 5%, 10%, 7.14%, 14.28%, 20%] (coming from PWR_CKS_CNTL.stretch_amount reg spec) */
f498d9ed 101static const uint8_t PP_ClockStretchAmountConversion[2][6] = {
c82baa28 102 {0, 1, 3, 2, 4, 5},
103 {0, 2, 4, 5, 6, 5} };
104
105/* Values for the CG_THERMAL_CTRL::DPM_EVENT_SRC field. */
106enum DPM_EVENT_SRC {
107 DPM_EVENT_SRC_ANALOG = 0, /* Internal analog trip point */
108 DPM_EVENT_SRC_EXTERNAL = 1, /* External (GPIO 17) signal */
109 DPM_EVENT_SRC_DIGITAL = 2, /* Internal digital trip point (DIG_THERM_DPM) */
110 DPM_EVENT_SRC_ANALOG_OR_EXTERNAL = 3, /* Internal analog or external */
111 DPM_EVENT_SRC_DIGITAL_OR_EXTERNAL = 4 /* Internal digital or external */
112};
113typedef enum DPM_EVENT_SRC DPM_EVENT_SRC;
114
f498d9ed 115static const unsigned long PhwTonga_Magic = (unsigned long)(PHM_VIslands_Magic);
c82baa28 116
117struct tonga_power_state *cast_phw_tonga_power_state(
118 struct pp_hw_power_state *hw_ps)
119{
c15c8d70
RZ
120 if (hw_ps == NULL)
121 return NULL;
122
c82baa28 123 PP_ASSERT_WITH_CODE((PhwTonga_Magic == hw_ps->magic),
124 "Invalid Powerstate Type!",
c15c8d70 125 return NULL);
c82baa28 126
127 return (struct tonga_power_state *)hw_ps;
128}
129
130const struct tonga_power_state *cast_const_phw_tonga_power_state(
131 const struct pp_hw_power_state *hw_ps)
132{
c15c8d70
RZ
133 if (hw_ps == NULL)
134 return NULL;
135
c82baa28 136 PP_ASSERT_WITH_CODE((PhwTonga_Magic == hw_ps->magic),
137 "Invalid Powerstate Type!",
c15c8d70 138 return NULL);
c82baa28 139
140 return (const struct tonga_power_state *)hw_ps;
141}
142
143int tonga_add_voltage(struct pp_hwmgr *hwmgr,
144 phm_ppt_v1_voltage_lookup_table *look_up_table,
145 phm_ppt_v1_voltage_lookup_record *record)
146{
147 uint32_t i;
148 PP_ASSERT_WITH_CODE((NULL != look_up_table),
149 "Lookup Table empty.", return -1;);
150 PP_ASSERT_WITH_CODE((0 != look_up_table->count),
151 "Lookup Table empty.", return -1;);
152 PP_ASSERT_WITH_CODE((SMU72_MAX_LEVELS_VDDGFX >= look_up_table->count),
153 "Lookup Table is full.", return -1;);
154
155 /* This is to avoid entering duplicate calculated records. */
156 for (i = 0; i < look_up_table->count; i++) {
157 if (look_up_table->entries[i].us_vdd == record->us_vdd) {
158 if (look_up_table->entries[i].us_calculated == 1)
159 return 0;
160 else
161 break;
162 }
163 }
164
165 look_up_table->entries[i].us_calculated = 1;
166 look_up_table->entries[i].us_vdd = record->us_vdd;
167 look_up_table->entries[i].us_cac_low = record->us_cac_low;
168 look_up_table->entries[i].us_cac_mid = record->us_cac_mid;
169 look_up_table->entries[i].us_cac_high = record->us_cac_high;
170 /* Only increment the count when we're appending, not replacing duplicate entry. */
171 if (i == look_up_table->count)
172 look_up_table->count++;
173
174 return 0;
175}
176
bbb207f3
RZ
177int tonga_notify_smc_display_change(struct pp_hwmgr *hwmgr, bool has_display)
178{
179 PPSMC_Msg msg = has_display? (PPSMC_Msg)PPSMC_HasDisplay : (PPSMC_Msg)PPSMC_NoDisplay;
180
181 return (smum_send_msg_to_smc(hwmgr->smumgr, msg) == 0) ? 0 : -1;
182}
183
c82baa28 184uint8_t tonga_get_voltage_id(pp_atomctrl_voltage_table *voltage_table,
185 uint32_t voltage)
186{
187 uint8_t count = (uint8_t) (voltage_table->count);
188 uint8_t i = 0;
189
190 PP_ASSERT_WITH_CODE((NULL != voltage_table),
191 "Voltage Table empty.", return 0;);
192 PP_ASSERT_WITH_CODE((0 != count),
193 "Voltage Table empty.", return 0;);
194
195 for (i = 0; i < count; i++) {
196 /* find first voltage bigger than requested */
197 if (voltage_table->entries[i].value >= voltage)
198 return i;
199 }
200
201 /* voltage is bigger than max voltage in the table */
202 return i - 1;
203}
204
2377cd94 205
c82baa28 206/**
207 * @brief PhwTonga_GetVoltageOrder
208 * Returns index of requested voltage record in lookup(table)
209 * @param hwmgr - pointer to hardware manager
210 * @param lookupTable - lookup list to search in
211 * @param voltage - voltage to look for
212 * @return 0 on success
213 */
214uint8_t tonga_get_voltage_index(phm_ppt_v1_voltage_lookup_table *look_up_table,
215 uint16_t voltage)
216{
217 uint8_t count = (uint8_t) (look_up_table->count);
218 uint8_t i;
219
220 PP_ASSERT_WITH_CODE((NULL != look_up_table), "Lookup Table empty.", return 0;);
221 PP_ASSERT_WITH_CODE((0 != count), "Lookup Table empty.", return 0;);
222
223 for (i = 0; i < count; i++) {
224 /* find first voltage equal or bigger than requested */
225 if (look_up_table->entries[i].us_vdd >= voltage)
226 return i;
227 }
228
229 /* voltage is bigger than max voltage in the table */
230 return i-1;
231}
232
c63e2d4c 233static bool tonga_is_dpm_running(struct pp_hwmgr *hwmgr)
c82baa28 234{
235 /*
236 * We return the status of Voltage Control instead of checking SCLK/MCLK DPM
237 * because we may have test scenarios that need us intentionly disable SCLK/MCLK DPM,
238 * whereas voltage control is a fundemental change that will not be disabled
239 */
240
241 return (0 == PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
242 FEATURE_STATUS, VOLTAGE_CONTROLLER_ON) ? 1 : 0);
243}
244
245/**
246 * Re-generate the DPM level mask value
247 * @param hwmgr the address of the hardware manager
248 */
249static uint32_t tonga_get_dpm_level_enable_mask_value(
250 struct tonga_single_dpm_table * dpm_table)
251{
252 uint32_t i;
253 uint32_t mask_value = 0;
254
255 for (i = dpm_table->count; i > 0; i--) {
256 mask_value = mask_value << 1;
257
258 if (dpm_table->dpm_levels[i-1].enabled)
259 mask_value |= 0x1;
260 else
261 mask_value &= 0xFFFFFFFE;
262 }
263 return mask_value;
264}
265
266/**
267 * Retrieve DPM default values from registry (if available)
268 *
269 * @param hwmgr the address of the powerplay hardware manager.
270 */
271void tonga_initialize_dpm_defaults(struct pp_hwmgr *hwmgr)
272{
273 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
274 phw_tonga_ulv_parm *ulv = &(data->ulv);
275 uint32_t tmp;
276
277 ulv->ch_ulv_parameter = PPTONGA_CGULVPARAMETER_DFLT;
278 data->voting_rights_clients0 = PPTONGA_VOTINGRIGHTSCLIENTS_DFLT0;
279 data->voting_rights_clients1 = PPTONGA_VOTINGRIGHTSCLIENTS_DFLT1;
280 data->voting_rights_clients2 = PPTONGA_VOTINGRIGHTSCLIENTS_DFLT2;
281 data->voting_rights_clients3 = PPTONGA_VOTINGRIGHTSCLIENTS_DFLT3;
282 data->voting_rights_clients4 = PPTONGA_VOTINGRIGHTSCLIENTS_DFLT4;
283 data->voting_rights_clients5 = PPTONGA_VOTINGRIGHTSCLIENTS_DFLT5;
284 data->voting_rights_clients6 = PPTONGA_VOTINGRIGHTSCLIENTS_DFLT6;
285 data->voting_rights_clients7 = PPTONGA_VOTINGRIGHTSCLIENTS_DFLT7;
286
287 data->static_screen_threshold_unit = PPTONGA_STATICSCREENTHRESHOLDUNIT_DFLT;
288 data->static_screen_threshold = PPTONGA_STATICSCREENTHRESHOLD_DFLT;
289
290 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
291 PHM_PlatformCaps_ABM);
292 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
293 PHM_PlatformCaps_NonABMSupportInPPLib);
294
295 tmp = 0;
296 if (tmp == 0)
297 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
298 PHM_PlatformCaps_DynamicACTiming);
299
300 tmp = 0;
301 if (0 != tmp)
302 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
303 PHM_PlatformCaps_DisableMemoryTransition);
304
2a702ccd
RZ
305 tonga_initialize_power_tune_defaults(hwmgr);
306
c82baa28 307 data->mclk_strobe_mode_threshold = 40000;
308 data->mclk_stutter_mode_threshold = 30000;
309 data->mclk_edc_enable_threshold = 40000;
310 data->mclk_edc_wr_enable_threshold = 40000;
311
312 tmp = 0;
313 if (tmp != 0)
314 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
315 PHM_PlatformCaps_DisableMCLS);
316
317 data->pcie_gen_performance.max = PP_PCIEGen1;
318 data->pcie_gen_performance.min = PP_PCIEGen3;
319 data->pcie_gen_power_saving.max = PP_PCIEGen1;
320 data->pcie_gen_power_saving.min = PP_PCIEGen3;
321
322 data->pcie_lane_performance.max = 0;
323 data->pcie_lane_performance.min = 16;
324 data->pcie_lane_power_saving.max = 0;
325 data->pcie_lane_power_saving.min = 16;
326
327 tmp = 0;
328
329 if (tmp)
330 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
331 PHM_PlatformCaps_SclkThrottleLowNotification);
332
333 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
334 PHM_PlatformCaps_DynamicUVDState);
335
336}
337
c63e2d4c 338static int tonga_update_sclk_threshold(struct pp_hwmgr *hwmgr)
c82baa28 339{
340 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
341
342 int result = 0;
343 uint32_t low_sclk_interrupt_threshold = 0;
344
345 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
346 PHM_PlatformCaps_SclkThrottleLowNotification)
347 && (hwmgr->gfx_arbiter.sclk_threshold != data->low_sclk_interrupt_threshold)) {
348 data->low_sclk_interrupt_threshold = hwmgr->gfx_arbiter.sclk_threshold;
349 low_sclk_interrupt_threshold = data->low_sclk_interrupt_threshold;
350
351 CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold);
352
353 result = tonga_copy_bytes_to_smc(
354 hwmgr->smumgr,
355 data->dpm_table_start + offsetof(SMU72_Discrete_DpmTable,
356 LowSclkInterruptThreshold),
357 (uint8_t *)&low_sclk_interrupt_threshold,
358 sizeof(uint32_t),
359 data->sram_end
360 );
361 }
362
363 return result;
364}
365
366/**
367 * Find SCLK value that is associated with specified virtual_voltage_Id.
368 *
369 * @param hwmgr the address of the powerplay hardware manager.
370 * @param virtual_voltage_Id voltageId to look for.
371 * @param sclk output value .
372 * @return always 0 if success and 2 if association not found
373 */
374static int tonga_get_sclk_for_voltage_evv(struct pp_hwmgr *hwmgr,
375 phm_ppt_v1_voltage_lookup_table *lookup_table,
376 uint16_t virtual_voltage_id, uint32_t *sclk)
377{
378 uint8_t entryId;
379 uint8_t voltageId;
380 struct phm_ppt_v1_information *pptable_info =
381 (struct phm_ppt_v1_information *)(hwmgr->pptable);
382
383 PP_ASSERT_WITH_CODE(lookup_table->count != 0, "Lookup table is empty", return -1);
384
385 /* search for leakage voltage ID 0xff01 ~ 0xff08 and sckl */
386 for (entryId = 0; entryId < pptable_info->vdd_dep_on_sclk->count; entryId++) {
387 voltageId = pptable_info->vdd_dep_on_sclk->entries[entryId].vddInd;
388 if (lookup_table->entries[voltageId].us_vdd == virtual_voltage_id)
389 break;
390 }
391
392 PP_ASSERT_WITH_CODE(entryId < pptable_info->vdd_dep_on_sclk->count,
393 "Can't find requested voltage id in vdd_dep_on_sclk table!",
394 return -1;
395 );
396
397 *sclk = pptable_info->vdd_dep_on_sclk->entries[entryId].clk;
398
399 return 0;
400}
401
402/**
403 * Get Leakage VDDC based on leakage ID.
404 *
405 * @param hwmgr the address of the powerplay hardware manager.
406 * @return 2 if vddgfx returned is greater than 2V or if BIOS
407 */
408int tonga_get_evv_voltage(struct pp_hwmgr *hwmgr)
409{
410 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
411 struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
412 phm_ppt_v1_clock_voltage_dependency_table *sclk_table = pptable_info->vdd_dep_on_sclk;
413 uint16_t virtual_voltage_id;
414 uint16_t vddc = 0;
415 uint16_t vddgfx = 0;
416 uint16_t i, j;
417 uint32_t sclk = 0;
418
419 /* retrieve voltage for leakage ID (0xff01 + i) */
420 for (i = 0; i < TONGA_MAX_LEAKAGE_COUNT; i++) {
421 virtual_voltage_id = ATOM_VIRTUAL_VOLTAGE_ID0 + i;
422
423 /* in split mode we should have only vddgfx EVV leakages */
424 if (data->vdd_gfx_control == TONGA_VOLTAGE_CONTROL_BY_SVID2) {
425 if (0 == tonga_get_sclk_for_voltage_evv(hwmgr,
426 pptable_info->vddgfx_lookup_table, virtual_voltage_id, &sclk)) {
427 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
428 PHM_PlatformCaps_ClockStretcher)) {
429 for (j = 1; j < sclk_table->count; j++) {
430 if (sclk_table->entries[j].clk == sclk &&
431 sclk_table->entries[j].cks_enable == 0) {
432 sclk += 5000;
433 break;
434 }
435 }
436 }
ac0cc350
MK
437 if (0 == atomctrl_get_voltage_evv_on_sclk
438 (hwmgr, VOLTAGE_TYPE_VDDGFX, sclk,
439 virtual_voltage_id, &vddgfx)) {
440 /* need to make sure vddgfx is less than 2v or else, it could burn the ASIC. */
441 PP_ASSERT_WITH_CODE((vddgfx < 2000 && vddgfx != 0), "Invalid VDDGFX value!", return -1);
442
443 /* the voltage should not be zero nor equal to leakage ID */
444 if (vddgfx != 0 && vddgfx != virtual_voltage_id) {
445 data->vddcgfx_leakage.actual_voltage[data->vddcgfx_leakage.count] = vddgfx;
446 data->vddcgfx_leakage.leakage_id[data->vddcgfx_leakage.count] = virtual_voltage_id;
447 data->vddcgfx_leakage.count++;
448 }
449 } else {
450 printk("Error retrieving EVV voltage value!\n");
c82baa28 451 }
452 }
453 } else {
454 /* in merged mode we have only vddc EVV leakages */
455 if (0 == tonga_get_sclk_for_voltage_evv(hwmgr,
456 pptable_info->vddc_lookup_table,
457 virtual_voltage_id, &sclk)) {
ac0cc350
MK
458 if (0 == atomctrl_get_voltage_evv_on_sclk
459 (hwmgr, VOLTAGE_TYPE_VDDC, sclk,
460 virtual_voltage_id, &vddc)) {
461 /* need to make sure vddc is less than 2v or else, it could burn the ASIC. */
462 PP_ASSERT_WITH_CODE(vddc < 2000, "Invalid VDDC value!", return -1);
463
464 /* the voltage should not be zero nor equal to leakage ID */
465 if (vddc != 0 && vddc != virtual_voltage_id) {
466 data->vddc_leakage.actual_voltage[data->vddc_leakage.count] = vddc;
467 data->vddc_leakage.leakage_id[data->vddc_leakage.count] = virtual_voltage_id;
468 data->vddc_leakage.count++;
469 }
470 } else {
471 printk("Error retrieving EVV voltage value!\n");
c82baa28 472 }
473 }
474 }
475 }
476
477 return 0;
478}
479
480int tonga_enable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr)
481{
482 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
483
484 /* enable SCLK dpm */
485 if (0 == data->sclk_dpm_key_disabled) {
486 PP_ASSERT_WITH_CODE(
487 (0 == smum_send_msg_to_smc(hwmgr->smumgr,
488 PPSMC_MSG_DPM_Enable)),
489 "Failed to enable SCLK DPM during DPM Start Function!",
490 return -1);
491 }
492
493 /* enable MCLK dpm */
494 if (0 == data->mclk_dpm_key_disabled) {
495 PP_ASSERT_WITH_CODE(
496 (0 == smum_send_msg_to_smc(hwmgr->smumgr,
497 PPSMC_MSG_MCLKDPM_Enable)),
498 "Failed to enable MCLK DPM during DPM Start Function!",
499 return -1);
500
501 PHM_WRITE_FIELD(hwmgr->device, MC_SEQ_CNTL_3, CAC_EN, 0x1);
502
503 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
504 ixLCAC_MC0_CNTL, 0x05);/* CH0,1 read */
505 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
506 ixLCAC_MC1_CNTL, 0x05);/* CH2,3 read */
507 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
508 ixLCAC_CPL_CNTL, 0x100005);/*Read */
509
510 udelay(10);
511
512 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
513 ixLCAC_MC0_CNTL, 0x400005);/* CH0,1 write */
514 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
515 ixLCAC_MC1_CNTL, 0x400005);/* CH2,3 write */
516 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
517 ixLCAC_CPL_CNTL, 0x500005);/* write */
518
519 }
520
521 return 0;
522}
523
524int tonga_start_dpm(struct pp_hwmgr *hwmgr)
525{
526 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
527
528 /* enable general power management */
529 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT, GLOBAL_PWRMGT_EN, 1);
530 /* enable sclk deep sleep */
531 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SCLK_PWRMGT_CNTL, DYNAMIC_PM_EN, 1);
532
533 /* prepare for PCIE DPM */
534 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, data->soft_regs_start +
535 offsetof(SMU72_SoftRegisters, VoltageChangeTimeout), 0x1000);
536
537 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__PCIE, SWRST_COMMAND_1, RESETLC, 0x0);
538
539 PP_ASSERT_WITH_CODE(
540 (0 == smum_send_msg_to_smc(hwmgr->smumgr,
541 PPSMC_MSG_Voltage_Cntl_Enable)),
542 "Failed to enable voltage DPM during DPM Start Function!",
543 return -1);
544
545 if (0 != tonga_enable_sclk_mclk_dpm(hwmgr)) {
546 PP_ASSERT_WITH_CODE(0, "Failed to enable Sclk DPM and Mclk DPM!", return -1);
547 }
548
549 /* enable PCIE dpm */
550 if (0 == data->pcie_dpm_key_disabled) {
551 PP_ASSERT_WITH_CODE(
552 (0 == smum_send_msg_to_smc(hwmgr->smumgr,
553 PPSMC_MSG_PCIeDPM_Enable)),
554 "Failed to enable pcie DPM during DPM Start Function!",
555 return -1
556 );
557 }
558
559 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
560 PHM_PlatformCaps_Falcon_QuickTransition)) {
561 smum_send_msg_to_smc(hwmgr->smumgr,
562 PPSMC_MSG_EnableACDCGPIOInterrupt);
563 }
564
565 return 0;
566}
567
568int tonga_disable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr)
569{
570 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
571
572 /* disable SCLK dpm */
573 if (0 == data->sclk_dpm_key_disabled) {
574 /* Checking if DPM is running. If we discover hang because of this, we should skip this message.*/
575 PP_ASSERT_WITH_CODE(
4ba27f9b 576 !tonga_is_dpm_running(hwmgr),
c82baa28 577 "Trying to Disable SCLK DPM when DPM is disabled",
578 return -1
579 );
580
581 PP_ASSERT_WITH_CODE(
582 (0 == smum_send_msg_to_smc(hwmgr->smumgr,
583 PPSMC_MSG_DPM_Disable)),
584 "Failed to disable SCLK DPM during DPM stop Function!",
585 return -1);
586 }
587
588 /* disable MCLK dpm */
589 if (0 == data->mclk_dpm_key_disabled) {
590 /* Checking if DPM is running. If we discover hang because of this, we should skip this message. */
591 PP_ASSERT_WITH_CODE(
4ba27f9b 592 !tonga_is_dpm_running(hwmgr),
c82baa28 593 "Trying to Disable MCLK DPM when DPM is disabled",
594 return -1
595 );
596
597 PP_ASSERT_WITH_CODE(
598 (0 == smum_send_msg_to_smc(hwmgr->smumgr,
599 PPSMC_MSG_MCLKDPM_Disable)),
600 "Failed to Disable MCLK DPM during DPM stop Function!",
601 return -1);
602 }
603
604 return 0;
605}
606
607int tonga_stop_dpm(struct pp_hwmgr *hwmgr)
608{
609 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
610
611 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT, GLOBAL_PWRMGT_EN, 0);
612 /* disable sclk deep sleep*/
613 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SCLK_PWRMGT_CNTL, DYNAMIC_PM_EN, 0);
614
615 /* disable PCIE dpm */
616 if (0 == data->pcie_dpm_key_disabled) {
617 /* Checking if DPM is running. If we discover hang because of this, we should skip this message.*/
618 PP_ASSERT_WITH_CODE(
4ba27f9b 619 !tonga_is_dpm_running(hwmgr),
c82baa28 620 "Trying to Disable PCIE DPM when DPM is disabled",
621 return -1
622 );
623 PP_ASSERT_WITH_CODE(
624 (0 == smum_send_msg_to_smc(hwmgr->smumgr,
625 PPSMC_MSG_PCIeDPM_Disable)),
626 "Failed to disable pcie DPM during DPM stop Function!",
627 return -1);
628 }
629
630 if (0 != tonga_disable_sclk_mclk_dpm(hwmgr))
631 PP_ASSERT_WITH_CODE(0, "Failed to disable Sclk DPM and Mclk DPM!", return -1);
632
633 /* Checking if DPM is running. If we discover hang because of this, we should skip this message.*/
634 PP_ASSERT_WITH_CODE(
4ba27f9b 635 !tonga_is_dpm_running(hwmgr),
c82baa28 636 "Trying to Disable Voltage CNTL when DPM is disabled",
637 return -1
638 );
639
640 PP_ASSERT_WITH_CODE(
641 (0 == smum_send_msg_to_smc(hwmgr->smumgr,
642 PPSMC_MSG_Voltage_Cntl_Disable)),
643 "Failed to disable voltage DPM during DPM stop Function!",
644 return -1);
645
646 return 0;
647}
648
649int tonga_enable_sclk_control(struct pp_hwmgr *hwmgr)
650{
651 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SCLK_PWRMGT_CNTL, SCLK_PWRMGT_OFF, 0);
652
653 return 0;
654}
655
656/**
657 * Send a message to the SMC and return a parameter
658 *
659 * @param hwmgr: the address of the powerplay hardware manager.
660 * @param msg: the message to send.
661 * @param parameter: pointer to the received parameter
662 * @return The response that came from the SMC.
663 */
664PPSMC_Result tonga_send_msg_to_smc_return_parameter(
665 struct pp_hwmgr *hwmgr,
666 PPSMC_Msg msg,
667 uint32_t *parameter)
668{
669 int result;
670
671 result = smum_send_msg_to_smc(hwmgr->smumgr, msg);
672
673 if ((0 == result) && parameter) {
674 *parameter = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0);
675 }
676
677 return result;
678}
679
680/**
681 * force DPM power State
682 *
683 * @param hwmgr: the address of the powerplay hardware manager.
684 * @param n : DPM level
685 * @return The response that came from the SMC.
686 */
687int tonga_dpm_force_state(struct pp_hwmgr *hwmgr, uint32_t n)
688{
689 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
690 uint32_t level_mask = 1 << n;
691
692 /* Checking if DPM is running. If we discover hang because of this, we should skip this message. */
4ba27f9b
EC
693 PP_ASSERT_WITH_CODE(!tonga_is_dpm_running(hwmgr),
694 "Trying to force SCLK when DPM is disabled",
695 return -1;);
c82baa28 696 if (0 == data->sclk_dpm_key_disabled)
697 return (0 == smum_send_msg_to_smc_with_parameter(
698 hwmgr->smumgr,
699 (PPSMC_Msg)(PPSMC_MSG_SCLKDPM_SetEnabledMask),
700 level_mask) ? 0 : 1);
701
702 return 0;
703}
704
705/**
706 * force DPM power State
707 *
708 * @param hwmgr: the address of the powerplay hardware manager.
709 * @param n : DPM level
710 * @return The response that came from the SMC.
711 */
712int tonga_dpm_force_state_mclk(struct pp_hwmgr *hwmgr, uint32_t n)
713{
714 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
715 uint32_t level_mask = 1 << n;
716
717 /* Checking if DPM is running. If we discover hang because of this, we should skip this message. */
4ba27f9b
EC
718 PP_ASSERT_WITH_CODE(!tonga_is_dpm_running(hwmgr),
719 "Trying to Force MCLK when DPM is disabled",
720 return -1;);
c82baa28 721 if (0 == data->mclk_dpm_key_disabled)
722 return (0 == smum_send_msg_to_smc_with_parameter(
723 hwmgr->smumgr,
724 (PPSMC_Msg)(PPSMC_MSG_MCLKDPM_SetEnabledMask),
725 level_mask) ? 0 : 1);
726
727 return 0;
728}
729
730/**
731 * force DPM power State
732 *
733 * @param hwmgr: the address of the powerplay hardware manager.
734 * @param n : DPM level
735 * @return The response that came from the SMC.
736 */
737int tonga_dpm_force_state_pcie(struct pp_hwmgr *hwmgr, uint32_t n)
738{
739 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
740
741 /* Checking if DPM is running. If we discover hang because of this, we should skip this message.*/
4ba27f9b
EC
742 PP_ASSERT_WITH_CODE(!tonga_is_dpm_running(hwmgr),
743 "Trying to Force PCIE level when DPM is disabled",
744 return -1;);
c82baa28 745 if (0 == data->pcie_dpm_key_disabled)
746 return (0 == smum_send_msg_to_smc_with_parameter(
747 hwmgr->smumgr,
748 (PPSMC_Msg)(PPSMC_MSG_PCIeDPM_ForceLevel),
749 n) ? 0 : 1);
750
751 return 0;
752}
753
754/**
755 * Set the initial state by calling SMC to switch to this state directly
756 *
757 * @param hwmgr the address of the powerplay hardware manager.
758 * @return always 0
759 */
760int tonga_set_boot_state(struct pp_hwmgr *hwmgr)
761{
762 /*
763 * SMC only stores one state that SW will ask to switch too,
764 * so we switch the the just uploaded one
765 */
766 return (0 == tonga_disable_sclk_mclk_dpm(hwmgr)) ? 0 : 1;
767}
768
769/**
770 * Get the location of various tables inside the FW image.
771 *
772 * @param hwmgr the address of the powerplay hardware manager.
773 * @return always 0
774 */
c63e2d4c 775static int tonga_process_firmware_header(struct pp_hwmgr *hwmgr)
c82baa28 776{
777 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
778 struct tonga_smumgr *tonga_smu = (struct tonga_smumgr *)(hwmgr->smumgr->backend);
779
780 uint32_t tmp;
781 int result;
ed5121a3 782 bool error = false;
c82baa28 783
784 result = tonga_read_smc_sram_dword(hwmgr->smumgr,
785 SMU72_FIRMWARE_HEADER_LOCATION +
786 offsetof(SMU72_Firmware_Header, DpmTable),
787 &tmp, data->sram_end);
788
789 if (0 == result) {
790 data->dpm_table_start = tmp;
791 }
792
793 error |= (0 != result);
794
795 result = tonga_read_smc_sram_dword(hwmgr->smumgr,
796 SMU72_FIRMWARE_HEADER_LOCATION +
797 offsetof(SMU72_Firmware_Header, SoftRegisters),
798 &tmp, data->sram_end);
799
800 if (0 == result) {
801 data->soft_regs_start = tmp;
802 tonga_smu->ulSoftRegsStart = tmp;
803 }
804
805 error |= (0 != result);
806
807
808 result = tonga_read_smc_sram_dword(hwmgr->smumgr,
809 SMU72_FIRMWARE_HEADER_LOCATION +
810 offsetof(SMU72_Firmware_Header, mcRegisterTable),
811 &tmp, data->sram_end);
812
813 if (0 == result) {
814 data->mc_reg_table_start = tmp;
815 }
816
817 result = tonga_read_smc_sram_dword(hwmgr->smumgr,
818 SMU72_FIRMWARE_HEADER_LOCATION +
819 offsetof(SMU72_Firmware_Header, FanTable),
820 &tmp, data->sram_end);
821
822 if (0 == result) {
823 data->fan_table_start = tmp;
824 }
825
826 error |= (0 != result);
827
828 result = tonga_read_smc_sram_dword(hwmgr->smumgr,
829 SMU72_FIRMWARE_HEADER_LOCATION +
830 offsetof(SMU72_Firmware_Header, mcArbDramTimingTable),
831 &tmp, data->sram_end);
832
833 if (0 == result) {
834 data->arb_table_start = tmp;
835 }
836
837 error |= (0 != result);
838
839
840 result = tonga_read_smc_sram_dword(hwmgr->smumgr,
841 SMU72_FIRMWARE_HEADER_LOCATION +
842 offsetof(SMU72_Firmware_Header, Version),
843 &tmp, data->sram_end);
844
845 if (0 == result) {
846 hwmgr->microcode_version_info.SMC = tmp;
847 }
848
849 error |= (0 != result);
850
851 return error ? 1 : 0;
852}
853
854/**
855 * Read clock related registers.
856 *
857 * @param hwmgr the address of the powerplay hardware manager.
858 * @return always 0
859 */
860int tonga_read_clock_registers(struct pp_hwmgr *hwmgr)
861{
862 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
863
864 data->clock_registers.vCG_SPLL_FUNC_CNTL =
865 cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_FUNC_CNTL);
866 data->clock_registers.vCG_SPLL_FUNC_CNTL_2 =
867 cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_FUNC_CNTL_2);
868 data->clock_registers.vCG_SPLL_FUNC_CNTL_3 =
869 cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_FUNC_CNTL_3);
870 data->clock_registers.vCG_SPLL_FUNC_CNTL_4 =
871 cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_FUNC_CNTL_4);
872 data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM =
873 cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_SPREAD_SPECTRUM);
874 data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2 =
875 cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_SPREAD_SPECTRUM_2);
876 data->clock_registers.vDLL_CNTL =
877 cgs_read_register(hwmgr->device, mmDLL_CNTL);
878 data->clock_registers.vMCLK_PWRMGT_CNTL =
879 cgs_read_register(hwmgr->device, mmMCLK_PWRMGT_CNTL);
880 data->clock_registers.vMPLL_AD_FUNC_CNTL =
881 cgs_read_register(hwmgr->device, mmMPLL_AD_FUNC_CNTL);
882 data->clock_registers.vMPLL_DQ_FUNC_CNTL =
883 cgs_read_register(hwmgr->device, mmMPLL_DQ_FUNC_CNTL);
884 data->clock_registers.vMPLL_FUNC_CNTL =
885 cgs_read_register(hwmgr->device, mmMPLL_FUNC_CNTL);
886 data->clock_registers.vMPLL_FUNC_CNTL_1 =
887 cgs_read_register(hwmgr->device, mmMPLL_FUNC_CNTL_1);
888 data->clock_registers.vMPLL_FUNC_CNTL_2 =
889 cgs_read_register(hwmgr->device, mmMPLL_FUNC_CNTL_2);
890 data->clock_registers.vMPLL_SS1 =
891 cgs_read_register(hwmgr->device, mmMPLL_SS1);
892 data->clock_registers.vMPLL_SS2 =
893 cgs_read_register(hwmgr->device, mmMPLL_SS2);
894
895 return 0;
896}
897
898/**
899 * Find out if memory is GDDR5.
900 *
901 * @param hwmgr the address of the powerplay hardware manager.
902 * @return always 0
903 */
904int tonga_get_memory_type(struct pp_hwmgr *hwmgr)
905{
906 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
907 uint32_t temp;
908
909 temp = cgs_read_register(hwmgr->device, mmMC_SEQ_MISC0);
910
911 data->is_memory_GDDR5 = (MC_SEQ_MISC0_GDDR5_VALUE ==
912 ((temp & MC_SEQ_MISC0_GDDR5_MASK) >>
913 MC_SEQ_MISC0_GDDR5_SHIFT));
914
915 return 0;
916}
917
918/**
919 * Enables Dynamic Power Management by SMC
920 *
921 * @param hwmgr the address of the powerplay hardware manager.
922 * @return always 0
923 */
924int tonga_enable_acpi_power_management(struct pp_hwmgr *hwmgr)
925{
926 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT, STATIC_PM_EN, 1);
927
928 return 0;
929}
930
931/**
932 * Initialize PowerGating States for different engines
933 *
934 * @param hwmgr the address of the powerplay hardware manager.
935 * @return always 0
936 */
937int tonga_init_power_gate_state(struct pp_hwmgr *hwmgr)
938{
939 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
940
ed5121a3
EC
941 data->uvd_power_gated = false;
942 data->vce_power_gated = false;
943 data->samu_power_gated = false;
944 data->acp_power_gated = false;
945 data->pg_acp_init = true;
c82baa28 946
947 return 0;
948}
949
950/**
951 * Checks if DPM is enabled
952 *
953 * @param hwmgr the address of the powerplay hardware manager.
954 * @return always 0
955 */
956int tonga_check_for_dpm_running(struct pp_hwmgr *hwmgr)
957{
958 /*
959 * We return the status of Voltage Control instead of checking SCLK/MCLK DPM
960 * because we may have test scenarios that need us intentionly disable SCLK/MCLK DPM,
961 * whereas voltage control is a fundemental change that will not be disabled
962 */
4ba27f9b 963 return (!tonga_is_dpm_running(hwmgr) ? 0 : 1);
c82baa28 964}
965
966/**
967 * Checks if DPM is stopped
968 *
969 * @param hwmgr the address of the powerplay hardware manager.
970 * @return always 0
971 */
972int tonga_check_for_dpm_stopped(struct pp_hwmgr *hwmgr)
973{
974 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
975
4ba27f9b 976 if (tonga_is_dpm_running(hwmgr)) {
c82baa28 977 /* If HW Virtualization is enabled, dpm_table_start will not have a valid value */
978 if (!data->dpm_table_start) {
979 return 1;
980 }
981 }
982
983 return 0;
984}
985
986/**
987 * Remove repeated voltage values and create table with unique values.
988 *
989 * @param hwmgr the address of the powerplay hardware manager.
990 * @param voltage_table the pointer to changing voltage table
991 * @return 1 in success
992 */
993
994static int tonga_trim_voltage_table(struct pp_hwmgr *hwmgr,
995 pp_atomctrl_voltage_table *voltage_table)
996{
997 uint32_t table_size, i, j;
998 uint16_t vvalue;
ed5121a3 999 bool bVoltageFound = false;
c82baa28 1000 pp_atomctrl_voltage_table *table;
1001
1002 PP_ASSERT_WITH_CODE((NULL != voltage_table), "Voltage Table empty.", return -1;);
1003 table_size = sizeof(pp_atomctrl_voltage_table);
1004 table = kzalloc(table_size, GFP_KERNEL);
1005
1006 if (NULL == table)
1007 return -ENOMEM;
1008
1009 memset(table, 0x00, table_size);
1010 table->mask_low = voltage_table->mask_low;
1011 table->phase_delay = voltage_table->phase_delay;
1012
1013 for (i = 0; i < voltage_table->count; i++) {
1014 vvalue = voltage_table->entries[i].value;
ed5121a3 1015 bVoltageFound = false;
c82baa28 1016
1017 for (j = 0; j < table->count; j++) {
1018 if (vvalue == table->entries[j].value) {
ed5121a3 1019 bVoltageFound = true;
c82baa28 1020 break;
1021 }
1022 }
1023
1024 if (!bVoltageFound) {
1025 table->entries[table->count].value = vvalue;
1026 table->entries[table->count].smio_low =
1027 voltage_table->entries[i].smio_low;
1028 table->count++;
1029 }
1030 }
1031
1032 memcpy(table, voltage_table, sizeof(pp_atomctrl_voltage_table));
1033
1034 kfree(table);
1035
1036 return 0;
1037}
1038
1039static int tonga_get_svi2_vdd_ci_voltage_table(
1040 struct pp_hwmgr *hwmgr,
1041 phm_ppt_v1_clock_voltage_dependency_table *voltage_dependency_table)
1042{
1043 uint32_t i;
1044 int result;
1045 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
1046 pp_atomctrl_voltage_table *vddci_voltage_table = &(data->vddci_voltage_table);
1047
1048 PP_ASSERT_WITH_CODE((0 != voltage_dependency_table->count),
1049 "Voltage Dependency Table empty.", return -1;);
1050
1051 vddci_voltage_table->mask_low = 0;
1052 vddci_voltage_table->phase_delay = 0;
1053 vddci_voltage_table->count = voltage_dependency_table->count;
1054
1055 for (i = 0; i < voltage_dependency_table->count; i++) {
1056 vddci_voltage_table->entries[i].value =
1057 voltage_dependency_table->entries[i].vddci;
1058 vddci_voltage_table->entries[i].smio_low = 0;
1059 }
1060
1061 result = tonga_trim_voltage_table(hwmgr, vddci_voltage_table);
1062 PP_ASSERT_WITH_CODE((0 == result),
1063 "Failed to trim VDDCI table.", return result;);
1064
1065 return 0;
1066}
1067
1068
1069
1070static int tonga_get_svi2_vdd_voltage_table(
1071 struct pp_hwmgr *hwmgr,
1072 phm_ppt_v1_voltage_lookup_table *look_up_table,
1073 pp_atomctrl_voltage_table *voltage_table)
1074{
1075 uint8_t i = 0;
1076
1077 PP_ASSERT_WITH_CODE((0 != look_up_table->count),
1078 "Voltage Lookup Table empty.", return -1;);
1079
1080 voltage_table->mask_low = 0;
1081 voltage_table->phase_delay = 0;
1082
1083 voltage_table->count = look_up_table->count;
1084
1085 for (i = 0; i < voltage_table->count; i++) {
1086 voltage_table->entries[i].value = look_up_table->entries[i].us_vdd;
1087 voltage_table->entries[i].smio_low = 0;
1088 }
1089
1090 return 0;
1091}
1092
1093/*
1094 * -------------------------------------------------------- Voltage Tables --------------------------------------------------------------------------
1095 * If the voltage table would be bigger than what will fit into the state table on the SMC keep only the higher entries.
1096 */
1097
1098static void tonga_trim_voltage_table_to_fit_state_table(
1099 struct pp_hwmgr *hwmgr,
1100 uint32_t max_voltage_steps,
1101 pp_atomctrl_voltage_table *voltage_table)
1102{
1103 unsigned int i, diff;
1104
1105 if (voltage_table->count <= max_voltage_steps) {
1106 return;
1107 }
1108
1109 diff = voltage_table->count - max_voltage_steps;
1110
1111 for (i = 0; i < max_voltage_steps; i++) {
1112 voltage_table->entries[i] = voltage_table->entries[i + diff];
1113 }
1114
1115 voltage_table->count = max_voltage_steps;
1116
1117 return;
1118}
1119
1120/**
1121 * Create Voltage Tables.
1122 *
1123 * @param hwmgr the address of the powerplay hardware manager.
1124 * @return always 0
1125 */
1126int tonga_construct_voltage_tables(struct pp_hwmgr *hwmgr)
1127{
1128 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
1129 struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
1130 int result;
1131
1132 /* MVDD has only GPIO voltage control */
1133 if (TONGA_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) {
1134 result = atomctrl_get_voltage_table_v3(hwmgr,
1135 VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_GPIO_LUT, &(data->mvdd_voltage_table));
1136 PP_ASSERT_WITH_CODE((0 == result),
1137 "Failed to retrieve MVDD table.", return result;);
1138 }
1139
1140 if (TONGA_VOLTAGE_CONTROL_BY_GPIO == data->vdd_ci_control) {
1141 /* GPIO voltage */
1142 result = atomctrl_get_voltage_table_v3(hwmgr,
1143 VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_GPIO_LUT, &(data->vddci_voltage_table));
1144 PP_ASSERT_WITH_CODE((0 == result),
1145 "Failed to retrieve VDDCI table.", return result;);
1146 } else if (TONGA_VOLTAGE_CONTROL_BY_SVID2 == data->vdd_ci_control) {
1147 /* SVI2 voltage */
1148 result = tonga_get_svi2_vdd_ci_voltage_table(hwmgr,
1149 pptable_info->vdd_dep_on_mclk);
1150 PP_ASSERT_WITH_CODE((0 == result),
1151 "Failed to retrieve SVI2 VDDCI table from dependancy table.", return result;);
1152 }
1153
1154 if (TONGA_VOLTAGE_CONTROL_BY_SVID2 == data->vdd_gfx_control) {
1155 /* VDDGFX has only SVI2 voltage control */
1156 result = tonga_get_svi2_vdd_voltage_table(hwmgr,
1157 pptable_info->vddgfx_lookup_table, &(data->vddgfx_voltage_table));
1158 PP_ASSERT_WITH_CODE((0 == result),
1159 "Failed to retrieve SVI2 VDDGFX table from lookup table.", return result;);
1160 }
1161
1162 if (TONGA_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) {
1163 /* VDDC has only SVI2 voltage control */
1164 result = tonga_get_svi2_vdd_voltage_table(hwmgr,
1165 pptable_info->vddc_lookup_table, &(data->vddc_voltage_table));
1166 PP_ASSERT_WITH_CODE((0 == result),
1167 "Failed to retrieve SVI2 VDDC table from lookup table.", return result;);
1168 }
1169
1170 PP_ASSERT_WITH_CODE(
1171 (data->vddc_voltage_table.count <= (SMU72_MAX_LEVELS_VDDC)),
1172 "Too many voltage values for VDDC. Trimming to fit state table.",
1173 tonga_trim_voltage_table_to_fit_state_table(hwmgr,
1174 SMU72_MAX_LEVELS_VDDC, &(data->vddc_voltage_table));
1175 );
1176
1177 PP_ASSERT_WITH_CODE(
1178 (data->vddgfx_voltage_table.count <= (SMU72_MAX_LEVELS_VDDGFX)),
1179 "Too many voltage values for VDDGFX. Trimming to fit state table.",
1180 tonga_trim_voltage_table_to_fit_state_table(hwmgr,
1181 SMU72_MAX_LEVELS_VDDGFX, &(data->vddgfx_voltage_table));
1182 );
1183
1184 PP_ASSERT_WITH_CODE(
1185 (data->vddci_voltage_table.count <= (SMU72_MAX_LEVELS_VDDCI)),
1186 "Too many voltage values for VDDCI. Trimming to fit state table.",
1187 tonga_trim_voltage_table_to_fit_state_table(hwmgr,
1188 SMU72_MAX_LEVELS_VDDCI, &(data->vddci_voltage_table));
1189 );
1190
1191 PP_ASSERT_WITH_CODE(
1192 (data->mvdd_voltage_table.count <= (SMU72_MAX_LEVELS_MVDD)),
1193 "Too many voltage values for MVDD. Trimming to fit state table.",
1194 tonga_trim_voltage_table_to_fit_state_table(hwmgr,
1195 SMU72_MAX_LEVELS_MVDD, &(data->mvdd_voltage_table));
1196 );
1197
1198 return 0;
1199}
1200
1201/**
1202 * Vddc table preparation for SMC.
1203 *
1204 * @param hwmgr the address of the hardware manager
1205 * @param table the SMC DPM table structure to be populated
1206 * @return always 0
1207 */
1208static int tonga_populate_smc_vddc_table(struct pp_hwmgr *hwmgr,
1209 SMU72_Discrete_DpmTable *table)
1210{
1211 unsigned int count;
1212 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
1213
1214 if (TONGA_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) {
1215 table->VddcLevelCount = data->vddc_voltage_table.count;
1216 for (count = 0; count < table->VddcLevelCount; count++) {
1217 table->VddcTable[count] =
1218 PP_HOST_TO_SMC_US(data->vddc_voltage_table.entries[count].value * VOLTAGE_SCALE);
1219 }
1220 CONVERT_FROM_HOST_TO_SMC_UL(table->VddcLevelCount);
1221 }
1222 return 0;
1223}
1224
1225/**
1226 * VddGfx table preparation for SMC.
1227 *
1228 * @param hwmgr the address of the hardware manager
1229 * @param table the SMC DPM table structure to be populated
1230 * @return always 0
1231 */
1232static int tonga_populate_smc_vdd_gfx_table(struct pp_hwmgr *hwmgr,
1233 SMU72_Discrete_DpmTable *table)
1234{
1235 unsigned int count;
1236 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
1237
1238 if (TONGA_VOLTAGE_CONTROL_BY_SVID2 == data->vdd_gfx_control) {
1239 table->VddGfxLevelCount = data->vddgfx_voltage_table.count;
1240 for (count = 0; count < data->vddgfx_voltage_table.count; count++) {
1241 table->VddGfxTable[count] =
1242 PP_HOST_TO_SMC_US(data->vddgfx_voltage_table.entries[count].value * VOLTAGE_SCALE);
1243 }
1244 CONVERT_FROM_HOST_TO_SMC_UL(table->VddGfxLevelCount);
1245 }
1246 return 0;
1247}
1248
1249/**
1250 * Vddci table preparation for SMC.
1251 *
1252 * @param *hwmgr The address of the hardware manager.
1253 * @param *table The SMC DPM table structure to be populated.
1254 * @return 0
1255 */
1256static int tonga_populate_smc_vdd_ci_table(struct pp_hwmgr *hwmgr,
1257 SMU72_Discrete_DpmTable *table)
1258{
1259 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
1260 uint32_t count;
1261
1262 table->VddciLevelCount = data->vddci_voltage_table.count;
1263 for (count = 0; count < table->VddciLevelCount; count++) {
1264 if (TONGA_VOLTAGE_CONTROL_BY_SVID2 == data->vdd_ci_control) {
1265 table->VddciTable[count] =
1266 PP_HOST_TO_SMC_US(data->vddci_voltage_table.entries[count].value * VOLTAGE_SCALE);
1267 } else if (TONGA_VOLTAGE_CONTROL_BY_GPIO == data->vdd_ci_control) {
1268 table->SmioTable1.Pattern[count].Voltage =
1269 PP_HOST_TO_SMC_US(data->vddci_voltage_table.entries[count].value * VOLTAGE_SCALE);
1270 /* Index into DpmTable.Smio. Drive bits from Smio entry to get this voltage level. */
1271 table->SmioTable1.Pattern[count].Smio =
1272 (uint8_t) count;
1273 table->Smio[count] |=
1274 data->vddci_voltage_table.entries[count].smio_low;
1275 table->VddciTable[count] =
1276 PP_HOST_TO_SMC_US(data->vddci_voltage_table.entries[count].value * VOLTAGE_SCALE);
1277 }
1278 }
1279
1280 table->SmioMask1 = data->vddci_voltage_table.mask_low;
1281 CONVERT_FROM_HOST_TO_SMC_UL(table->VddciLevelCount);
1282
1283 return 0;
1284}
1285
1286/**
1287 * Mvdd table preparation for SMC.
1288 *
1289 * @param *hwmgr The address of the hardware manager.
1290 * @param *table The SMC DPM table structure to be populated.
1291 * @return 0
1292 */
1293static int tonga_populate_smc_mvdd_table(struct pp_hwmgr *hwmgr,
1294 SMU72_Discrete_DpmTable *table)
1295{
1296 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
1297 uint32_t count;
1298
1299 if (TONGA_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) {
1300 table->MvddLevelCount = data->mvdd_voltage_table.count;
1301 for (count = 0; count < table->MvddLevelCount; count++) {
1302 table->SmioTable2.Pattern[count].Voltage =
1303 PP_HOST_TO_SMC_US(data->mvdd_voltage_table.entries[count].value * VOLTAGE_SCALE);
1304 /* Index into DpmTable.Smio. Drive bits from Smio entry to get this voltage level.*/
1305 table->SmioTable2.Pattern[count].Smio =
1306 (uint8_t) count;
1307 table->Smio[count] |=
1308 data->mvdd_voltage_table.entries[count].smio_low;
1309 }
1dfefee8 1310 table->SmioMask2 = data->mvdd_voltage_table.mask_low;
c82baa28 1311
1312 CONVERT_FROM_HOST_TO_SMC_UL(table->MvddLevelCount);
1313 }
1314
1315 return 0;
1316}
1317
c82baa28 1318/**
1319 * Preparation of vddc and vddgfx CAC tables for SMC.
1320 *
1321 * @param hwmgr the address of the hardware manager
1322 * @param table the SMC DPM table structure to be populated
1323 * @return always 0
1324 */
1325static int tonga_populate_cac_tables(struct pp_hwmgr *hwmgr,
1326 SMU72_Discrete_DpmTable *table)
1327{
1328 uint32_t count;
1329 uint8_t index;
c82baa28 1330 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
1331 struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
1332 struct phm_ppt_v1_voltage_lookup_table *vddgfx_lookup_table = pptable_info->vddgfx_lookup_table;
1333 struct phm_ppt_v1_voltage_lookup_table *vddc_lookup_table = pptable_info->vddc_lookup_table;
1334
1335 /* pTables is already swapped, so in order to use the value from it, we need to swap it back. */
1336 uint32_t vddcLevelCount = PP_SMC_TO_HOST_UL(table->VddcLevelCount);
1337 uint32_t vddgfxLevelCount = PP_SMC_TO_HOST_UL(table->VddGfxLevelCount);
1338
1339 for (count = 0; count < vddcLevelCount; count++) {
1340 /* We are populating vddc CAC data to BapmVddc table in split and merged mode */
1341 index = tonga_get_voltage_index(vddc_lookup_table,
1342 data->vddc_voltage_table.entries[count].value);
1343 table->BapmVddcVidLoSidd[count] =
1344 convert_to_vid(vddc_lookup_table->entries[index].us_cac_low);
1345 table->BapmVddcVidHiSidd[count] =
1346 convert_to_vid(vddc_lookup_table->entries[index].us_cac_mid);
1347 table->BapmVddcVidHiSidd2[count] =
1348 convert_to_vid(vddc_lookup_table->entries[index].us_cac_high);
1349 }
1350
1351 if ((data->vdd_gfx_control == TONGA_VOLTAGE_CONTROL_BY_SVID2)) {
1352 /* We are populating vddgfx CAC data to BapmVddgfx table in split mode */
1353 for (count = 0; count < vddgfxLevelCount; count++) {
1354 index = tonga_get_voltage_index(vddgfx_lookup_table,
1355 data->vddgfx_voltage_table.entries[count].value);
1356 table->BapmVddGfxVidLoSidd[count] =
1357 convert_to_vid(vddgfx_lookup_table->entries[index].us_cac_low);
1358 table->BapmVddGfxVidHiSidd[count] =
1359 convert_to_vid(vddgfx_lookup_table->entries[index].us_cac_mid);
1360 table->BapmVddGfxVidHiSidd2[count] =
1361 convert_to_vid(vddgfx_lookup_table->entries[index].us_cac_high);
1362 }
1363 } else {
1364 for (count = 0; count < vddcLevelCount; count++) {
1365 index = tonga_get_voltage_index(vddc_lookup_table,
1366 data->vddc_voltage_table.entries[count].value);
1367 table->BapmVddGfxVidLoSidd[count] =
1368 convert_to_vid(vddc_lookup_table->entries[index].us_cac_low);
1369 table->BapmVddGfxVidHiSidd[count] =
1370 convert_to_vid(vddc_lookup_table->entries[index].us_cac_mid);
1371 table->BapmVddGfxVidHiSidd2[count] =
1372 convert_to_vid(vddc_lookup_table->entries[index].us_cac_high);
1373 }
1374 }
1375
538f1ef3 1376 return 0;
c82baa28 1377}
1378
1379
1380/**
1381 * Preparation of voltage tables for SMC.
1382 *
1383 * @param hwmgr the address of the hardware manager
1384 * @param table the SMC DPM table structure to be populated
1385 * @return always 0
1386 */
1387
1388int tonga_populate_smc_voltage_tables(struct pp_hwmgr *hwmgr,
1389 SMU72_Discrete_DpmTable *table)
1390{
1391 int result;
1392
1393 result = tonga_populate_smc_vddc_table(hwmgr, table);
1394 PP_ASSERT_WITH_CODE(0 == result,
1395 "can not populate VDDC voltage table to SMC", return -1);
1396
1397 result = tonga_populate_smc_vdd_ci_table(hwmgr, table);
1398 PP_ASSERT_WITH_CODE(0 == result,
1399 "can not populate VDDCI voltage table to SMC", return -1);
1400
1401 result = tonga_populate_smc_vdd_gfx_table(hwmgr, table);
1402 PP_ASSERT_WITH_CODE(0 == result,
1403 "can not populate VDDGFX voltage table to SMC", return -1);
1404
1405 result = tonga_populate_smc_mvdd_table(hwmgr, table);
1406 PP_ASSERT_WITH_CODE(0 == result,
1407 "can not populate MVDD voltage table to SMC", return -1);
1408
1409 result = tonga_populate_cac_tables(hwmgr, table);
1410 PP_ASSERT_WITH_CODE(0 == result,
1411 "can not populate CAC voltage tables to SMC", return -1);
1412
1413 return 0;
1414}
1415
1416/**
1417 * Populates the SMC VRConfig field in DPM table.
1418 *
1419 * @param hwmgr the address of the hardware manager
1420 * @param table the SMC DPM table structure to be populated
1421 * @return always 0
1422 */
1423static int tonga_populate_vr_config(struct pp_hwmgr *hwmgr,
1424 SMU72_Discrete_DpmTable *table)
1425{
1426 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
1427 uint16_t config;
1428
1429 if (TONGA_VOLTAGE_CONTROL_BY_SVID2 == data->vdd_gfx_control) {
1430 /* Splitted mode */
1431 config = VR_SVI2_PLANE_1;
1432 table->VRConfig |= (config<<VRCONF_VDDGFX_SHIFT);
1433
1434 if (TONGA_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) {
1435 config = VR_SVI2_PLANE_2;
1436 table->VRConfig |= config;
1437 } else {
1438 printk(KERN_ERR "[ powerplay ] VDDC and VDDGFX should be both on SVI2 control in splitted mode! \n");
1439 }
1440 } else {
1441 /* Merged mode */
1442 config = VR_MERGED_WITH_VDDC;
1443 table->VRConfig |= (config<<VRCONF_VDDGFX_SHIFT);
1444
1445 /* Set Vddc Voltage Controller */
1446 if (TONGA_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) {
1447 config = VR_SVI2_PLANE_1;
1448 table->VRConfig |= config;
1449 } else {
1450 printk(KERN_ERR "[ powerplay ] VDDC should be on SVI2 control in merged mode! \n");
1451 }
1452 }
1453
1454 /* Set Vddci Voltage Controller */
1455 if (TONGA_VOLTAGE_CONTROL_BY_SVID2 == data->vdd_ci_control) {
1456 config = VR_SVI2_PLANE_2; /* only in merged mode */
1457 table->VRConfig |= (config<<VRCONF_VDDCI_SHIFT);
1458 } else if (TONGA_VOLTAGE_CONTROL_BY_GPIO == data->vdd_ci_control) {
1459 config = VR_SMIO_PATTERN_1;
1460 table->VRConfig |= (config<<VRCONF_VDDCI_SHIFT);
1461 }
1462
1463 /* Set Mvdd Voltage Controller */
1464 if (TONGA_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) {
1465 config = VR_SMIO_PATTERN_2;
1466 table->VRConfig |= (config<<VRCONF_MVDD_SHIFT);
1467 }
1468
1469 return 0;
1470}
1471
1472static int tonga_get_dependecy_volt_by_clk(struct pp_hwmgr *hwmgr,
1473 phm_ppt_v1_clock_voltage_dependency_table *allowed_clock_voltage_table,
1474 uint32_t clock, SMU_VoltageLevel *voltage, uint32_t *mvdd)
1475{
1476 uint32_t i = 0;
1477 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
1478 struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
1479
1480 /* clock - voltage dependency table is empty table */
1481 if (allowed_clock_voltage_table->count == 0)
1482 return -1;
1483
1484 for (i = 0; i < allowed_clock_voltage_table->count; i++) {
1485 /* find first sclk bigger than request */
1486 if (allowed_clock_voltage_table->entries[i].clk >= clock) {
1487 voltage->VddGfx = tonga_get_voltage_index(pptable_info->vddgfx_lookup_table,
1488 allowed_clock_voltage_table->entries[i].vddgfx);
1489
1490 voltage->Vddc = tonga_get_voltage_index(pptable_info->vddc_lookup_table,
1491 allowed_clock_voltage_table->entries[i].vddc);
1492
1493 if (allowed_clock_voltage_table->entries[i].vddci) {
1494 voltage->Vddci = tonga_get_voltage_id(&data->vddci_voltage_table,
1495 allowed_clock_voltage_table->entries[i].vddci);
1496 } else {
1497 voltage->Vddci = tonga_get_voltage_id(&data->vddci_voltage_table,
1498 allowed_clock_voltage_table->entries[i].vddc - data->vddc_vddci_delta);
1499 }
1500
1501 if (allowed_clock_voltage_table->entries[i].mvdd) {
1502 *mvdd = (uint32_t) allowed_clock_voltage_table->entries[i].mvdd;
1503 }
1504
1505 voltage->Phases = 1;
1506 return 0;
1507 }
1508 }
1509
1510 /* sclk is bigger than max sclk in the dependence table */
1511 voltage->VddGfx = tonga_get_voltage_index(pptable_info->vddgfx_lookup_table,
1512 allowed_clock_voltage_table->entries[i-1].vddgfx);
1513 voltage->Vddc = tonga_get_voltage_index(pptable_info->vddc_lookup_table,
1514 allowed_clock_voltage_table->entries[i-1].vddc);
1515
1516 if (allowed_clock_voltage_table->entries[i-1].vddci) {
1517 voltage->Vddci = tonga_get_voltage_id(&data->vddci_voltage_table,
1518 allowed_clock_voltage_table->entries[i-1].vddci);
1519 }
1520 if (allowed_clock_voltage_table->entries[i-1].mvdd) {
1521 *mvdd = (uint32_t) allowed_clock_voltage_table->entries[i-1].mvdd;
1522 }
1523
1524 return 0;
1525}
1526
1527/**
1528 * Call SMC to reset S0/S1 to S1 and Reset SMIO to initial value
1529 *
1530 * @param hwmgr the address of the powerplay hardware manager.
1531 * @return always 0
1532 */
1533int tonga_reset_to_default(struct pp_hwmgr *hwmgr)
1534{
1535 return (smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_ResetToDefaults) == 0) ? 0 : 1;
1536}
1537
1538int tonga_populate_memory_timing_parameters(
1539 struct pp_hwmgr *hwmgr,
1540 uint32_t engine_clock,
1541 uint32_t memory_clock,
1542 struct SMU72_Discrete_MCArbDramTimingTableEntry *arb_regs
1543 )
1544{
1545 uint32_t dramTiming;
1546 uint32_t dramTiming2;
1547 uint32_t burstTime;
1548 int result;
1549
1550 result = atomctrl_set_engine_dram_timings_rv770(hwmgr,
1551 engine_clock, memory_clock);
1552
1553 PP_ASSERT_WITH_CODE(result == 0,
1554 "Error calling VBIOS to set DRAM_TIMING.", return result);
1555
1556 dramTiming = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING);
1557 dramTiming2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2);
1558 burstTime = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0);
1559
1560 arb_regs->McArbDramTiming = PP_HOST_TO_SMC_UL(dramTiming);
1561 arb_regs->McArbDramTiming2 = PP_HOST_TO_SMC_UL(dramTiming2);
1562 arb_regs->McArbBurstTime = (uint8_t)burstTime;
1563
1564 return 0;
1565}
1566
1567/**
1568 * Setup parameters for the MC ARB.
1569 *
1570 * @param hwmgr the address of the powerplay hardware manager.
1571 * @return always 0
1572 * This function is to be called from the SetPowerState table.
1573 */
1574int tonga_program_memory_timing_parameters(struct pp_hwmgr *hwmgr)
1575{
1576 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
1577 int result = 0;
1578 SMU72_Discrete_MCArbDramTimingTable arb_regs;
1579 uint32_t i, j;
1580
1581 memset(&arb_regs, 0x00, sizeof(SMU72_Discrete_MCArbDramTimingTable));
1582
1583 for (i = 0; i < data->dpm_table.sclk_table.count; i++) {
1584 for (j = 0; j < data->dpm_table.mclk_table.count; j++) {
1585 result = tonga_populate_memory_timing_parameters
1586 (hwmgr, data->dpm_table.sclk_table.dpm_levels[i].value,
1587 data->dpm_table.mclk_table.dpm_levels[j].value,
1588 &arb_regs.entries[i][j]);
1589
1590 if (0 != result) {
1591 break;
1592 }
1593 }
1594 }
1595
1596 if (0 == result) {
1597 result = tonga_copy_bytes_to_smc(
1598 hwmgr->smumgr,
1599 data->arb_table_start,
1600 (uint8_t *)&arb_regs,
1601 sizeof(SMU72_Discrete_MCArbDramTimingTable),
1602 data->sram_end
1603 );
1604 }
1605
1606 return result;
1607}
1608
1609static int tonga_populate_smc_link_level(struct pp_hwmgr *hwmgr, SMU72_Discrete_DpmTable *table)
1610{
1611 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
1612 struct tonga_dpm_table *dpm_table = &data->dpm_table;
1613 uint32_t i;
1614
1615 /* Index (dpm_table->pcie_speed_table.count) is reserved for PCIE boot level. */
1616 for (i = 0; i <= dpm_table->pcie_speed_table.count; i++) {
1617 table->LinkLevel[i].PcieGenSpeed =
1618 (uint8_t)dpm_table->pcie_speed_table.dpm_levels[i].value;
1619 table->LinkLevel[i].PcieLaneCount =
1620 (uint8_t)encode_pcie_lane_width(dpm_table->pcie_speed_table.dpm_levels[i].param1);
1621 table->LinkLevel[i].EnabledForActivity =
1622 1;
1623 table->LinkLevel[i].SPC =
1624 (uint8_t)(data->pcie_spc_cap & 0xff);
1625 table->LinkLevel[i].DownThreshold =
1626 PP_HOST_TO_SMC_UL(5);
1627 table->LinkLevel[i].UpThreshold =
1628 PP_HOST_TO_SMC_UL(30);
1629 }
1630
1631 data->smc_state_table.LinkLevelCount =
1632 (uint8_t)dpm_table->pcie_speed_table.count;
1633 data->dpm_level_enable_mask.pcie_dpm_enable_mask =
1634 tonga_get_dpm_level_enable_mask_value(&dpm_table->pcie_speed_table);
1635
1636 return 0;
1637}
1638
0104aa21
AD
1639static int tonga_populate_smc_uvd_level(struct pp_hwmgr *hwmgr,
1640 SMU72_Discrete_DpmTable *table)
1641{
1642 int result = 0;
1643
1644 uint8_t count;
1645 pp_atomctrl_clock_dividers_vi dividers;
1646 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
1647 struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
1648 phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = pptable_info->mm_dep_table;
1649
1650 table->UvdLevelCount = (uint8_t) (mm_table->count);
1651 table->UvdBootLevel = 0;
1652
1653 for (count = 0; count < table->UvdLevelCount; count++) {
1654 table->UvdLevel[count].VclkFrequency = mm_table->entries[count].vclk;
1655 table->UvdLevel[count].DclkFrequency = mm_table->entries[count].dclk;
1656 table->UvdLevel[count].MinVoltage.Vddc =
1657 tonga_get_voltage_index(pptable_info->vddc_lookup_table,
1658 mm_table->entries[count].vddc);
1659 table->UvdLevel[count].MinVoltage.VddGfx =
1660 (data->vdd_gfx_control == TONGA_VOLTAGE_CONTROL_BY_SVID2) ?
1661 tonga_get_voltage_index(pptable_info->vddgfx_lookup_table,
1662 mm_table->entries[count].vddgfx) : 0;
1663 table->UvdLevel[count].MinVoltage.Vddci =
1664 tonga_get_voltage_id(&data->vddci_voltage_table,
1665 mm_table->entries[count].vddc - data->vddc_vddci_delta);
1666 table->UvdLevel[count].MinVoltage.Phases = 1;
1667
1668 /* retrieve divider value for VBIOS */
1669 result = atomctrl_get_dfs_pll_dividers_vi(hwmgr,
1670 table->UvdLevel[count].VclkFrequency, &dividers);
1671 PP_ASSERT_WITH_CODE((0 == result),
1672 "can not find divide id for Vclk clock", return result);
1673
1674 table->UvdLevel[count].VclkDivider = (uint8_t)dividers.pll_post_divider;
1675
1676 result = atomctrl_get_dfs_pll_dividers_vi(hwmgr,
1677 table->UvdLevel[count].DclkFrequency, &dividers);
1678 PP_ASSERT_WITH_CODE((0 == result),
1679 "can not find divide id for Dclk clock", return result);
1680
1681 table->UvdLevel[count].DclkDivider = (uint8_t)dividers.pll_post_divider;
1682
1683 CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].VclkFrequency);
1684 CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].DclkFrequency);
1685 //CONVERT_FROM_HOST_TO_SMC_UL((uint32_t)table->UvdLevel[count].MinVoltage);
c15c8d70 1686 }
0104aa21 1687
c15c8d70 1688 return result;
0104aa21
AD
1689
1690}
c82baa28 1691
1692static int tonga_populate_smc_vce_level(struct pp_hwmgr *hwmgr,
1693 SMU72_Discrete_DpmTable *table)
1694{
1695 int result = 0;
1696
1697 uint8_t count;
1698 pp_atomctrl_clock_dividers_vi dividers;
1699 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
1700 struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
1701 phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = pptable_info->mm_dep_table;
1702
1703 table->VceLevelCount = (uint8_t) (mm_table->count);
1704 table->VceBootLevel = 0;
1705
1706 for (count = 0; count < table->VceLevelCount; count++) {
1707 table->VceLevel[count].Frequency =
1708 mm_table->entries[count].eclk;
1709 table->VceLevel[count].MinVoltage.Vddc =
1710 tonga_get_voltage_index(pptable_info->vddc_lookup_table,
1711 mm_table->entries[count].vddc);
1712 table->VceLevel[count].MinVoltage.VddGfx =
1713 (data->vdd_gfx_control == TONGA_VOLTAGE_CONTROL_BY_SVID2) ?
1714 tonga_get_voltage_index(pptable_info->vddgfx_lookup_table,
1715 mm_table->entries[count].vddgfx) : 0;
1716 table->VceLevel[count].MinVoltage.Vddci =
1717 tonga_get_voltage_id(&data->vddci_voltage_table,
1718 mm_table->entries[count].vddc - data->vddc_vddci_delta);
1719 table->VceLevel[count].MinVoltage.Phases = 1;
1720
1721 /* retrieve divider value for VBIOS */
1722 result = atomctrl_get_dfs_pll_dividers_vi(hwmgr,
1723 table->VceLevel[count].Frequency, &dividers);
1724 PP_ASSERT_WITH_CODE((0 == result),
1725 "can not find divide id for VCE engine clock", return result);
1726
c15c8d70 1727 table->VceLevel[count].Divider = (uint8_t)dividers.pll_post_divider;
c82baa28 1728
1729 CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].Frequency);
1730 }
1731
1732 return result;
1733}
1734
1735static int tonga_populate_smc_acp_level(struct pp_hwmgr *hwmgr,
1736 SMU72_Discrete_DpmTable *table)
1737{
1738 int result = 0;
1739 uint8_t count;
1740 pp_atomctrl_clock_dividers_vi dividers;
1741 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
1742 struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
1743 phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = pptable_info->mm_dep_table;
1744
1745 table->AcpLevelCount = (uint8_t) (mm_table->count);
1746 table->AcpBootLevel = 0;
1747
1748 for (count = 0; count < table->AcpLevelCount; count++) {
1749 table->AcpLevel[count].Frequency =
1750 pptable_info->mm_dep_table->entries[count].aclk;
1751 table->AcpLevel[count].MinVoltage.Vddc =
1752 tonga_get_voltage_index(pptable_info->vddc_lookup_table,
1753 mm_table->entries[count].vddc);
1754 table->AcpLevel[count].MinVoltage.VddGfx =
1755 (data->vdd_gfx_control == TONGA_VOLTAGE_CONTROL_BY_SVID2) ?
1756 tonga_get_voltage_index(pptable_info->vddgfx_lookup_table,
1757 mm_table->entries[count].vddgfx) : 0;
1758 table->AcpLevel[count].MinVoltage.Vddci =
1759 tonga_get_voltage_id(&data->vddci_voltage_table,
1760 mm_table->entries[count].vddc - data->vddc_vddci_delta);
1761 table->AcpLevel[count].MinVoltage.Phases = 1;
1762
1763 /* retrieve divider value for VBIOS */
1764 result = atomctrl_get_dfs_pll_dividers_vi(hwmgr,
1765 table->AcpLevel[count].Frequency, &dividers);
1766 PP_ASSERT_WITH_CODE((0 == result),
1767 "can not find divide id for engine clock", return result);
1768
1769 table->AcpLevel[count].Divider = (uint8_t)dividers.pll_post_divider;
1770
1771 CONVERT_FROM_HOST_TO_SMC_UL(table->AcpLevel[count].Frequency);
1772 }
1773
1774 return result;
1775}
1776
1777static int tonga_populate_smc_samu_level(struct pp_hwmgr *hwmgr,
1778 SMU72_Discrete_DpmTable *table)
1779{
1780 int result = 0;
1781 uint8_t count;
1782 pp_atomctrl_clock_dividers_vi dividers;
1783 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
1784 struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
1785 phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = pptable_info->mm_dep_table;
1786
1787 table->SamuBootLevel = 0;
1788 table->SamuLevelCount = (uint8_t) (mm_table->count);
1789
1790 for (count = 0; count < table->SamuLevelCount; count++) {
1791 /* not sure whether we need evclk or not */
1792 table->SamuLevel[count].Frequency =
1793 pptable_info->mm_dep_table->entries[count].samclock;
1794 table->SamuLevel[count].MinVoltage.Vddc =
1795 tonga_get_voltage_index(pptable_info->vddc_lookup_table,
1796 mm_table->entries[count].vddc);
1797 table->SamuLevel[count].MinVoltage.VddGfx =
1798 (data->vdd_gfx_control == TONGA_VOLTAGE_CONTROL_BY_SVID2) ?
1799 tonga_get_voltage_index(pptable_info->vddgfx_lookup_table,
1800 mm_table->entries[count].vddgfx) : 0;
1801 table->SamuLevel[count].MinVoltage.Vddci =
1802 tonga_get_voltage_id(&data->vddci_voltage_table,
1803 mm_table->entries[count].vddc - data->vddc_vddci_delta);
1804 table->SamuLevel[count].MinVoltage.Phases = 1;
1805
1806 /* retrieve divider value for VBIOS */
1807 result = atomctrl_get_dfs_pll_dividers_vi(hwmgr,
1808 table->SamuLevel[count].Frequency, &dividers);
1809 PP_ASSERT_WITH_CODE((0 == result),
1810 "can not find divide id for samu clock", return result);
1811
c15c8d70 1812 table->SamuLevel[count].Divider = (uint8_t)dividers.pll_post_divider;
c82baa28 1813
1814 CONVERT_FROM_HOST_TO_SMC_UL(table->SamuLevel[count].Frequency);
1815 }
1816
1817 return result;
1818}
1819
1820/**
1821 * Populates the SMC MCLK structure using the provided memory clock
1822 *
1823 * @param hwmgr the address of the hardware manager
1824 * @param memory_clock the memory clock to use to populate the structure
1825 * @param sclk the SMC SCLK structure to be populated
1826 */
1827static int tonga_calculate_mclk_params(
1828 struct pp_hwmgr *hwmgr,
1829 uint32_t memory_clock,
1830 SMU72_Discrete_MemoryLevel *mclk,
1831 bool strobe_mode,
1832 bool dllStateOn
1833 )
1834{
1835 const tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
1836 uint32_t dll_cntl = data->clock_registers.vDLL_CNTL;
1837 uint32_t mclk_pwrmgt_cntl = data->clock_registers.vMCLK_PWRMGT_CNTL;
1838 uint32_t mpll_ad_func_cntl = data->clock_registers.vMPLL_AD_FUNC_CNTL;
1839 uint32_t mpll_dq_func_cntl = data->clock_registers.vMPLL_DQ_FUNC_CNTL;
1840 uint32_t mpll_func_cntl = data->clock_registers.vMPLL_FUNC_CNTL;
1841 uint32_t mpll_func_cntl_1 = data->clock_registers.vMPLL_FUNC_CNTL_1;
1842 uint32_t mpll_func_cntl_2 = data->clock_registers.vMPLL_FUNC_CNTL_2;
1843 uint32_t mpll_ss1 = data->clock_registers.vMPLL_SS1;
1844 uint32_t mpll_ss2 = data->clock_registers.vMPLL_SS2;
1845
1846 pp_atomctrl_memory_clock_param mpll_param;
1847 int result;
1848
1849 result = atomctrl_get_memory_pll_dividers_si(hwmgr,
1850 memory_clock, &mpll_param, strobe_mode);
1851 PP_ASSERT_WITH_CODE(0 == result,
1852 "Error retrieving Memory Clock Parameters from VBIOS.", return result);
1853
1854 /* MPLL_FUNC_CNTL setup*/
c15c8d70 1855 mpll_func_cntl = PHM_SET_FIELD(mpll_func_cntl, MPLL_FUNC_CNTL, BWCTRL, mpll_param.bw_ctrl);
c82baa28 1856
1857 /* MPLL_FUNC_CNTL_1 setup*/
1858 mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1,
1859 MPLL_FUNC_CNTL_1, CLKF, mpll_param.mpll_fb_divider.cl_kf);
1860 mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1,
1861 MPLL_FUNC_CNTL_1, CLKFRAC, mpll_param.mpll_fb_divider.clk_frac);
1862 mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1,
1863 MPLL_FUNC_CNTL_1, VCO_MODE, mpll_param.vco_mode);
1864
1865 /* MPLL_AD_FUNC_CNTL setup*/
1866 mpll_ad_func_cntl = PHM_SET_FIELD(mpll_ad_func_cntl,
1867 MPLL_AD_FUNC_CNTL, YCLK_POST_DIV, mpll_param.mpll_post_divider);
1868
1869 if (data->is_memory_GDDR5) {
1870 /* MPLL_DQ_FUNC_CNTL setup*/
1871 mpll_dq_func_cntl = PHM_SET_FIELD(mpll_dq_func_cntl,
1872 MPLL_DQ_FUNC_CNTL, YCLK_SEL, mpll_param.yclk_sel);
1873 mpll_dq_func_cntl = PHM_SET_FIELD(mpll_dq_func_cntl,
1874 MPLL_DQ_FUNC_CNTL, YCLK_POST_DIV, mpll_param.mpll_post_divider);
1875 }
1876
1877 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1878 PHM_PlatformCaps_MemorySpreadSpectrumSupport)) {
1879 /*
1880 ************************************
1881 Fref = Reference Frequency
1882 NF = Feedback divider ratio
1883 NR = Reference divider ratio
1884 Fnom = Nominal VCO output frequency = Fref * NF / NR
1885 Fs = Spreading Rate
1886 D = Percentage down-spread / 2
1887 Fint = Reference input frequency to PFD = Fref / NR
1888 NS = Spreading rate divider ratio = int(Fint / (2 * Fs))
1889 CLKS = NS - 1 = ISS_STEP_NUM[11:0]
1890 NV = D * Fs / Fnom * 4 * ((Fnom/Fref * NR) ^ 2)
1891 CLKV = 65536 * NV = ISS_STEP_SIZE[25:0]
1892 *************************************
1893 */
1894 pp_atomctrl_internal_ss_info ss_info;
1895 uint32_t freq_nom;
1896 uint32_t tmp;
1897 uint32_t reference_clock = atomctrl_get_mpll_reference_clock(hwmgr);
1898
1899 /* for GDDR5 for all modes and DDR3 */
1900 if (1 == mpll_param.qdr)
1901 freq_nom = memory_clock * 4 * (1 << mpll_param.mpll_post_divider);
1902 else
1903 freq_nom = memory_clock * 2 * (1 << mpll_param.mpll_post_divider);
1904
1905 /* tmp = (freq_nom / reference_clock * reference_divider) ^ 2 Note: S.I. reference_divider = 1*/
1906 tmp = (freq_nom / reference_clock);
1907 tmp = tmp * tmp;
1908
1909 if (0 == atomctrl_get_memory_clock_spread_spectrum(hwmgr, freq_nom, &ss_info)) {
1910 /* ss_info.speed_spectrum_percentage -- in unit of 0.01% */
1911 /* ss.Info.speed_spectrum_rate -- in unit of khz */
1912 /* CLKS = reference_clock / (2 * speed_spectrum_rate * reference_divider) * 10 */
1913 /* = reference_clock * 5 / speed_spectrum_rate */
1914 uint32_t clks = reference_clock * 5 / ss_info.speed_spectrum_rate;
1915
1916 /* CLKV = 65536 * speed_spectrum_percentage / 2 * spreadSpecrumRate / freq_nom * 4 / 100000 * ((freq_nom / reference_clock) ^ 2) */
1917 /* = 131 * speed_spectrum_percentage * speed_spectrum_rate / 100 * ((freq_nom / reference_clock) ^ 2) / freq_nom */
1918 uint32_t clkv =
1919 (uint32_t)((((131 * ss_info.speed_spectrum_percentage *
1920 ss_info.speed_spectrum_rate) / 100) * tmp) / freq_nom);
1921
1922 mpll_ss1 = PHM_SET_FIELD(mpll_ss1, MPLL_SS1, CLKV, clkv);
1923 mpll_ss2 = PHM_SET_FIELD(mpll_ss2, MPLL_SS2, CLKS, clks);
1924 }
1925 }
1926
1927 /* MCLK_PWRMGT_CNTL setup */
1928 mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl,
1929 MCLK_PWRMGT_CNTL, DLL_SPEED, mpll_param.dll_speed);
1930 mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl,
1931 MCLK_PWRMGT_CNTL, MRDCK0_PDNB, dllStateOn);
1932 mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl,
1933 MCLK_PWRMGT_CNTL, MRDCK1_PDNB, dllStateOn);
1934
1935
1936 /* Save the result data to outpupt memory level structure */
1937 mclk->MclkFrequency = memory_clock;
1938 mclk->MpllFuncCntl = mpll_func_cntl;
1939 mclk->MpllFuncCntl_1 = mpll_func_cntl_1;
1940 mclk->MpllFuncCntl_2 = mpll_func_cntl_2;
1941 mclk->MpllAdFuncCntl = mpll_ad_func_cntl;
1942 mclk->MpllDqFuncCntl = mpll_dq_func_cntl;
1943 mclk->MclkPwrmgtCntl = mclk_pwrmgt_cntl;
1944 mclk->DllCntl = dll_cntl;
1945 mclk->MpllSs1 = mpll_ss1;
1946 mclk->MpllSs2 = mpll_ss2;
1947
1948 return 0;
1949}
1950
1951static uint8_t tonga_get_mclk_frequency_ratio(uint32_t memory_clock,
1952 bool strobe_mode)
1953{
1954 uint8_t mc_para_index;
1955
1956 if (strobe_mode) {
1957 if (memory_clock < 12500) {
1958 mc_para_index = 0x00;
1959 } else if (memory_clock > 47500) {
1960 mc_para_index = 0x0f;
1961 } else {
1962 mc_para_index = (uint8_t)((memory_clock - 10000) / 2500);
1963 }
1964 } else {
1965 if (memory_clock < 65000) {
1966 mc_para_index = 0x00;
1967 } else if (memory_clock > 135000) {
1968 mc_para_index = 0x0f;
1969 } else {
1970 mc_para_index = (uint8_t)((memory_clock - 60000) / 5000);
1971 }
1972 }
1973
1974 return mc_para_index;
1975}
1976
1977static uint8_t tonga_get_ddr3_mclk_frequency_ratio(uint32_t memory_clock)
1978{
1979 uint8_t mc_para_index;
1980
1981 if (memory_clock < 10000) {
1982 mc_para_index = 0;
1983 } else if (memory_clock >= 80000) {
1984 mc_para_index = 0x0f;
1985 } else {
1986 mc_para_index = (uint8_t)((memory_clock - 10000) / 5000 + 1);
1987 }
1988
1989 return mc_para_index;
1990}
1991
1992static int tonga_populate_single_memory_level(
1993 struct pp_hwmgr *hwmgr,
1994 uint32_t memory_clock,
1995 SMU72_Discrete_MemoryLevel *memory_level
1996 )
1997{
1998 uint32_t minMvdd = 0;
1999 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
2000 struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
2001 int result = 0;
2002 bool dllStateOn;
2003 struct cgs_display_info info = {0};
2004
2005
2006 if (NULL != pptable_info->vdd_dep_on_mclk) {
2007 result = tonga_get_dependecy_volt_by_clk(hwmgr,
2008 pptable_info->vdd_dep_on_mclk, memory_clock, &memory_level->MinVoltage, &minMvdd);
2009 PP_ASSERT_WITH_CODE((0 == result),
2010 "can not find MinVddc voltage value from memory VDDC voltage dependency table", return result);
2011 }
2012
2013 if (data->mvdd_control == TONGA_VOLTAGE_CONTROL_NONE) {
2014 memory_level->MinMvdd = data->vbios_boot_state.mvdd_bootup_value;
2015 } else {
2016 memory_level->MinMvdd = minMvdd;
2017 }
2018 memory_level->EnabledForThrottle = 1;
2019 memory_level->EnabledForActivity = 0;
2020 memory_level->UpHyst = 0;
2021 memory_level->DownHyst = 100;
2022 memory_level->VoltageDownHyst = 0;
2023
2024 /* Indicates maximum activity level for this performance level.*/
2025 memory_level->ActivityLevel = (uint16_t)data->mclk_activity_target;
2026 memory_level->StutterEnable = 0;
2027 memory_level->StrobeEnable = 0;
2028 memory_level->EdcReadEnable = 0;
2029 memory_level->EdcWriteEnable = 0;
2030 memory_level->RttEnable = 0;
2031
2032 /* default set to low watermark. Highest level will be set to high later.*/
2033 memory_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW;
2034
2035 cgs_get_active_displays_info(hwmgr->device, &info);
2036 data->display_timing.num_existing_displays = info.display_count;
2037
2038 if ((data->mclk_stutter_mode_threshold != 0) &&
7e8d1fbd 2039 (memory_clock <= data->mclk_stutter_mode_threshold) &&
4ba27f9b 2040 (!data->is_uvd_enabled)
7e8d1fbd
AD
2041 && (PHM_READ_FIELD(hwmgr->device, DPG_PIPE_STUTTER_CONTROL, STUTTER_ENABLE) & 0x1)
2042 && (data->display_timing.num_existing_displays <= 2)
2043 && (data->display_timing.num_existing_displays != 0))
c82baa28 2044 memory_level->StutterEnable = 1;
2045
2046 /* decide strobe mode*/
2047 memory_level->StrobeEnable = (data->mclk_strobe_mode_threshold != 0) &&
2048 (memory_clock <= data->mclk_strobe_mode_threshold);
2049
2050 /* decide EDC mode and memory clock ratio*/
2051 if (data->is_memory_GDDR5) {
2052 memory_level->StrobeRatio = tonga_get_mclk_frequency_ratio(memory_clock,
2053 memory_level->StrobeEnable);
2054
2055 if ((data->mclk_edc_enable_threshold != 0) &&
2056 (memory_clock > data->mclk_edc_enable_threshold)) {
2057 memory_level->EdcReadEnable = 1;
2058 }
2059
2060 if ((data->mclk_edc_wr_enable_threshold != 0) &&
2061 (memory_clock > data->mclk_edc_wr_enable_threshold)) {
2062 memory_level->EdcWriteEnable = 1;
2063 }
2064
2065 if (memory_level->StrobeEnable) {
2066 if (tonga_get_mclk_frequency_ratio(memory_clock, 1) >=
2067 ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC7) >> 16) & 0xf)) {
2068 dllStateOn = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC5) >> 1) & 0x1) ? 1 : 0;
2069 } else {
2070 dllStateOn = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC6) >> 1) & 0x1) ? 1 : 0;
2071 }
2072
2073 } else {
2074 dllStateOn = data->dll_defaule_on;
2075 }
2076 } else {
2077 memory_level->StrobeRatio =
2078 tonga_get_ddr3_mclk_frequency_ratio(memory_clock);
2079 dllStateOn = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC5) >> 1) & 0x1) ? 1 : 0;
2080 }
2081
2082 result = tonga_calculate_mclk_params(hwmgr,
2083 memory_clock, memory_level, memory_level->StrobeEnable, dllStateOn);
2084
2085 if (0 == result) {
2086 CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MinMvdd);
2087 /* MCLK frequency in units of 10KHz*/
2088 CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MclkFrequency);
2089 /* Indicates maximum activity level for this performance level.*/
2090 CONVERT_FROM_HOST_TO_SMC_US(memory_level->ActivityLevel);
2091 CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl);
2092 CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl_1);
2093 CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl_2);
2094 CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllAdFuncCntl);
2095 CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllDqFuncCntl);
2096 CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MclkPwrmgtCntl);
2097 CONVERT_FROM_HOST_TO_SMC_UL(memory_level->DllCntl);
2098 CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllSs1);
2099 CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllSs2);
2100 }
2101
2102 return result;
2103}
2104
2105/**
2106 * Populates the SMC MVDD structure using the provided memory clock.
2107 *
2108 * @param hwmgr the address of the hardware manager
2109 * @param mclk the MCLK value to be used in the decision if MVDD should be high or low.
2110 * @param voltage the SMC VOLTAGE structure to be populated
2111 */
2112int tonga_populate_mvdd_value(struct pp_hwmgr *hwmgr, uint32_t mclk, SMIO_Pattern *smio_pattern)
2113{
2114 const tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
2115 struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
2116 uint32_t i = 0;
2117
2118 if (TONGA_VOLTAGE_CONTROL_NONE != data->mvdd_control) {
2119 /* find mvdd value which clock is more than request */
2120 for (i = 0; i < pptable_info->vdd_dep_on_mclk->count; i++) {
2121 if (mclk <= pptable_info->vdd_dep_on_mclk->entries[i].clk) {
2122 /* Always round to higher voltage. */
2123 smio_pattern->Voltage = data->mvdd_voltage_table.entries[i].value;
2124 break;
2125 }
2126 }
2127
2128 PP_ASSERT_WITH_CODE(i < pptable_info->vdd_dep_on_mclk->count,
2129 "MVDD Voltage is outside the supported range.", return -1);
2130
2131 } else {
2132 return -1;
2133 }
2134
2135 return 0;
2136}
2137
2138
2139static int tonga_populate_smv_acpi_level(struct pp_hwmgr *hwmgr,
2140 SMU72_Discrete_DpmTable *table)
2141{
2142 int result = 0;
2143 const tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
2144 pp_atomctrl_clock_dividers_vi dividers;
2145 SMIO_Pattern voltage_level;
2146 uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL;
2147 uint32_t spll_func_cntl_2 = data->clock_registers.vCG_SPLL_FUNC_CNTL_2;
2148 uint32_t dll_cntl = data->clock_registers.vDLL_CNTL;
2149 uint32_t mclk_pwrmgt_cntl = data->clock_registers.vMCLK_PWRMGT_CNTL;
2150
2151 /* The ACPI state should not do DPM on DC (or ever).*/
2152 table->ACPILevel.Flags &= ~PPSMC_SWSTATE_FLAG_DC;
2153
2154 table->ACPILevel.MinVoltage = data->smc_state_table.GraphicsLevel[0].MinVoltage;
2155
2156 /* assign zero for now*/
2157 table->ACPILevel.SclkFrequency = atomctrl_get_reference_clock(hwmgr);
2158
2159 /* get the engine clock dividers for this clock value*/
2160 result = atomctrl_get_engine_pll_dividers_vi(hwmgr,
2161 table->ACPILevel.SclkFrequency, &dividers);
2162
2163 PP_ASSERT_WITH_CODE(result == 0,
2164 "Error retrieving Engine Clock dividers from VBIOS.", return result);
2165
2166 /* divider ID for required SCLK*/
2167 table->ACPILevel.SclkDid = (uint8_t)dividers.pll_post_divider;
2168 table->ACPILevel.DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW;
2169 table->ACPILevel.DeepSleepDivId = 0;
2170
2171 spll_func_cntl = PHM_SET_FIELD(spll_func_cntl,
2172 CG_SPLL_FUNC_CNTL, SPLL_PWRON, 0);
2173 spll_func_cntl = PHM_SET_FIELD(spll_func_cntl,
2174 CG_SPLL_FUNC_CNTL, SPLL_RESET, 1);
2175 spll_func_cntl_2 = PHM_SET_FIELD(spll_func_cntl_2,
2176 CG_SPLL_FUNC_CNTL_2, SCLK_MUX_SEL, 4);
2177
2178 table->ACPILevel.CgSpllFuncCntl = spll_func_cntl;
2179 table->ACPILevel.CgSpllFuncCntl2 = spll_func_cntl_2;
2180 table->ACPILevel.CgSpllFuncCntl3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3;
2181 table->ACPILevel.CgSpllFuncCntl4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4;
2182 table->ACPILevel.SpllSpreadSpectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM;
2183 table->ACPILevel.SpllSpreadSpectrum2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2;
2184 table->ACPILevel.CcPwrDynRm = 0;
2185 table->ACPILevel.CcPwrDynRm1 = 0;
2186
2187
2188 /* For various features to be enabled/disabled while this level is active.*/
2189 CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.Flags);
2190 /* SCLK frequency in units of 10KHz*/
2191 CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SclkFrequency);
2192 CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl);
2193 CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl2);
2194 CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl3);
2195 CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl4);
2196 CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum);
2197 CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum2);
2198 CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm);
2199 CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm1);
2200
2201 /* table->MemoryACPILevel.MinVddcPhases = table->ACPILevel.MinVddcPhases;*/
2202 table->MemoryACPILevel.MinVoltage = data->smc_state_table.MemoryLevel[0].MinVoltage;
2203
2204 /* CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MinVoltage);*/
2205
2206 if (0 == tonga_populate_mvdd_value(hwmgr, 0, &voltage_level))
2207 table->MemoryACPILevel.MinMvdd =
2208 PP_HOST_TO_SMC_UL(voltage_level.Voltage * VOLTAGE_SCALE);
2209 else
2210 table->MemoryACPILevel.MinMvdd = 0;
2211
2212 /* Force reset on DLL*/
2213 mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl,
2214 MCLK_PWRMGT_CNTL, MRDCK0_RESET, 0x1);
2215 mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl,
2216 MCLK_PWRMGT_CNTL, MRDCK1_RESET, 0x1);
2217
2218 /* Disable DLL in ACPIState*/
2219 mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl,
2220 MCLK_PWRMGT_CNTL, MRDCK0_PDNB, 0);
2221 mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl,
2222 MCLK_PWRMGT_CNTL, MRDCK1_PDNB, 0);
2223
2224 /* Enable DLL bypass signal*/
2225 dll_cntl = PHM_SET_FIELD(dll_cntl,
2226 DLL_CNTL, MRDCK0_BYPASS, 0);
2227 dll_cntl = PHM_SET_FIELD(dll_cntl,
2228 DLL_CNTL, MRDCK1_BYPASS, 0);
2229
2230 table->MemoryACPILevel.DllCntl =
2231 PP_HOST_TO_SMC_UL(dll_cntl);
2232 table->MemoryACPILevel.MclkPwrmgtCntl =
2233 PP_HOST_TO_SMC_UL(mclk_pwrmgt_cntl);
2234 table->MemoryACPILevel.MpllAdFuncCntl =
2235 PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_AD_FUNC_CNTL);
2236 table->MemoryACPILevel.MpllDqFuncCntl =
2237 PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_DQ_FUNC_CNTL);
2238 table->MemoryACPILevel.MpllFuncCntl =
2239 PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL);
2240 table->MemoryACPILevel.MpllFuncCntl_1 =
2241 PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL_1);
2242 table->MemoryACPILevel.MpllFuncCntl_2 =
2243 PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL_2);
2244 table->MemoryACPILevel.MpllSs1 =
2245 PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_SS1);
2246 table->MemoryACPILevel.MpllSs2 =
2247 PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_SS2);
2248
2249 table->MemoryACPILevel.EnabledForThrottle = 0;
2250 table->MemoryACPILevel.EnabledForActivity = 0;
2251 table->MemoryACPILevel.UpHyst = 0;
2252 table->MemoryACPILevel.DownHyst = 100;
2253 table->MemoryACPILevel.VoltageDownHyst = 0;
2254 /* Indicates maximum activity level for this performance level.*/
2255 table->MemoryACPILevel.ActivityLevel = PP_HOST_TO_SMC_US((uint16_t)data->mclk_activity_target);
2256
2257 table->MemoryACPILevel.StutterEnable = 0;
2258 table->MemoryACPILevel.StrobeEnable = 0;
2259 table->MemoryACPILevel.EdcReadEnable = 0;
2260 table->MemoryACPILevel.EdcWriteEnable = 0;
2261 table->MemoryACPILevel.RttEnable = 0;
2262
2263 return result;
2264}
2265
2266static int tonga_find_boot_level(struct tonga_single_dpm_table *table, uint32_t value, uint32_t *boot_level)
2267{
2268 int result = 0;
2269 uint32_t i;
2270
2271 for (i = 0; i < table->count; i++) {
2272 if (value == table->dpm_levels[i].value) {
2273 *boot_level = i;
2274 result = 0;
2275 }
2276 }
2277 return result;
2278}
2279
2280static int tonga_populate_smc_boot_level(struct pp_hwmgr *hwmgr,
2281 SMU72_Discrete_DpmTable *table)
2282{
2283 int result = 0;
2284 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
2285
2286 table->GraphicsBootLevel = 0; /* 0 == DPM[0] (low), etc. */
2287 table->MemoryBootLevel = 0; /* 0 == DPM[0] (low), etc. */
2288
2289 /* find boot level from dpm table*/
2290 result = tonga_find_boot_level(&(data->dpm_table.sclk_table),
2291 data->vbios_boot_state.sclk_bootup_value,
2292 (uint32_t *)&(data->smc_state_table.GraphicsBootLevel));
2293
2294 if (0 != result) {
2295 data->smc_state_table.GraphicsBootLevel = 0;
2296 printk(KERN_ERR "[ powerplay ] VBIOS did not find boot engine clock value \
2297 in dependency table. Using Graphics DPM level 0!");
2298 result = 0;
2299 }
2300
2301 result = tonga_find_boot_level(&(data->dpm_table.mclk_table),
2302 data->vbios_boot_state.mclk_bootup_value,
2303 (uint32_t *)&(data->smc_state_table.MemoryBootLevel));
2304
2305 if (0 != result) {
2306 data->smc_state_table.MemoryBootLevel = 0;
2307 printk(KERN_ERR "[ powerplay ] VBIOS did not find boot engine clock value \
2308 in dependency table. Using Memory DPM level 0!");
2309 result = 0;
2310 }
2311
2312 table->BootVoltage.Vddc =
2313 tonga_get_voltage_id(&(data->vddc_voltage_table),
2314 data->vbios_boot_state.vddc_bootup_value);
2315 table->BootVoltage.VddGfx =
2316 tonga_get_voltage_id(&(data->vddgfx_voltage_table),
2317 data->vbios_boot_state.vddgfx_bootup_value);
2318 table->BootVoltage.Vddci =
2319 tonga_get_voltage_id(&(data->vddci_voltage_table),
2320 data->vbios_boot_state.vddci_bootup_value);
2321 table->BootMVdd = data->vbios_boot_state.mvdd_bootup_value;
2322
2323 CONVERT_FROM_HOST_TO_SMC_US(table->BootMVdd);
2324
2325 return result;
2326}
2327
2328
2329/**
2330 * Calculates the SCLK dividers using the provided engine clock
2331 *
2332 * @param hwmgr the address of the hardware manager
2333 * @param engine_clock the engine clock to use to populate the structure
2334 * @param sclk the SMC SCLK structure to be populated
2335 */
2336int tonga_calculate_sclk_params(struct pp_hwmgr *hwmgr,
2337 uint32_t engine_clock, SMU72_Discrete_GraphicsLevel *sclk)
2338{
2339 const tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
2340 pp_atomctrl_clock_dividers_vi dividers;
2341 uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL;
2342 uint32_t spll_func_cntl_3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3;
2343 uint32_t spll_func_cntl_4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4;
2344 uint32_t cg_spll_spread_spectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM;
2345 uint32_t cg_spll_spread_spectrum_2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2;
2346 uint32_t reference_clock;
2347 uint32_t reference_divider;
2348 uint32_t fbdiv;
2349 int result;
2350
2351 /* get the engine clock dividers for this clock value*/
2352 result = atomctrl_get_engine_pll_dividers_vi(hwmgr, engine_clock, &dividers);
2353
2354 PP_ASSERT_WITH_CODE(result == 0,
2355 "Error retrieving Engine Clock dividers from VBIOS.", return result);
2356
2357 /* To get FBDIV we need to multiply this by 16384 and divide it by Fref.*/
2358 reference_clock = atomctrl_get_reference_clock(hwmgr);
2359
2360 reference_divider = 1 + dividers.uc_pll_ref_div;
2361
2362 /* low 14 bits is fraction and high 12 bits is divider*/
2363 fbdiv = dividers.ul_fb_div.ul_fb_divider & 0x3FFFFFF;
2364
2365 /* SPLL_FUNC_CNTL setup*/
2366 spll_func_cntl = PHM_SET_FIELD(spll_func_cntl,
2367 CG_SPLL_FUNC_CNTL, SPLL_REF_DIV, dividers.uc_pll_ref_div);
2368 spll_func_cntl = PHM_SET_FIELD(spll_func_cntl,
2369 CG_SPLL_FUNC_CNTL, SPLL_PDIV_A, dividers.uc_pll_post_div);
2370
2371 /* SPLL_FUNC_CNTL_3 setup*/
2372 spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3,
2373 CG_SPLL_FUNC_CNTL_3, SPLL_FB_DIV, fbdiv);
2374
2375 /* set to use fractional accumulation*/
2376 spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3,
2377 CG_SPLL_FUNC_CNTL_3, SPLL_DITHEN, 1);
2378
2379 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2380 PHM_PlatformCaps_EngineSpreadSpectrumSupport)) {
2381 pp_atomctrl_internal_ss_info ss_info;
2382
2383 uint32_t vcoFreq = engine_clock * dividers.uc_pll_post_div;
2384 if (0 == atomctrl_get_engine_clock_spread_spectrum(hwmgr, vcoFreq, &ss_info)) {
2385 /*
2386 * ss_info.speed_spectrum_percentage -- in unit of 0.01%
2387 * ss_info.speed_spectrum_rate -- in unit of khz
2388 */
2389 /* clks = reference_clock * 10 / (REFDIV + 1) / speed_spectrum_rate / 2 */
2390 uint32_t clkS = reference_clock * 5 / (reference_divider * ss_info.speed_spectrum_rate);
2391
2392 /* clkv = 2 * D * fbdiv / NS */
2393 uint32_t clkV = 4 * ss_info.speed_spectrum_percentage * fbdiv / (clkS * 10000);
2394
2395 cg_spll_spread_spectrum =
2396 PHM_SET_FIELD(cg_spll_spread_spectrum, CG_SPLL_SPREAD_SPECTRUM, CLKS, clkS);
2397 cg_spll_spread_spectrum =
2398 PHM_SET_FIELD(cg_spll_spread_spectrum, CG_SPLL_SPREAD_SPECTRUM, SSEN, 1);
2399 cg_spll_spread_spectrum_2 =
2400 PHM_SET_FIELD(cg_spll_spread_spectrum_2, CG_SPLL_SPREAD_SPECTRUM_2, CLKV, clkV);
2401 }
2402 }
2403
2404 sclk->SclkFrequency = engine_clock;
2405 sclk->CgSpllFuncCntl3 = spll_func_cntl_3;
2406 sclk->CgSpllFuncCntl4 = spll_func_cntl_4;
2407 sclk->SpllSpreadSpectrum = cg_spll_spread_spectrum;
2408 sclk->SpllSpreadSpectrum2 = cg_spll_spread_spectrum_2;
2409 sclk->SclkDid = (uint8_t)dividers.pll_post_divider;
2410
2411 return 0;
2412}
2413
438498a8
NW
2414static uint8_t tonga_get_sleep_divider_id_from_clock(uint32_t engine_clock,
2415 uint32_t min_engine_clock_in_sr)
a4333b4c
EH
2416{
2417 uint32_t i, temp;
9887e425 2418 uint32_t min = max(min_engine_clock_in_sr, (uint32_t)TONGA_MINIMUM_ENGINE_CLOCK);
a4333b4c
EH
2419
2420 PP_ASSERT_WITH_CODE((engine_clock >= min),
2421 "Engine clock can't satisfy stutter requirement!", return 0);
2422
2423 for (i = TONGA_MAX_DEEPSLEEP_DIVIDER_ID;; i--) {
354ef928 2424 temp = engine_clock >> i;
a4333b4c
EH
2425
2426 if(temp >= min || i == 0)
2427 break;
2428 }
2429 return (uint8_t)i;
2430}
2431
c82baa28 2432/**
2433 * Populates single SMC SCLK structure using the provided engine clock
2434 *
2435 * @param hwmgr the address of the hardware manager
2436 * @param engine_clock the engine clock to use to populate the structure
2437 * @param sclk the SMC SCLK structure to be populated
2438 */
2439static int tonga_populate_single_graphic_level(struct pp_hwmgr *hwmgr, uint32_t engine_clock, uint16_t sclk_activity_level_threshold, SMU72_Discrete_GraphicsLevel *graphic_level)
2440{
2441 int result;
2442 uint32_t threshold;
2443 uint32_t mvdd;
2444 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
2445 struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
2446
2447 result = tonga_calculate_sclk_params(hwmgr, engine_clock, graphic_level);
2448
2449
2450 /* populate graphics levels*/
2451 result = tonga_get_dependecy_volt_by_clk(hwmgr,
2452 pptable_info->vdd_dep_on_sclk, engine_clock,
2453 &graphic_level->MinVoltage, &mvdd);
2454 PP_ASSERT_WITH_CODE((0 == result),
2455 "can not find VDDC voltage value for VDDC \
2456 engine clock dependency table", return result);
2457
2458 /* SCLK frequency in units of 10KHz*/
2459 graphic_level->SclkFrequency = engine_clock;
2460
2461 /* Indicates maximum activity level for this performance level. 50% for now*/
2462 graphic_level->ActivityLevel = sclk_activity_level_threshold;
2463
2464 graphic_level->CcPwrDynRm = 0;
2465 graphic_level->CcPwrDynRm1 = 0;
2466 /* this level can be used if activity is high enough.*/
2467 graphic_level->EnabledForActivity = 0;
2468 /* this level can be used for throttling.*/
2469 graphic_level->EnabledForThrottle = 1;
2470 graphic_level->UpHyst = 0;
2471 graphic_level->DownHyst = 0;
2472 graphic_level->VoltageDownHyst = 0;
2473 graphic_level->PowerThrottle = 0;
2474
2a702ccd 2475 threshold = engine_clock * data->fast_watermark_threshold / 100;
c82baa28 2476/*
2477 *get the DAL clock. do it in funture.
2478 PECI_GetMinClockSettings(hwmgr->peci, &minClocks);
2479 data->display_timing.min_clock_insr = minClocks.engineClockInSR;
c82baa28 2480*/
a4333b4c
EH
2481 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2482 PHM_PlatformCaps_SclkDeepSleep))
2483 graphic_level->DeepSleepDivId =
438498a8 2484 tonga_get_sleep_divider_id_from_clock(engine_clock,
a4333b4c 2485 data->display_timing.min_clock_insr);
c82baa28 2486
2487 /* Default to slow, highest DPM level will be set to PPSMC_DISPLAY_WATERMARK_LOW later.*/
2488 graphic_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW;
2489
2490 if (0 == result) {
2491 /* CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->MinVoltage);*/
2492 /* CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->MinVddcPhases);*/
2493 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SclkFrequency);
2494 CONVERT_FROM_HOST_TO_SMC_US(graphic_level->ActivityLevel);
2495 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CgSpllFuncCntl3);
2496 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CgSpllFuncCntl4);
2497 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SpllSpreadSpectrum);
2498 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SpllSpreadSpectrum2);
2499 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CcPwrDynRm);
2500 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CcPwrDynRm1);
2501 }
2502
2503 return result;
2504}
2505
2506/**
2507 * Populates all SMC SCLK levels' structure based on the trimmed allowed dpm engine clock states
2508 *
2509 * @param hwmgr the address of the hardware manager
2510 */
2511static int tonga_populate_all_graphic_levels(struct pp_hwmgr *hwmgr)
2512{
2513 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
2514 struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
2515 struct tonga_dpm_table *dpm_table = &data->dpm_table;
2516 phm_ppt_v1_pcie_table *pcie_table = pptable_info->pcie_table;
2517 uint8_t pcie_entry_count = (uint8_t) data->dpm_table.pcie_speed_table.count;
2518 int result = 0;
2519 uint32_t level_array_adress = data->dpm_table_start +
2520 offsetof(SMU72_Discrete_DpmTable, GraphicsLevel);
2521 uint32_t level_array_size = sizeof(SMU72_Discrete_GraphicsLevel) *
2522 SMU72_MAX_LEVELS_GRAPHICS; /* 64 -> long; 32 -> int*/
2523 SMU72_Discrete_GraphicsLevel *levels = data->smc_state_table.GraphicsLevel;
2524 uint32_t i, maxEntry;
2525 uint8_t highest_pcie_level_enabled = 0, lowest_pcie_level_enabled = 0, mid_pcie_level_enabled = 0, count = 0;
2526 PECI_RegistryValue reg_value;
2527 memset(levels, 0x00, level_array_size);
2528
2529 for (i = 0; i < dpm_table->sclk_table.count; i++) {
2530 result = tonga_populate_single_graphic_level(hwmgr,
2531 dpm_table->sclk_table.dpm_levels[i].value,
2532 (uint16_t)data->activity_target[i],
2533 &(data->smc_state_table.GraphicsLevel[i]));
2534
2535 if (0 != result)
2536 return result;
2537
2538 /* Making sure only DPM level 0-1 have Deep Sleep Div ID populated. */
2539 if (i > 1)
2540 data->smc_state_table.GraphicsLevel[i].DeepSleepDivId = 0;
2541
2542 if (0 == i) {
2543 reg_value = 0;
2544 if (reg_value != 0)
2545 data->smc_state_table.GraphicsLevel[0].UpHyst = (uint8_t)reg_value;
2546 }
2547
2548 if (1 == i) {
2549 reg_value = 0;
2550 if (reg_value != 0)
2551 data->smc_state_table.GraphicsLevel[1].UpHyst = (uint8_t)reg_value;
2552 }
2553 }
2554
2555 /* Only enable level 0 for now. */
2556 data->smc_state_table.GraphicsLevel[0].EnabledForActivity = 1;
2557
2558 /* set highest level watermark to high */
2559 if (dpm_table->sclk_table.count > 1)
2560 data->smc_state_table.GraphicsLevel[dpm_table->sclk_table.count-1].DisplayWatermark =
2561 PPSMC_DISPLAY_WATERMARK_HIGH;
2562
2563 data->smc_state_table.GraphicsDpmLevelCount =
2564 (uint8_t)dpm_table->sclk_table.count;
2565 data->dpm_level_enable_mask.sclk_dpm_enable_mask =
2566 tonga_get_dpm_level_enable_mask_value(&dpm_table->sclk_table);
2567
2568 if (pcie_table != NULL) {
2569 PP_ASSERT_WITH_CODE((pcie_entry_count >= 1),
2570 "There must be 1 or more PCIE levels defined in PPTable.", return -1);
2571 maxEntry = pcie_entry_count - 1; /* for indexing, we need to decrement by 1.*/
2572 for (i = 0; i < dpm_table->sclk_table.count; i++) {
2573 data->smc_state_table.GraphicsLevel[i].pcieDpmLevel =
2574 (uint8_t) ((i < maxEntry) ? i : maxEntry);
2575 }
2576 } else {
2577 if (0 == data->dpm_level_enable_mask.pcie_dpm_enable_mask)
2578 printk(KERN_ERR "[ powerplay ] Pcie Dpm Enablemask is 0!");
2579
2580 while (data->dpm_level_enable_mask.pcie_dpm_enable_mask &&
2581 ((data->dpm_level_enable_mask.pcie_dpm_enable_mask &
2582 (1<<(highest_pcie_level_enabled+1))) != 0)) {
2583 highest_pcie_level_enabled++;
2584 }
2585
2586 while (data->dpm_level_enable_mask.pcie_dpm_enable_mask &&
2587 ((data->dpm_level_enable_mask.pcie_dpm_enable_mask &
2588 (1<<lowest_pcie_level_enabled)) == 0)) {
2589 lowest_pcie_level_enabled++;
2590 }
2591
2592 while ((count < highest_pcie_level_enabled) &&
2593 ((data->dpm_level_enable_mask.pcie_dpm_enable_mask &
2594 (1<<(lowest_pcie_level_enabled+1+count))) == 0)) {
2595 count++;
2596 }
2597 mid_pcie_level_enabled = (lowest_pcie_level_enabled+1+count) < highest_pcie_level_enabled ?
2598 (lowest_pcie_level_enabled+1+count) : highest_pcie_level_enabled;
2599
2600
2601 /* set pcieDpmLevel to highest_pcie_level_enabled*/
2602 for (i = 2; i < dpm_table->sclk_table.count; i++) {
2603 data->smc_state_table.GraphicsLevel[i].pcieDpmLevel = highest_pcie_level_enabled;
2604 }
2605
2606 /* set pcieDpmLevel to lowest_pcie_level_enabled*/
2607 data->smc_state_table.GraphicsLevel[0].pcieDpmLevel = lowest_pcie_level_enabled;
2608
2609 /* set pcieDpmLevel to mid_pcie_level_enabled*/
2610 data->smc_state_table.GraphicsLevel[1].pcieDpmLevel = mid_pcie_level_enabled;
2611 }
2612 /* level count will send to smc once at init smc table and never change*/
2613 result = tonga_copy_bytes_to_smc(hwmgr->smumgr, level_array_adress, (uint8_t *)levels, (uint32_t)level_array_size, data->sram_end);
2614
2615 if (0 != result)
2616 return result;
2617
2618 return 0;
2619}
2620
2621/**
2622 * Populates all SMC MCLK levels' structure based on the trimmed allowed dpm memory clock states
2623 *
2624 * @param hwmgr the address of the hardware manager
2625 */
2626
2627static int tonga_populate_all_memory_levels(struct pp_hwmgr *hwmgr)
2628{
2629 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
2630 struct tonga_dpm_table *dpm_table = &data->dpm_table;
2631 int result;
2632 /* populate MCLK dpm table to SMU7 */
2633 uint32_t level_array_adress = data->dpm_table_start + offsetof(SMU72_Discrete_DpmTable, MemoryLevel);
2634 uint32_t level_array_size = sizeof(SMU72_Discrete_MemoryLevel) * SMU72_MAX_LEVELS_MEMORY;
2635 SMU72_Discrete_MemoryLevel *levels = data->smc_state_table.MemoryLevel;
2636 uint32_t i;
2637
2638 memset(levels, 0x00, level_array_size);
2639
2640 for (i = 0; i < dpm_table->mclk_table.count; i++) {
2641 PP_ASSERT_WITH_CODE((0 != dpm_table->mclk_table.dpm_levels[i].value),
2642 "can not populate memory level as memory clock is zero", return -1);
2643 result = tonga_populate_single_memory_level(hwmgr, dpm_table->mclk_table.dpm_levels[i].value,
2644 &(data->smc_state_table.MemoryLevel[i]));
2645 if (0 != result) {
2646 return result;
2647 }
2648 }
2649
2650 /* Only enable level 0 for now.*/
2651 data->smc_state_table.MemoryLevel[0].EnabledForActivity = 1;
2652
2653 /*
2654 * in order to prevent MC activity from stutter mode to push DPM up.
2655 * the UVD change complements this by putting the MCLK in a higher state
2656 * by default such that we are not effected by up threshold or and MCLK DPM latency.
2657 */
2658 data->smc_state_table.MemoryLevel[0].ActivityLevel = 0x1F;
2659 CONVERT_FROM_HOST_TO_SMC_US(data->smc_state_table.MemoryLevel[0].ActivityLevel);
2660
2661 data->smc_state_table.MemoryDpmLevelCount = (uint8_t)dpm_table->mclk_table.count;
2662 data->dpm_level_enable_mask.mclk_dpm_enable_mask = tonga_get_dpm_level_enable_mask_value(&dpm_table->mclk_table);
2663 /* set highest level watermark to high*/
2664 data->smc_state_table.MemoryLevel[dpm_table->mclk_table.count-1].DisplayWatermark = PPSMC_DISPLAY_WATERMARK_HIGH;
2665
2666 /* level count will send to smc once at init smc table and never change*/
2667 result = tonga_copy_bytes_to_smc(hwmgr->smumgr,
2668 level_array_adress, (uint8_t *)levels, (uint32_t)level_array_size, data->sram_end);
2669
2670 if (0 != result) {
2671 return result;
2672 }
2673
2674 return 0;
2675}
2676
2677struct TONGA_DLL_SPEED_SETTING {
2678 uint16_t Min; /* Minimum Data Rate*/
2679 uint16_t Max; /* Maximum Data Rate*/
edf600da 2680 uint32_t dll_speed; /* The desired DLL_SPEED setting*/
c82baa28 2681};
2682
2683static int tonga_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr)
2684{
2685 return 0;
2686}
2687
2688/* ---------------------------------------- ULV related functions ----------------------------------------------------*/
2689
2690
2691static int tonga_reset_single_dpm_table(
2692 struct pp_hwmgr *hwmgr,
2693 struct tonga_single_dpm_table *dpm_table,
2694 uint32_t count)
2695{
2696 uint32_t i;
2697 if (!(count <= MAX_REGULAR_DPM_NUMBER))
2698 printk(KERN_ERR "[ powerplay ] Fatal error, can not set up single DPM \
2699 table entries to exceed max number! \n");
2700
2701 dpm_table->count = count;
2702 for (i = 0; i < MAX_REGULAR_DPM_NUMBER; i++) {
ed5121a3 2703 dpm_table->dpm_levels[i].enabled = false;
c82baa28 2704 }
2705
2706 return 0;
2707}
2708
2709static void tonga_setup_pcie_table_entry(
2710 struct tonga_single_dpm_table *dpm_table,
2711 uint32_t index, uint32_t pcie_gen,
2712 uint32_t pcie_lanes)
2713{
2714 dpm_table->dpm_levels[index].value = pcie_gen;
2715 dpm_table->dpm_levels[index].param1 = pcie_lanes;
ed5121a3 2716 dpm_table->dpm_levels[index].enabled = true;
c82baa28 2717}
2718
c82baa28 2719static int tonga_setup_default_pcie_tables(struct pp_hwmgr *hwmgr)
2720{
2721 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
2722 struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
2723 phm_ppt_v1_pcie_table *pcie_table = pptable_info->pcie_table;
2724 uint32_t i, maxEntry;
2725
2726 if (data->use_pcie_performance_levels && !data->use_pcie_power_saving_levels) {
2727 data->pcie_gen_power_saving = data->pcie_gen_performance;
2728 data->pcie_lane_power_saving = data->pcie_lane_performance;
2729 } else if (!data->use_pcie_performance_levels && data->use_pcie_power_saving_levels) {
2730 data->pcie_gen_performance = data->pcie_gen_power_saving;
2731 data->pcie_lane_performance = data->pcie_lane_power_saving;
2732 }
2733
2734 tonga_reset_single_dpm_table(hwmgr, &data->dpm_table.pcie_speed_table, SMU72_MAX_LEVELS_LINK);
2735
2736 if (pcie_table != NULL) {
2737 /*
2738 * maxEntry is used to make sure we reserve one PCIE level for boot level (fix for A+A PSPP issue).
2739 * If PCIE table from PPTable have ULV entry + 8 entries, then ignore the last entry.
2740 */
2741 maxEntry = (SMU72_MAX_LEVELS_LINK < pcie_table->count) ?
2742 SMU72_MAX_LEVELS_LINK : pcie_table->count;
2743 for (i = 1; i < maxEntry; i++) {
2744 tonga_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, i-1,
2745 get_pcie_gen_support(data->pcie_gen_cap, pcie_table->entries[i].gen_speed),
2746 get_pcie_lane_support(data->pcie_lane_cap, PP_Max_PCIELane));
2747 }
2748 data->dpm_table.pcie_speed_table.count = maxEntry - 1;
2749 } else {
2750 /* Hardcode Pcie Table */
2751 tonga_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 0,
2752 get_pcie_gen_support(data->pcie_gen_cap, PP_Min_PCIEGen),
2753 get_pcie_lane_support(data->pcie_lane_cap, PP_Max_PCIELane));
2754 tonga_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 1,
2755 get_pcie_gen_support(data->pcie_gen_cap, PP_Min_PCIEGen),
2756 get_pcie_lane_support(data->pcie_lane_cap, PP_Max_PCIELane));
2757 tonga_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 2,
2758 get_pcie_gen_support(data->pcie_gen_cap, PP_Max_PCIEGen),
2759 get_pcie_lane_support(data->pcie_lane_cap, PP_Max_PCIELane));
2760 tonga_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 3,
2761 get_pcie_gen_support(data->pcie_gen_cap, PP_Max_PCIEGen),
2762 get_pcie_lane_support(data->pcie_lane_cap, PP_Max_PCIELane));
2763 tonga_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 4,
2764 get_pcie_gen_support(data->pcie_gen_cap, PP_Max_PCIEGen),
2765 get_pcie_lane_support(data->pcie_lane_cap, PP_Max_PCIELane));
2766 tonga_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 5,
2767 get_pcie_gen_support(data->pcie_gen_cap, PP_Max_PCIEGen),
2768 get_pcie_lane_support(data->pcie_lane_cap, PP_Max_PCIELane));
2769 data->dpm_table.pcie_speed_table.count = 6;
2770 }
2771 /* Populate last level for boot PCIE level, but do not increment count. */
2772 tonga_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table,
2773 data->dpm_table.pcie_speed_table.count,
2774 get_pcie_gen_support(data->pcie_gen_cap, PP_Min_PCIEGen),
2775 get_pcie_lane_support(data->pcie_lane_cap, PP_Max_PCIELane));
2776
2777 return 0;
2778
2779}
2780
2781/*
2782 * This function is to initalize all DPM state tables for SMU7 based on the dependency table.
2783 * Dynamic state patching function will then trim these state tables to the allowed range based
2784 * on the power policy or external client requests, such as UVD request, etc.
2785 */
2786static int tonga_setup_default_dpm_tables(struct pp_hwmgr *hwmgr)
2787{
2788 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
2789 struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
2790 uint32_t i;
2791
2792 phm_ppt_v1_clock_voltage_dependency_table *allowed_vdd_sclk_table =
2793 pptable_info->vdd_dep_on_sclk;
2794 phm_ppt_v1_clock_voltage_dependency_table *allowed_vdd_mclk_table =
2795 pptable_info->vdd_dep_on_mclk;
2796
2797 PP_ASSERT_WITH_CODE(allowed_vdd_sclk_table != NULL,
2798 "SCLK dependency table is missing. This table is mandatory", return -1);
2799 PP_ASSERT_WITH_CODE(allowed_vdd_sclk_table->count >= 1,
2800 "SCLK dependency table has to have is missing. This table is mandatory", return -1);
2801
2802 PP_ASSERT_WITH_CODE(allowed_vdd_mclk_table != NULL,
2803 "MCLK dependency table is missing. This table is mandatory", return -1);
2804 PP_ASSERT_WITH_CODE(allowed_vdd_mclk_table->count >= 1,
2805 "VMCLK dependency table has to have is missing. This table is mandatory", return -1);
2806
2807 /* clear the state table to reset everything to default */
2808 memset(&(data->dpm_table), 0x00, sizeof(data->dpm_table));
2809 tonga_reset_single_dpm_table(hwmgr, &data->dpm_table.sclk_table, SMU72_MAX_LEVELS_GRAPHICS);
2810 tonga_reset_single_dpm_table(hwmgr, &data->dpm_table.mclk_table, SMU72_MAX_LEVELS_MEMORY);
2811 /* tonga_reset_single_dpm_table(hwmgr, &tonga_hwmgr->dpm_table.VddcTable, SMU72_MAX_LEVELS_VDDC); */
2812 /* tonga_reset_single_dpm_table(hwmgr, &tonga_hwmgr->dpm_table.vdd_gfx_table, SMU72_MAX_LEVELS_VDDGFX);*/
2813 /* tonga_reset_single_dpm_table(hwmgr, &tonga_hwmgr->dpm_table.vdd_ci_table, SMU72_MAX_LEVELS_VDDCI);*/
2814 /* tonga_reset_single_dpm_table(hwmgr, &tonga_hwmgr->dpm_table.mvdd_table, SMU72_MAX_LEVELS_MVDD);*/
2815
2816 PP_ASSERT_WITH_CODE(allowed_vdd_sclk_table != NULL,
2817 "SCLK dependency table is missing. This table is mandatory", return -1);
2818 /* Initialize Sclk DPM table based on allow Sclk values*/
2819 data->dpm_table.sclk_table.count = 0;
2820
2821 for (i = 0; i < allowed_vdd_sclk_table->count; i++) {
2822 if (i == 0 || data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count-1].value !=
2823 allowed_vdd_sclk_table->entries[i].clk) {
2824 data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count].value =
2825 allowed_vdd_sclk_table->entries[i].clk;
ed5121a3 2826 data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count].enabled = true; /*(i==0) ? 1 : 0; to do */
c82baa28 2827 data->dpm_table.sclk_table.count++;
2828 }
2829 }
2830
2831 PP_ASSERT_WITH_CODE(allowed_vdd_mclk_table != NULL,
2832 "MCLK dependency table is missing. This table is mandatory", return -1);
2833 /* Initialize Mclk DPM table based on allow Mclk values */
2834 data->dpm_table.mclk_table.count = 0;
2835 for (i = 0; i < allowed_vdd_mclk_table->count; i++) {
2836 if (i == 0 || data->dpm_table.mclk_table.dpm_levels[data->dpm_table.mclk_table.count-1].value !=
2837 allowed_vdd_mclk_table->entries[i].clk) {
2838 data->dpm_table.mclk_table.dpm_levels[data->dpm_table.mclk_table.count].value =
2839 allowed_vdd_mclk_table->entries[i].clk;
ed5121a3 2840 data->dpm_table.mclk_table.dpm_levels[data->dpm_table.mclk_table.count].enabled = true; /*(i==0) ? 1 : 0; */
c82baa28 2841 data->dpm_table.mclk_table.count++;
2842 }
2843 }
2844
c82baa28 2845 /* setup PCIE gen speed levels*/
2846 tonga_setup_default_pcie_tables(hwmgr);
2847
2848 /* save a copy of the default DPM table*/
2849 memcpy(&(data->golden_dpm_table), &(data->dpm_table), sizeof(struct tonga_dpm_table));
2850
2851 return 0;
2852}
2853
2854int tonga_populate_smc_initial_state(struct pp_hwmgr *hwmgr,
2855 const struct tonga_power_state *bootState)
2856{
2857 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
2858 struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
2859 uint8_t count, level;
2860
2861 count = (uint8_t) (pptable_info->vdd_dep_on_sclk->count);
2862 for (level = 0; level < count; level++) {
2863 if (pptable_info->vdd_dep_on_sclk->entries[level].clk >=
2864 bootState->performance_levels[0].engine_clock) {
2865 data->smc_state_table.GraphicsBootLevel = level;
2866 break;
2867 }
2868 }
2869
2870 count = (uint8_t) (pptable_info->vdd_dep_on_mclk->count);
2871 for (level = 0; level < count; level++) {
2872 if (pptable_info->vdd_dep_on_mclk->entries[level].clk >=
2873 bootState->performance_levels[0].memory_clock) {
2874 data->smc_state_table.MemoryBootLevel = level;
2875 break;
2876 }
2877 }
2878
2879 return 0;
2880}
2881
2882/**
2883 * Initializes the SMC table and uploads it
2884 *
2885 * @param hwmgr the address of the powerplay hardware manager.
2886 * @param pInput the pointer to input data (PowerState)
2887 * @return always 0
2888 */
c63e2d4c 2889static int tonga_init_smc_table(struct pp_hwmgr *hwmgr)
c82baa28 2890{
2891 int result;
2892 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
2893 struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
2894 SMU72_Discrete_DpmTable *table = &(data->smc_state_table);
2895 const phw_tonga_ulv_parm *ulv = &(data->ulv);
2896 uint8_t i;
2897 PECI_RegistryValue reg_value;
2898 pp_atomctrl_gpio_pin_assignment gpio_pin_assignment;
2899
2900 result = tonga_setup_default_dpm_tables(hwmgr);
2901 PP_ASSERT_WITH_CODE(0 == result,
2902 "Failed to setup default DPM tables!", return result;);
2903 memset(&(data->smc_state_table), 0x00, sizeof(data->smc_state_table));
2904 if (TONGA_VOLTAGE_CONTROL_NONE != data->voltage_control) {
2905 tonga_populate_smc_voltage_tables(hwmgr, table);
2906 }
2907
2908 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2909 PHM_PlatformCaps_AutomaticDCTransition)) {
2910 table->SystemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC;
2911 }
2912
2913 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2914 PHM_PlatformCaps_StepVddc)) {
2915 table->SystemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC;
2916 }
2917
2918 if (data->is_memory_GDDR5) {
2919 table->SystemFlags |= PPSMC_SYSTEMFLAG_GDDR5;
2920 }
2921
2922 i = PHM_READ_FIELD(hwmgr->device, CC_MC_MAX_CHANNEL, NOOFCHAN);
2923
2924 if (i == 1 || i == 0) {
2925 table->SystemFlags |= PPSMC_SYSTEMFLAG_12CHANNEL;
2926 }
2927
2928 if (ulv->ulv_supported && pptable_info->us_ulv_voltage_offset) {
2929 PP_ASSERT_WITH_CODE(0 == result,
2930 "Failed to initialize ULV state!", return result;);
2931
2932 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
2933 ixCG_ULV_PARAMETER, ulv->ch_ulv_parameter);
2934 }
2935
2936 result = tonga_populate_smc_link_level(hwmgr, table);
2937 PP_ASSERT_WITH_CODE(0 == result,
2938 "Failed to initialize Link Level!", return result;);
2939
2940 result = tonga_populate_all_graphic_levels(hwmgr);
2941 PP_ASSERT_WITH_CODE(0 == result,
2942 "Failed to initialize Graphics Level!", return result;);
2943
2944 result = tonga_populate_all_memory_levels(hwmgr);
2945 PP_ASSERT_WITH_CODE(0 == result,
2946 "Failed to initialize Memory Level!", return result;);
2947
2948 result = tonga_populate_smv_acpi_level(hwmgr, table);
2949 PP_ASSERT_WITH_CODE(0 == result,
2950 "Failed to initialize ACPI Level!", return result;);
2951
2952 result = tonga_populate_smc_vce_level(hwmgr, table);
2953 PP_ASSERT_WITH_CODE(0 == result,
2954 "Failed to initialize VCE Level!", return result;);
2955
2956 result = tonga_populate_smc_acp_level(hwmgr, table);
2957 PP_ASSERT_WITH_CODE(0 == result,
2958 "Failed to initialize ACP Level!", return result;);
2959
2960 result = tonga_populate_smc_samu_level(hwmgr, table);
2961 PP_ASSERT_WITH_CODE(0 == result,
2962 "Failed to initialize SAMU Level!", return result;);
2963
2964 /* Since only the initial state is completely set up at this point (the other states are just copies of the boot state) we only */
2965 /* need to populate the ARB settings for the initial state. */
2966 result = tonga_program_memory_timing_parameters(hwmgr);
2967 PP_ASSERT_WITH_CODE(0 == result,
2968 "Failed to Write ARB settings for the initial state.", return result;);
2969
0104aa21
AD
2970 result = tonga_populate_smc_uvd_level(hwmgr, table);
2971 PP_ASSERT_WITH_CODE(0 == result,
2972 "Failed to initialize UVD Level!", return result;);
2973
c82baa28 2974 result = tonga_populate_smc_boot_level(hwmgr, table);
2975 PP_ASSERT_WITH_CODE(0 == result,
2976 "Failed to initialize Boot Level!", return result;);
2977
2a702ccd
RZ
2978 result = tonga_populate_bapm_parameters_in_dpm_table(hwmgr);
2979 PP_ASSERT_WITH_CODE(result == 0,
2980 "Failed to populate BAPM Parameters!", return result);
2981
c82baa28 2982 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2983 PHM_PlatformCaps_ClockStretcher)) {
2984 result = tonga_populate_clock_stretcher_data_table(hwmgr);
2985 PP_ASSERT_WITH_CODE(0 == result,
2986 "Failed to populate Clock Stretcher Data Table!", return result;);
2987 }
2988 table->GraphicsVoltageChangeEnable = 1;
2989 table->GraphicsThermThrottleEnable = 1;
2990 table->GraphicsInterval = 1;
2991 table->VoltageInterval = 1;
2992 table->ThermalInterval = 1;
2993 table->TemperatureLimitHigh =
2994 pptable_info->cac_dtp_table->usTargetOperatingTemp *
2995 TONGA_Q88_FORMAT_CONVERSION_UNIT;
2996 table->TemperatureLimitLow =
2997 (pptable_info->cac_dtp_table->usTargetOperatingTemp - 1) *
2998 TONGA_Q88_FORMAT_CONVERSION_UNIT;
2999 table->MemoryVoltageChangeEnable = 1;
3000 table->MemoryInterval = 1;
3001 table->VoltageResponseTime = 0;
3002 table->PhaseResponseTime = 0;
3003 table->MemoryThermThrottleEnable = 1;
3004
3005 /*
3006 * Cail reads current link status and reports it as cap (we cannot change this due to some previous issues we had)
3007 * SMC drops the link status to lowest level after enabling DPM by PowerPlay. After pnp or toggling CF, driver gets reloaded again
3008 * but this time Cail reads current link status which was set to low by SMC and reports it as cap to powerplay
3009 * To avoid it, we set PCIeBootLinkLevel to highest dpm level
3010 */
3011 PP_ASSERT_WITH_CODE((1 <= data->dpm_table.pcie_speed_table.count),
3012 "There must be 1 or more PCIE levels defined in PPTable.",
3013 return -1);
3014
3015 table->PCIeBootLinkLevel = (uint8_t) (data->dpm_table.pcie_speed_table.count);
3016
3017 table->PCIeGenInterval = 1;
3018
3019 result = tonga_populate_vr_config(hwmgr, table);
3020 PP_ASSERT_WITH_CODE(0 == result,
3021 "Failed to populate VRConfig setting!", return result);
3022
3023 table->ThermGpio = 17;
3024 table->SclkStepSize = 0x4000;
3025
3026 reg_value = 0;
3027 if ((0 == reg_value) &&
e013c91c
RZ
3028 (atomctrl_get_pp_assign_pin(hwmgr, VDDC_VRHOT_GPIO_PINID,
3029 &gpio_pin_assignment))) {
c82baa28 3030 table->VRHotGpio = gpio_pin_assignment.uc_gpio_pin_bit_shift;
3031 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
3032 PHM_PlatformCaps_RegulatorHot);
3033 } else {
3034 table->VRHotGpio = TONGA_UNUSED_GPIO_PIN;
3035 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
3036 PHM_PlatformCaps_RegulatorHot);
3037 }
3038
3039 /* ACDC Switch GPIO */
3040 reg_value = 0;
3041 if ((0 == reg_value) &&
e013c91c
RZ
3042 (atomctrl_get_pp_assign_pin(hwmgr, PP_AC_DC_SWITCH_GPIO_PINID,
3043 &gpio_pin_assignment))) {
c82baa28 3044 table->AcDcGpio = gpio_pin_assignment.uc_gpio_pin_bit_shift;
3045 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
3046 PHM_PlatformCaps_AutomaticDCTransition);
3047 } else {
3048 table->AcDcGpio = TONGA_UNUSED_GPIO_PIN;
3049 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
3050 PHM_PlatformCaps_AutomaticDCTransition);
3051 }
3052
3053 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
3054 PHM_PlatformCaps_Falcon_QuickTransition);
3055
3056 reg_value = 0;
3057 if (1 == reg_value) {
3058 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
3059 PHM_PlatformCaps_AutomaticDCTransition);
3060 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
3061 PHM_PlatformCaps_Falcon_QuickTransition);
3062 }
3063
3064 reg_value = 0;
e013c91c 3065 if ((0 == reg_value) && (atomctrl_get_pp_assign_pin(hwmgr,
c82baa28 3066 THERMAL_INT_OUTPUT_GPIO_PINID, &gpio_pin_assignment))) {
3067 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
3068 PHM_PlatformCaps_ThermalOutGPIO);
3069
3070 table->ThermOutGpio = gpio_pin_assignment.uc_gpio_pin_bit_shift;
3071
3072 table->ThermOutPolarity =
3073 (0 == (cgs_read_register(hwmgr->device, mmGPIOPAD_A) &
3074 (1 << gpio_pin_assignment.uc_gpio_pin_bit_shift))) ? 1:0;
3075
3076 table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_ONLY;
3077
3078 /* if required, combine VRHot/PCC with thermal out GPIO*/
3079 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
3080 PHM_PlatformCaps_RegulatorHot) &&
3081 phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
3082 PHM_PlatformCaps_CombinePCCWithThermalSignal)){
3083 table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_VRHOT;
3084 }
3085 } else {
3086 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
3087 PHM_PlatformCaps_ThermalOutGPIO);
3088
3089 table->ThermOutGpio = 17;
3090 table->ThermOutPolarity = 1;
3091 table->ThermOutMode = SMU7_THERM_OUT_MODE_DISABLE;
3092 }
3093
3094 for (i = 0; i < SMU72_MAX_ENTRIES_SMIO; i++) {
3095 table->Smio[i] = PP_HOST_TO_SMC_UL(table->Smio[i]);
3096 }
3097 CONVERT_FROM_HOST_TO_SMC_UL(table->SystemFlags);
3098 CONVERT_FROM_HOST_TO_SMC_UL(table->VRConfig);
3099 CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask1);
3100 CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask2);
3101 CONVERT_FROM_HOST_TO_SMC_UL(table->SclkStepSize);
3102 CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitHigh);
3103 CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitLow);
3104 CONVERT_FROM_HOST_TO_SMC_US(table->VoltageResponseTime);
3105 CONVERT_FROM_HOST_TO_SMC_US(table->PhaseResponseTime);
3106
3107 /* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */
3108 result = tonga_copy_bytes_to_smc(hwmgr->smumgr, data->dpm_table_start +
3109 offsetof(SMU72_Discrete_DpmTable, SystemFlags),
3110 (uint8_t *)&(table->SystemFlags),
3111 sizeof(SMU72_Discrete_DpmTable)-3 * sizeof(SMU72_PIDController),
3112 data->sram_end);
3113
3114 PP_ASSERT_WITH_CODE(0 == result,
3115 "Failed to upload dpm data to SMC memory!", return result;);
3116
3117 return result;
3118}
3119
3120/* Look up the voltaged based on DAL's requested level. and then send the requested VDDC voltage to SMC*/
3121static void tonga_apply_dal_minimum_voltage_request(struct pp_hwmgr *hwmgr)
3122{
3123 return;
3124}
3125
3126int tonga_upload_dpm_level_enable_mask(struct pp_hwmgr *hwmgr)
3127{
3128 PPSMC_Result result;
3129 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
3130
3131 /* Apply minimum voltage based on DAL's request level */
3132 tonga_apply_dal_minimum_voltage_request(hwmgr);
3133
3134 if (0 == data->sclk_dpm_key_disabled) {
3135 /* Checking if DPM is running. If we discover hang because of this, we should skip this message.*/
4ba27f9b 3136 if (tonga_is_dpm_running(hwmgr))
c82baa28 3137 printk(KERN_ERR "[ powerplay ] Trying to set Enable Mask when DPM is disabled \n");
3138
3139 if (0 != data->dpm_level_enable_mask.sclk_dpm_enable_mask) {
3140 result = smum_send_msg_to_smc_with_parameter(
3141 hwmgr->smumgr,
3142 (PPSMC_Msg)PPSMC_MSG_SCLKDPM_SetEnabledMask,
3143 data->dpm_level_enable_mask.sclk_dpm_enable_mask);
3144 PP_ASSERT_WITH_CODE((0 == result),
3145 "Set Sclk Dpm enable Mask failed", return -1);
3146 }
3147 }
3148
3149 if (0 == data->mclk_dpm_key_disabled) {
3150 /* Checking if DPM is running. If we discover hang because of this, we should skip this message.*/
4ba27f9b 3151 if (tonga_is_dpm_running(hwmgr))
c82baa28 3152 printk(KERN_ERR "[ powerplay ] Trying to set Enable Mask when DPM is disabled \n");
3153
3154 if (0 != data->dpm_level_enable_mask.mclk_dpm_enable_mask) {
3155 result = smum_send_msg_to_smc_with_parameter(
3156 hwmgr->smumgr,
3157 (PPSMC_Msg)PPSMC_MSG_MCLKDPM_SetEnabledMask,
3158 data->dpm_level_enable_mask.mclk_dpm_enable_mask);
3159 PP_ASSERT_WITH_CODE((0 == result),
3160 "Set Mclk Dpm enable Mask failed", return -1);
3161 }
3162 }
3163
3164 return 0;
3165}
3166
3167
3168int tonga_force_dpm_highest(struct pp_hwmgr *hwmgr)
3169{
3170 uint32_t level, tmp;
3171 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
3172
3173 if (0 == data->pcie_dpm_key_disabled) {
3174 /* PCIE */
3175 if (data->dpm_level_enable_mask.pcie_dpm_enable_mask != 0) {
3176 level = 0;
3177 tmp = data->dpm_level_enable_mask.pcie_dpm_enable_mask;
3178 while (tmp >>= 1)
3179 level++ ;
3180
3181 if (0 != level) {
3182 PP_ASSERT_WITH_CODE((0 == tonga_dpm_force_state_pcie(hwmgr, level)),
3183 "force highest pcie dpm state failed!", return -1);
3184 }
3185 }
3186 }
3187
3188 if (0 == data->sclk_dpm_key_disabled) {
3189 /* SCLK */
3190 if (data->dpm_level_enable_mask.sclk_dpm_enable_mask != 0) {
3191 level = 0;
3192 tmp = data->dpm_level_enable_mask.sclk_dpm_enable_mask;
3193 while (tmp >>= 1)
3194 level++ ;
3195
3196 if (0 != level) {
3197 PP_ASSERT_WITH_CODE((0 == tonga_dpm_force_state(hwmgr, level)),
3198 "force highest sclk dpm state failed!", return -1);
3199 if (PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device,
3200 CGS_IND_REG__SMC, TARGET_AND_CURRENT_PROFILE_INDEX, CURR_SCLK_INDEX) != level)
3201 printk(KERN_ERR "[ powerplay ] Target_and_current_Profile_Index. \
3202 Curr_Sclk_Index does not match the level \n");
3203
3204 }
3205 }
3206 }
3207
3208 if (0 == data->mclk_dpm_key_disabled) {
3209 /* MCLK */
3210 if (data->dpm_level_enable_mask.mclk_dpm_enable_mask != 0) {
3211 level = 0;
3212 tmp = data->dpm_level_enable_mask.mclk_dpm_enable_mask;
3213 while (tmp >>= 1)
3214 level++ ;
3215
3216 if (0 != level) {
3217 PP_ASSERT_WITH_CODE((0 == tonga_dpm_force_state_mclk(hwmgr, level)),
3218 "force highest mclk dpm state failed!", return -1);
3219 if (PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
3220 TARGET_AND_CURRENT_PROFILE_INDEX, CURR_MCLK_INDEX) != level)
3221 printk(KERN_ERR "[ powerplay ] Target_and_current_Profile_Index. \
9fe1837d 3222 Curr_Mclk_Index does not match the level \n");
c82baa28 3223 }
3224 }
3225 }
3226
3227 return 0;
3228}
3229
3230/**
3231 * Find the MC microcode version and store it in the HwMgr struct
3232 *
3233 * @param hwmgr the address of the powerplay hardware manager.
3234 * @return always 0
3235 */
3236int tonga_get_mc_microcode_version (struct pp_hwmgr *hwmgr)
3237{
3238 cgs_write_register(hwmgr->device, mmMC_SEQ_IO_DEBUG_INDEX, 0x9F);
3239
3240 hwmgr->microcode_version_info.MC = cgs_read_register(hwmgr->device, mmMC_SEQ_IO_DEBUG_DATA);
3241
3242 return 0;
3243}
3244
3245/**
3246 * Initialize Dynamic State Adjustment Rule Settings
3247 *
3248 * @param hwmgr the address of the powerplay hardware manager.
3249 */
3250int tonga_initializa_dynamic_state_adjustment_rule_settings(struct pp_hwmgr *hwmgr)
3251{
3252 uint32_t table_size;
3253 struct phm_clock_voltage_dependency_table *table_clk_vlt;
3254 struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
3255
3256 hwmgr->dyn_state.mclk_sclk_ratio = 4;
3257 hwmgr->dyn_state.sclk_mclk_delta = 15000; /* 150 MHz */
3258 hwmgr->dyn_state.vddc_vddci_delta = 200; /* 200mV */
3259
3260 /* initialize vddc_dep_on_dal_pwrl table */
3261 table_size = sizeof(uint32_t) + 4 * sizeof(struct phm_clock_voltage_dependency_record);
5969a8c7 3262 table_clk_vlt = kzalloc(table_size, GFP_KERNEL);
c82baa28 3263
3264 if (NULL == table_clk_vlt) {
3265 printk(KERN_ERR "[ powerplay ] Can not allocate space for vddc_dep_on_dal_pwrl! \n");
3266 return -ENOMEM;
3267 } else {
3268 table_clk_vlt->count = 4;
3269 table_clk_vlt->entries[0].clk = PP_DAL_POWERLEVEL_ULTRALOW;
3270 table_clk_vlt->entries[0].v = 0;
3271 table_clk_vlt->entries[1].clk = PP_DAL_POWERLEVEL_LOW;
3272 table_clk_vlt->entries[1].v = 720;
3273 table_clk_vlt->entries[2].clk = PP_DAL_POWERLEVEL_NOMINAL;
3274 table_clk_vlt->entries[2].v = 810;
3275 table_clk_vlt->entries[3].clk = PP_DAL_POWERLEVEL_PERFORMANCE;
3276 table_clk_vlt->entries[3].v = 900;
3277 pptable_info->vddc_dep_on_dal_pwrl = table_clk_vlt;
3278 hwmgr->dyn_state.vddc_dep_on_dal_pwrl = table_clk_vlt;
3279 }
3280
3281 return 0;
3282}
3283
3284static int tonga_set_private_var_based_on_pptale(struct pp_hwmgr *hwmgr)
3285{
3286 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
3287 struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
3288
3289 phm_ppt_v1_clock_voltage_dependency_table *allowed_sclk_vdd_table =
3290 pptable_info->vdd_dep_on_sclk;
3291 phm_ppt_v1_clock_voltage_dependency_table *allowed_mclk_vdd_table =
3292 pptable_info->vdd_dep_on_mclk;
3293
3294 PP_ASSERT_WITH_CODE(allowed_sclk_vdd_table != NULL,
edf600da 3295 "VDD dependency on SCLK table is missing. \
c82baa28 3296 This table is mandatory", return -1);
3297 PP_ASSERT_WITH_CODE(allowed_sclk_vdd_table->count >= 1,
edf600da 3298 "VDD dependency on SCLK table has to have is missing. \
c82baa28 3299 This table is mandatory", return -1);
3300
3301 PP_ASSERT_WITH_CODE(allowed_mclk_vdd_table != NULL,
edf600da 3302 "VDD dependency on MCLK table is missing. \
c82baa28 3303 This table is mandatory", return -1);
3304 PP_ASSERT_WITH_CODE(allowed_mclk_vdd_table->count >= 1,
3305 "VDD dependency on MCLK table has to have is missing. \
3306 This table is mandatory", return -1);
3307
3308 data->min_vddc_in_pp_table = (uint16_t)allowed_sclk_vdd_table->entries[0].vddc;
3309 data->max_vddc_in_pp_table = (uint16_t)allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].vddc;
3310
3311 pptable_info->max_clock_voltage_on_ac.sclk =
3312 allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].clk;
3313 pptable_info->max_clock_voltage_on_ac.mclk =
3314 allowed_mclk_vdd_table->entries[allowed_mclk_vdd_table->count - 1].clk;
3315 pptable_info->max_clock_voltage_on_ac.vddc =
3316 allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].vddc;
3317 pptable_info->max_clock_voltage_on_ac.vddci =
3318 allowed_mclk_vdd_table->entries[allowed_mclk_vdd_table->count - 1].vddci;
3319
3320 hwmgr->dyn_state.max_clock_voltage_on_ac.sclk =
3321 pptable_info->max_clock_voltage_on_ac.sclk;
3322 hwmgr->dyn_state.max_clock_voltage_on_ac.mclk =
3323 pptable_info->max_clock_voltage_on_ac.mclk;
3324 hwmgr->dyn_state.max_clock_voltage_on_ac.vddc =
3325 pptable_info->max_clock_voltage_on_ac.vddc;
3326 hwmgr->dyn_state.max_clock_voltage_on_ac.vddci =
3327 pptable_info->max_clock_voltage_on_ac.vddci;
3328
3329 return 0;
3330}
3331
3332int tonga_unforce_dpm_levels(struct pp_hwmgr *hwmgr)
3333{
3334 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
3335 int result = 1;
3336
4ba27f9b
EC
3337 PP_ASSERT_WITH_CODE (!tonga_is_dpm_running(hwmgr),
3338 "Trying to Unforce DPM when DPM is disabled. Returning without sending SMC message.",
3339 return result);
c82baa28 3340
3341 if (0 == data->pcie_dpm_key_disabled) {
3342 PP_ASSERT_WITH_CODE((0 == smum_send_msg_to_smc(
3343 hwmgr->smumgr,
3344 PPSMC_MSG_PCIeDPM_UnForceLevel)),
3345 "unforce pcie level failed!",
3346 return -1);
3347 }
3348
3349 result = tonga_upload_dpm_level_enable_mask(hwmgr);
3350
3351 return result;
3352}
3353
3354static uint32_t tonga_get_lowest_enable_level(
3355 struct pp_hwmgr *hwmgr, uint32_t level_mask)
3356{
3357 uint32_t level = 0;
3358
3359 while (0 == (level_mask & (1 << level)))
3360 level++;
3361
3362 return level;
3363}
3364
3365static int tonga_force_dpm_lowest(struct pp_hwmgr *hwmgr)
3366{
9fe1837d 3367 uint32_t level;
c82baa28 3368 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
3369
9fe1837d
AD
3370 if (0 == data->pcie_dpm_key_disabled) {
3371 /* PCIE */
3372 if (data->dpm_level_enable_mask.pcie_dpm_enable_mask != 0) {
3373 level = tonga_get_lowest_enable_level(hwmgr,
3374 data->dpm_level_enable_mask.pcie_dpm_enable_mask);
3375 PP_ASSERT_WITH_CODE((0 == tonga_dpm_force_state_pcie(hwmgr, level)),
3376 "force lowest pcie dpm state failed!", return -1);
3377 }
3378 }
3379
3380 if (0 == data->sclk_dpm_key_disabled) {
3381 /* SCLK */
3382 if (0 != data->dpm_level_enable_mask.sclk_dpm_enable_mask) {
3383 level = tonga_get_lowest_enable_level(hwmgr,
3384 data->dpm_level_enable_mask.sclk_dpm_enable_mask);
c82baa28 3385
9fe1837d
AD
3386 PP_ASSERT_WITH_CODE((0 == tonga_dpm_force_state(hwmgr, level)),
3387 "force sclk dpm state failed!", return -1);
c82baa28 3388
9fe1837d
AD
3389 if (PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device,
3390 CGS_IND_REG__SMC, TARGET_AND_CURRENT_PROFILE_INDEX, CURR_SCLK_INDEX) != level)
3391 printk(KERN_ERR "[ powerplay ] Target_and_current_Profile_Index. \
c82baa28 3392 Curr_Sclk_Index does not match the level \n");
9fe1837d
AD
3393 }
3394 }
3395
3396 if (0 == data->mclk_dpm_key_disabled) {
3397 /* MCLK */
3398 if (data->dpm_level_enable_mask.mclk_dpm_enable_mask != 0) {
3399 level = tonga_get_lowest_enable_level(hwmgr,
3400 data->dpm_level_enable_mask.mclk_dpm_enable_mask);
3401 PP_ASSERT_WITH_CODE((0 == tonga_dpm_force_state_mclk(hwmgr, level)),
3402 "force lowest mclk dpm state failed!", return -1);
3403 if (PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
3404 TARGET_AND_CURRENT_PROFILE_INDEX, CURR_MCLK_INDEX) != level)
3405 printk(KERN_ERR "[ powerplay ] Target_and_current_Profile_Index. \
3406 Curr_Mclk_Index does not match the level \n");
3407 }
c82baa28 3408 }
3409
3410 return 0;
3411}
3412
3413static int tonga_patch_voltage_dependency_tables_with_lookup_table(struct pp_hwmgr *hwmgr)
3414{
3415 uint8_t entryId;
3416 uint8_t voltageId;
3417 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
3418 struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
3419
3420 phm_ppt_v1_clock_voltage_dependency_table *sclk_table = pptable_info->vdd_dep_on_sclk;
3421 phm_ppt_v1_clock_voltage_dependency_table *mclk_table = pptable_info->vdd_dep_on_mclk;
3422 phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = pptable_info->mm_dep_table;
3423
3424 if (data->vdd_gfx_control == TONGA_VOLTAGE_CONTROL_BY_SVID2) {
3425 for (entryId = 0; entryId < sclk_table->count; ++entryId) {
3426 voltageId = sclk_table->entries[entryId].vddInd;
3427 sclk_table->entries[entryId].vddgfx =
3428 pptable_info->vddgfx_lookup_table->entries[voltageId].us_vdd;
3429 }
3430 } else {
3431 for (entryId = 0; entryId < sclk_table->count; ++entryId) {
3432 voltageId = sclk_table->entries[entryId].vddInd;
3433 sclk_table->entries[entryId].vddc =
3434 pptable_info->vddc_lookup_table->entries[voltageId].us_vdd;
3435 }
3436 }
3437
3438 for (entryId = 0; entryId < mclk_table->count; ++entryId) {
3439 voltageId = mclk_table->entries[entryId].vddInd;
3440 mclk_table->entries[entryId].vddc =
3441 pptable_info->vddc_lookup_table->entries[voltageId].us_vdd;
3442 }
3443
3444 for (entryId = 0; entryId < mm_table->count; ++entryId) {
3445 voltageId = mm_table->entries[entryId].vddcInd;
3446 mm_table->entries[entryId].vddc =
3447 pptable_info->vddc_lookup_table->entries[voltageId].us_vdd;
3448 }
3449
3450 return 0;
3451
3452}
3453
3454static int tonga_calc_voltage_dependency_tables(struct pp_hwmgr *hwmgr)
3455{
3456 uint8_t entryId;
3457 phm_ppt_v1_voltage_lookup_record v_record;
3458 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
3459 struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
3460
3461 phm_ppt_v1_clock_voltage_dependency_table *sclk_table = pptable_info->vdd_dep_on_sclk;
3462 phm_ppt_v1_clock_voltage_dependency_table *mclk_table = pptable_info->vdd_dep_on_mclk;
3463
3464 if (data->vdd_gfx_control == TONGA_VOLTAGE_CONTROL_BY_SVID2) {
3465 for (entryId = 0; entryId < sclk_table->count; ++entryId) {
3466 if (sclk_table->entries[entryId].vdd_offset & (1 << 15))
3467 v_record.us_vdd = sclk_table->entries[entryId].vddgfx +
3468 sclk_table->entries[entryId].vdd_offset - 0xFFFF;
3469 else
3470 v_record.us_vdd = sclk_table->entries[entryId].vddgfx +
3471 sclk_table->entries[entryId].vdd_offset;
3472
3473 sclk_table->entries[entryId].vddc =
3474 v_record.us_cac_low = v_record.us_cac_mid =
3475 v_record.us_cac_high = v_record.us_vdd;
3476
3477 tonga_add_voltage(hwmgr, pptable_info->vddc_lookup_table, &v_record);
3478 }
3479
3480 for (entryId = 0; entryId < mclk_table->count; ++entryId) {
3481 if (mclk_table->entries[entryId].vdd_offset & (1 << 15))
3482 v_record.us_vdd = mclk_table->entries[entryId].vddc +
3483 mclk_table->entries[entryId].vdd_offset - 0xFFFF;
3484 else
3485 v_record.us_vdd = mclk_table->entries[entryId].vddc +
3486 mclk_table->entries[entryId].vdd_offset;
3487
3488 mclk_table->entries[entryId].vddgfx = v_record.us_cac_low =
3489 v_record.us_cac_mid = v_record.us_cac_high = v_record.us_vdd;
3490 tonga_add_voltage(hwmgr, pptable_info->vddgfx_lookup_table, &v_record);
3491 }
3492 }
3493
3494 return 0;
3495
3496}
3497
3498static int tonga_calc_mm_voltage_dependency_table(struct pp_hwmgr *hwmgr)
3499{
3500 uint32_t entryId;
3501 phm_ppt_v1_voltage_lookup_record v_record;
3502 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
3503 struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
3504 phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = pptable_info->mm_dep_table;
3505
3506 if (data->vdd_gfx_control == TONGA_VOLTAGE_CONTROL_BY_SVID2) {
3507 for (entryId = 0; entryId < mm_table->count; entryId++) {
3508 if (mm_table->entries[entryId].vddgfx_offset & (1 << 15))
3509 v_record.us_vdd = mm_table->entries[entryId].vddc +
3510 mm_table->entries[entryId].vddgfx_offset - 0xFFFF;
3511 else
3512 v_record.us_vdd = mm_table->entries[entryId].vddc +
3513 mm_table->entries[entryId].vddgfx_offset;
3514
3515 /* Add the calculated VDDGFX to the VDDGFX lookup table */
3516 mm_table->entries[entryId].vddgfx = v_record.us_cac_low =
3517 v_record.us_cac_mid = v_record.us_cac_high = v_record.us_vdd;
3518 tonga_add_voltage(hwmgr, pptable_info->vddgfx_lookup_table, &v_record);
3519 }
3520 }
3521 return 0;
3522}
3523
3524
3525/**
3526 * Change virtual leakage voltage to actual value.
3527 *
3528 * @param hwmgr the address of the powerplay hardware manager.
3529 * @param pointer to changing voltage
3530 * @param pointer to leakage table
3531 */
3532static void tonga_patch_with_vdd_leakage(struct pp_hwmgr *hwmgr,
3533 uint16_t *voltage, phw_tonga_leakage_voltage *pLeakageTable)
3534{
3535 uint32_t leakage_index;
3536
3537 /* search for leakage voltage ID 0xff01 ~ 0xff08 */
3538 for (leakage_index = 0; leakage_index < pLeakageTable->count; leakage_index++) {
3539 /* if this voltage matches a leakage voltage ID */
3540 /* patch with actual leakage voltage */
3541 if (pLeakageTable->leakage_id[leakage_index] == *voltage) {
3542 *voltage = pLeakageTable->actual_voltage[leakage_index];
3543 break;
3544 }
3545 }
3546
3547 if (*voltage > ATOM_VIRTUAL_VOLTAGE_ID0)
3548 printk(KERN_ERR "[ powerplay ] Voltage value looks like a Leakage ID but it's not patched \n");
3549}
3550
3551/**
3552 * Patch voltage lookup table by EVV leakages.
3553 *
3554 * @param hwmgr the address of the powerplay hardware manager.
3555 * @param pointer to voltage lookup table
3556 * @param pointer to leakage table
3557 * @return always 0
3558 */
3559static int tonga_patch_lookup_table_with_leakage(struct pp_hwmgr *hwmgr,
3560 phm_ppt_v1_voltage_lookup_table *lookup_table,
3561 phw_tonga_leakage_voltage *pLeakageTable)
3562{
3563 uint32_t i;
3564
3565 for (i = 0; i < lookup_table->count; i++) {
3566 tonga_patch_with_vdd_leakage(hwmgr,
3567 &lookup_table->entries[i].us_vdd, pLeakageTable);
3568 }
3569
3570 return 0;
3571}
3572
3573static int tonga_patch_clock_voltage_lomits_with_vddc_leakage(struct pp_hwmgr *hwmgr,
3574 phw_tonga_leakage_voltage *pLeakageTable, uint16_t *Vddc)
3575{
3576 struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
3577
3578 tonga_patch_with_vdd_leakage(hwmgr, (uint16_t *)Vddc, pLeakageTable);
3579 hwmgr->dyn_state.max_clock_voltage_on_dc.vddc =
3580 pptable_info->max_clock_voltage_on_dc.vddc;
3581
3582 return 0;
3583}
3584
3585static int tonga_patch_clock_voltage_limits_with_vddgfx_leakage(
3586 struct pp_hwmgr *hwmgr, phw_tonga_leakage_voltage *pLeakageTable,
3587 uint16_t *Vddgfx)
3588{
3589 tonga_patch_with_vdd_leakage(hwmgr, (uint16_t *)Vddgfx, pLeakageTable);
3590 return 0;
3591}
3592
3593int tonga_sort_lookup_table(struct pp_hwmgr *hwmgr,
3594 phm_ppt_v1_voltage_lookup_table *lookup_table)
3595{
3596 uint32_t table_size, i, j;
3597 phm_ppt_v1_voltage_lookup_record tmp_voltage_lookup_record;
3598 table_size = lookup_table->count;
3599
3600 PP_ASSERT_WITH_CODE(0 != lookup_table->count,
3601 "Lookup table is empty", return -1);
3602
3603 /* Sorting voltages */
3604 for (i = 0; i < table_size - 1; i++) {
3605 for (j = i + 1; j > 0; j--) {
3606 if (lookup_table->entries[j].us_vdd < lookup_table->entries[j-1].us_vdd) {
3607 tmp_voltage_lookup_record = lookup_table->entries[j-1];
3608 lookup_table->entries[j-1] = lookup_table->entries[j];
3609 lookup_table->entries[j] = tmp_voltage_lookup_record;
3610 }
3611 }
3612 }
3613
3614 return 0;
3615}
3616
3617static int tonga_complete_dependency_tables(struct pp_hwmgr *hwmgr)
3618{
3619 int result = 0;
3620 int tmp_result;
3621 tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
3622 struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
3623
3624 if (data->vdd_gfx_control == TONGA_VOLTAGE_CONTROL_BY_SVID2) {
3625 tmp_result = tonga_patch_lookup_table_with_leakage(hwmgr,
3626 pptable_info->vddgfx_lookup_table, &(data->vddcgfx_leakage));
3627 if (tmp_result != 0)
3628 result = tmp_result;
3629
3630 tmp_result = tonga_patch_clock_voltage_limits_with_vddgfx_leakage(hwmgr,
3631 &(data->vddcgfx_leakage), &pptable_info->max_clock_voltage_on_dc.vddgfx);
3632 if (tmp_result != 0)
3633 result = tmp_result;
3634 } else {
3635 tmp_result = tonga_patch_lookup_table_with_leakage(hwmgr,
3636 pptable_info->vddc_lookup_table, &(data->vddc_leakage));
3637 if (tmp_result != 0)
3638 result = tmp_result;
3639
3640 tmp_result = tonga_patch_clock_voltage_lomits_with_vddc_leakage(hwmgr,
3641 &(data->vddc_leakage), &pptable_info->max_clock_voltage_on_dc.vddc);
3642 if (tmp_result != 0)
3643 result = tmp_result;
3644 }
3645
3646 tmp_result = tonga_patch_voltage_dependency_tables_with_lookup_table(hwmgr);
3647 if (tmp_result != 0)
3648 result = tmp_result;
3649
3650 tmp_result = tonga_calc_voltage_dependency_tables(hwmgr);
3651 if (tmp_result != 0)
3652 result = tmp_result;
3653
3654 tmp_result = tonga_calc_mm_voltage_dependency_table(hwmgr);
3655 if (tmp_result != 0)
3656 result = tmp_result;
3657
3658 tmp_result = tonga_sort_lookup_table(hwmgr, pptable_info->vddgfx_lookup_table);
3659 if (tmp_result != 0)
3660 result = tmp_result;
3661
3662 tmp_result = tonga_sort_lookup_table(hwmgr, pptable_info->vddc_lookup_table);
3663 if (tmp_result != 0)
3664 result = tmp_result;
3665
3666 return result;
3667}
3668
3669int tonga_init_sclk_threshold(struct pp_hwmgr *hwmgr)
3670{
3671 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
3672 data->low_sclk_interrupt_threshold = 0;
3673
3674 return 0;
3675}
3676
3677int tonga_setup_asic_task(struct pp_hwmgr *hwmgr)
3678{
3679 int tmp_result, result = 0;
3680
3681 tmp_result = tonga_read_clock_registers(hwmgr);
3682 PP_ASSERT_WITH_CODE((0 == tmp_result),
3683 "Failed to read clock registers!", result = tmp_result);
3684
3685 tmp_result = tonga_get_memory_type(hwmgr);
3686 PP_ASSERT_WITH_CODE((0 == tmp_result),
3687 "Failed to get memory type!", result = tmp_result);
3688
3689 tmp_result = tonga_enable_acpi_power_management(hwmgr);
3690 PP_ASSERT_WITH_CODE((0 == tmp_result),
3691 "Failed to enable ACPI power management!", result = tmp_result);
3692
3693 tmp_result = tonga_init_power_gate_state(hwmgr);
3694 PP_ASSERT_WITH_CODE((0 == tmp_result),
3695 "Failed to init power gate state!", result = tmp_result);
3696
3697 tmp_result = tonga_get_mc_microcode_version(hwmgr);
3698 PP_ASSERT_WITH_CODE((0 == tmp_result),
3699 "Failed to get MC microcode version!", result = tmp_result);
3700
3701 tmp_result = tonga_init_sclk_threshold(hwmgr);
3702 PP_ASSERT_WITH_CODE((0 == tmp_result),
3703 "Failed to init sclk threshold!", result = tmp_result);
3704
3705 return result;
3706}
3707
3708/**
3709 * Enable voltage control
3710 *
3711 * @param hwmgr the address of the powerplay hardware manager.
3712 * @return always 0
3713 */
3714int tonga_enable_voltage_control(struct pp_hwmgr *hwmgr)
3715{
3716 /* enable voltage control */
3717 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT, VOLT_PWRMGT_EN, 1);
3718
3719 return 0;
3720}
3721
3722/**
3723 * Checks if we want to support voltage control
3724 *
3725 * @param hwmgr the address of the powerplay hardware manager.
3726 */
3727bool cf_tonga_voltage_control(const struct pp_hwmgr *hwmgr)
3728{
3729 const struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
3730
3731 return(TONGA_VOLTAGE_CONTROL_NONE != data->voltage_control);
3732}
3733
3734/*---------------------------MC----------------------------*/
3735
3736uint8_t tonga_get_memory_modile_index(struct pp_hwmgr *hwmgr)
3737{
3738 return (uint8_t) (0xFF & (cgs_read_register(hwmgr->device, mmBIOS_SCRATCH_4) >> 16));
3739}
3740
3741bool tonga_check_s0_mc_reg_index(uint16_t inReg, uint16_t *outReg)
3742{
ed5121a3 3743 bool result = true;
c82baa28 3744
3745 switch (inReg) {
3746 case mmMC_SEQ_RAS_TIMING:
3747 *outReg = mmMC_SEQ_RAS_TIMING_LP;
3748 break;
3749
3750 case mmMC_SEQ_DLL_STBY:
3751 *outReg = mmMC_SEQ_DLL_STBY_LP;
3752 break;
3753
3754 case mmMC_SEQ_G5PDX_CMD0:
3755 *outReg = mmMC_SEQ_G5PDX_CMD0_LP;
3756 break;
3757
3758 case mmMC_SEQ_G5PDX_CMD1:
3759 *outReg = mmMC_SEQ_G5PDX_CMD1_LP;
3760 break;
3761
3762 case mmMC_SEQ_G5PDX_CTRL:
3763 *outReg = mmMC_SEQ_G5PDX_CTRL_LP;
3764 break;
3765
3766 case mmMC_SEQ_CAS_TIMING:
3767 *outReg = mmMC_SEQ_CAS_TIMING_LP;
3768 break;
3769
3770 case mmMC_SEQ_MISC_TIMING:
3771 *outReg = mmMC_SEQ_MISC_TIMING_LP;
3772 break;
3773
3774 case mmMC_SEQ_MISC_TIMING2:
3775 *outReg = mmMC_SEQ_MISC_TIMING2_LP;
3776 break;
3777
3778 case mmMC_SEQ_PMG_DVS_CMD:
3779 *outReg = mmMC_SEQ_PMG_DVS_CMD_LP;
3780 break;
3781
3782 case mmMC_SEQ_PMG_DVS_CTL:
3783 *outReg = mmMC_SEQ_PMG_DVS_CTL_LP;
3784 break;
3785
3786 case mmMC_SEQ_RD_CTL_D0:
3787 *outReg = mmMC_SEQ_RD_CTL_D0_LP;
3788 break;
3789
3790 case mmMC_SEQ_RD_CTL_D1:
3791 *outReg = mmMC_SEQ_RD_CTL_D1_LP;
3792 break;
3793
3794 case mmMC_SEQ_WR_CTL_D0:
3795 *outReg = mmMC_SEQ_WR_CTL_D0_LP;
3796 break;
3797
3798 case mmMC_SEQ_WR_CTL_D1:
3799 *outReg = mmMC_SEQ_WR_CTL_D1_LP;
3800 break;
3801
3802 case mmMC_PMG_CMD_EMRS:
3803 *outReg = mmMC_SEQ_PMG_CMD_EMRS_LP;
3804 break;
3805
3806 case mmMC_PMG_CMD_MRS:
3807 *outReg = mmMC_SEQ_PMG_CMD_MRS_LP;
3808 break;
3809
3810 case mmMC_PMG_CMD_MRS1:
3811 *outReg = mmMC_SEQ_PMG_CMD_MRS1_LP;
3812 break;
3813
3814 case mmMC_SEQ_PMG_TIMING:
3815 *outReg = mmMC_SEQ_PMG_TIMING_LP;
3816 break;
3817
3818 case mmMC_PMG_CMD_MRS2:
3819 *outReg = mmMC_SEQ_PMG_CMD_MRS2_LP;
3820 break;
3821
3822 case mmMC_SEQ_WR_CTL_2:
3823 *outReg = mmMC_SEQ_WR_CTL_2_LP;
3824 break;
3825
3826 default:
ed5121a3 3827 result = false;
c82baa28 3828 break;
3829 }
3830
3831 return result;
3832}
3833
3834int tonga_set_s0_mc_reg_index(phw_tonga_mc_reg_table *table)
3835{
3836 uint32_t i;
3837 uint16_t address;
3838
3839 for (i = 0; i < table->last; i++) {
3840 table->mc_reg_address[i].s0 =
3841 tonga_check_s0_mc_reg_index(table->mc_reg_address[i].s1, &address)
3842 ? address : table->mc_reg_address[i].s1;
3843 }
3844 return 0;
3845}
3846
3847int tonga_copy_vbios_smc_reg_table(const pp_atomctrl_mc_reg_table *table, phw_tonga_mc_reg_table *ni_table)
3848{
3849 uint8_t i, j;
3850
3851 PP_ASSERT_WITH_CODE((table->last <= SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE),
3852 "Invalid VramInfo table.", return -1);
3853 PP_ASSERT_WITH_CODE((table->num_entries <= MAX_AC_TIMING_ENTRIES),
3854 "Invalid VramInfo table.", return -1);
3855
3856 for (i = 0; i < table->last; i++) {
3857 ni_table->mc_reg_address[i].s1 = table->mc_reg_address[i].s1;
3858 }
3859 ni_table->last = table->last;
3860
3861 for (i = 0; i < table->num_entries; i++) {
3862 ni_table->mc_reg_table_entry[i].mclk_max =
3863 table->mc_reg_table_entry[i].mclk_max;
3864 for (j = 0; j < table->last; j++) {
3865 ni_table->mc_reg_table_entry[i].mc_data[j] =
3866 table->mc_reg_table_entry[i].mc_data[j];
3867 }
3868 }
c15c8d70 3869
c82baa28 3870 ni_table->num_entries = table->num_entries;
3871
3872 return 0;
3873}
3874
3875/**
3876 * VBIOS omits some information to reduce size, we need to recover them here.
3877 * 1. when we see mmMC_SEQ_MISC1, bit[31:16] EMRS1, need to be write to mmMC_PMG_CMD_EMRS /_LP[15:0].
3878 * Bit[15:0] MRS, need to be update mmMC_PMG_CMD_MRS/_LP[15:0]
3879 * 2. when we see mmMC_SEQ_RESERVE_M, bit[15:0] EMRS2, need to be write to mmMC_PMG_CMD_MRS1/_LP[15:0].
3880 * 3. need to set these data for each clock range
3881 *
3882 * @param hwmgr the address of the powerplay hardware manager.
3883 * @param table the address of MCRegTable
3884 * @return always 0
3885 */
3886int tonga_set_mc_special_registers(struct pp_hwmgr *hwmgr, phw_tonga_mc_reg_table *table)
3887{
3888 uint8_t i, j, k;
3889 uint32_t temp_reg;
3890 const tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
3891
3892 for (i = 0, j = table->last; i < table->last; i++) {
3893 PP_ASSERT_WITH_CODE((j < SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE),
3894 "Invalid VramInfo table.", return -1);
3895 switch (table->mc_reg_address[i].s1) {
3896 /*
3897 * mmMC_SEQ_MISC1, bit[31:16] EMRS1, need to be write to mmMC_PMG_CMD_EMRS /_LP[15:0].
3898 * Bit[15:0] MRS, need to be update mmMC_PMG_CMD_MRS/_LP[15:0]
3899 */
3900 case mmMC_SEQ_MISC1:
3901 temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_EMRS);
3902 table->mc_reg_address[j].s1 = mmMC_PMG_CMD_EMRS;
3903 table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_EMRS_LP;
3904 for (k = 0; k < table->num_entries; k++) {
3905 table->mc_reg_table_entry[k].mc_data[j] =
3906 ((temp_reg & 0xffff0000)) |
3907 ((table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16);
3908 }
3909 j++;
3910 PP_ASSERT_WITH_CODE((j < SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE),
3911 "Invalid VramInfo table.", return -1);
3912
3913 temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS);
3914 table->mc_reg_address[j].s1 = mmMC_PMG_CMD_MRS;
3915 table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_MRS_LP;
3916 for (k = 0; k < table->num_entries; k++) {
3917 table->mc_reg_table_entry[k].mc_data[j] =
3918 (temp_reg & 0xffff0000) |
3919 (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff);
3920
3921 if (!data->is_memory_GDDR5) {
3922 table->mc_reg_table_entry[k].mc_data[j] |= 0x100;
3923 }
3924 }
3925 j++;
3926 PP_ASSERT_WITH_CODE((j <= SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE),
3927 "Invalid VramInfo table.", return -1);
3928
3929 if (!data->is_memory_GDDR5) {
3930 table->mc_reg_address[j].s1 = mmMC_PMG_AUTO_CMD;
3931 table->mc_reg_address[j].s0 = mmMC_PMG_AUTO_CMD;
3932 for (k = 0; k < table->num_entries; k++) {
3933 table->mc_reg_table_entry[k].mc_data[j] =
3934 (table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16;
3935 }
3936 j++;
3937 PP_ASSERT_WITH_CODE((j <= SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE),
3938 "Invalid VramInfo table.", return -1);
3939 }
3940
3941 break;
3942
3943 case mmMC_SEQ_RESERVE_M:
3944 temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS1);
3945 table->mc_reg_address[j].s1 = mmMC_PMG_CMD_MRS1;
3946 table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_MRS1_LP;
3947 for (k = 0; k < table->num_entries; k++) {
3948 table->mc_reg_table_entry[k].mc_data[j] =
3949 (temp_reg & 0xffff0000) |
3950 (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff);
3951 }
3952 j++;
3953 PP_ASSERT_WITH_CODE((j <= SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE),
3954 "Invalid VramInfo table.", return -1);
3955 break;
3956
3957 default:
3958 break;
3959 }
3960
3961 }
3962
3963 table->last = j;
3964
3965 return 0;
3966}
3967
3968int tonga_set_valid_flag(phw_tonga_mc_reg_table *table)
3969{
3970 uint8_t i, j;
3971 for (i = 0; i < table->last; i++) {
3972 for (j = 1; j < table->num_entries; j++) {
3973 if (table->mc_reg_table_entry[j-1].mc_data[i] !=
3974 table->mc_reg_table_entry[j].mc_data[i]) {
3975 table->validflag |= (1<<i);
3976 break;
3977 }
3978 }
3979 }
3980
3981 return 0;
3982}
3983
c63e2d4c 3984static int tonga_initialize_mc_reg_table(struct pp_hwmgr *hwmgr)
c82baa28 3985{
3986 int result;
3987 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
3988 pp_atomctrl_mc_reg_table *table;
3989 phw_tonga_mc_reg_table *ni_table = &data->tonga_mc_reg_table;
3990 uint8_t module_index = tonga_get_memory_modile_index(hwmgr);
3991
3992 table = kzalloc(sizeof(pp_atomctrl_mc_reg_table), GFP_KERNEL);
3993
3994 if (NULL == table)
c15c8d70 3995 return -ENOMEM;
c82baa28 3996
3997 /* Program additional LP registers that are no longer programmed by VBIOS */
3998 cgs_write_register(hwmgr->device, mmMC_SEQ_RAS_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RAS_TIMING));
3999 cgs_write_register(hwmgr->device, mmMC_SEQ_CAS_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_CAS_TIMING));
4000 cgs_write_register(hwmgr->device, mmMC_SEQ_DLL_STBY_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_DLL_STBY));
4001 cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD0));
4002 cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD1));
4003 cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CTRL_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CTRL));
4004 cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CMD_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CMD));
4005 cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CTL_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CTL));
4006 cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING));
4007 cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2));
4008 cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_EMRS_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_EMRS));
4009 cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS));
4010 cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS1_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS1));
4011 cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D0));
4012 cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1));
4013 cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0));
4014 cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1));
4015 cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_TIMING));
4016 cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS2_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS2));
4017 cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_2_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_2));
4018
4019 memset(table, 0x00, sizeof(pp_atomctrl_mc_reg_table));
4020
4021 result = atomctrl_initialize_mc_reg_table(hwmgr, module_index, table);
4022
4023 if (0 == result)
4024 result = tonga_copy_vbios_smc_reg_table(table, ni_table);
4025
4026 if (0 == result) {
4027 tonga_set_s0_mc_reg_index(ni_table);
4028 result = tonga_set_mc_special_registers(hwmgr, ni_table);
4029 }
4030
4031 if (0 == result)
4032 tonga_set_valid_flag(ni_table);
4033
4034 kfree(table);
4035 return result;
4036}
4037
4038/*
4039* Copy one arb setting to another and then switch the active set.
4040* arbFreqSrc and arbFreqDest is one of the MC_CG_ARB_FREQ_Fx constants.
4041*/
4042int tonga_copy_and_switch_arb_sets(struct pp_hwmgr *hwmgr,
4043 uint32_t arbFreqSrc, uint32_t arbFreqDest)
4044{
4045 uint32_t mc_arb_dram_timing;
4046 uint32_t mc_arb_dram_timing2;
4047 uint32_t burst_time;
4048 uint32_t mc_cg_config;
4049
4050 switch (arbFreqSrc) {
4051 case MC_CG_ARB_FREQ_F0:
4052 mc_arb_dram_timing = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING);
4053 mc_arb_dram_timing2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2);
4054 burst_time = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0);
4055 break;
4056
4057 case MC_CG_ARB_FREQ_F1:
4058 mc_arb_dram_timing = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING_1);
4059 mc_arb_dram_timing2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2_1);
4060 burst_time = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE1);
4061 break;
4062
4063 default:
4064 return -1;
4065 }
4066
4067 switch (arbFreqDest) {
4068 case MC_CG_ARB_FREQ_F0:
4069 cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING, mc_arb_dram_timing);
4070 cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2, mc_arb_dram_timing2);
4071 PHM_WRITE_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0, burst_time);
4072 break;
4073
4074 case MC_CG_ARB_FREQ_F1:
4075 cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING_1, mc_arb_dram_timing);
4076 cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2_1, mc_arb_dram_timing2);
4077 PHM_WRITE_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE1, burst_time);
4078 break;
4079
4080 default:
4081 return -1;
4082 }
4083
4084 mc_cg_config = cgs_read_register(hwmgr->device, mmMC_CG_CONFIG);
4085 mc_cg_config |= 0x0000000F;
4086 cgs_write_register(hwmgr->device, mmMC_CG_CONFIG, mc_cg_config);
4087 PHM_WRITE_FIELD(hwmgr->device, MC_ARB_CG, CG_ARB_REQ, arbFreqDest);
4088
4089 return 0;
4090}
4091
4092/**
4093 * Initial switch from ARB F0->F1
4094 *
4095 * @param hwmgr the address of the powerplay hardware manager.
4096 * @return always 0
4097 * This function is to be called from the SetPowerState table.
4098 */
4099int tonga_initial_switch_from_arb_f0_to_f1(struct pp_hwmgr *hwmgr)
4100{
4101 return tonga_copy_and_switch_arb_sets(hwmgr, MC_CG_ARB_FREQ_F0, MC_CG_ARB_FREQ_F1);
4102}
4103
4104/**
4105 * Initialize the ARB DRAM timing table's index field.
4106 *
4107 * @param hwmgr the address of the powerplay hardware manager.
4108 * @return always 0
4109 */
4110int tonga_init_arb_table_index(struct pp_hwmgr *hwmgr)
4111{
4112 const tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
4113 uint32_t tmp;
4114 int result;
4115
4116 /*
4117 * This is a read-modify-write on the first byte of the ARB table.
4118 * The first byte in the SMU72_Discrete_MCArbDramTimingTable structure is the field 'current'.
4119 * This solution is ugly, but we never write the whole table only individual fields in it.
4120 * In reality this field should not be in that structure but in a soft register.
4121 */
4122 result = tonga_read_smc_sram_dword(hwmgr->smumgr,
4123 data->arb_table_start, &tmp, data->sram_end);
4124
4125 if (0 != result)
4126 return result;
4127
4128 tmp &= 0x00FFFFFF;
4129 tmp |= ((uint32_t)MC_CG_ARB_FREQ_F1) << 24;
4130
4131 return tonga_write_smc_sram_dword(hwmgr->smumgr,
4132 data->arb_table_start, tmp, data->sram_end);
4133}
4134
4135int tonga_populate_mc_reg_address(struct pp_hwmgr *hwmgr, SMU72_Discrete_MCRegisters *mc_reg_table)
4136{
4137 const struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
4138
4139 uint32_t i, j;
4140
4141 for (i = 0, j = 0; j < data->tonga_mc_reg_table.last; j++) {
4142 if (data->tonga_mc_reg_table.validflag & 1<<j) {
4143 PP_ASSERT_WITH_CODE(i < SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE,
4144 "Index of mc_reg_table->address[] array out of boundary", return -1);
4145 mc_reg_table->address[i].s0 =
4146 PP_HOST_TO_SMC_US(data->tonga_mc_reg_table.mc_reg_address[j].s0);
4147 mc_reg_table->address[i].s1 =
4148 PP_HOST_TO_SMC_US(data->tonga_mc_reg_table.mc_reg_address[j].s1);
4149 i++;
4150 }
4151 }
4152
4153 mc_reg_table->last = (uint8_t)i;
4154
4155 return 0;
4156}
4157
4158/*convert register values from driver to SMC format */
4159void tonga_convert_mc_registers(
4160 const phw_tonga_mc_reg_entry * pEntry,
4161 SMU72_Discrete_MCRegisterSet *pData,
4162 uint32_t numEntries, uint32_t validflag)
4163{
4164 uint32_t i, j;
4165
4166 for (i = 0, j = 0; j < numEntries; j++) {
4167 if (validflag & 1<<j) {
4168 pData->value[i] = PP_HOST_TO_SMC_UL(pEntry->mc_data[j]);
4169 i++;
4170 }
4171 }
4172}
4173
4174/* find the entry in the memory range table, then populate the value to SMC's tonga_mc_reg_table */
4175int tonga_convert_mc_reg_table_entry_to_smc(
4176 struct pp_hwmgr *hwmgr,
4177 const uint32_t memory_clock,
4178 SMU72_Discrete_MCRegisterSet *mc_reg_table_data
4179 )
4180{
4181 const tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
4182 uint32_t i = 0;
4183
4184 for (i = 0; i < data->tonga_mc_reg_table.num_entries; i++) {
4185 if (memory_clock <=
4186 data->tonga_mc_reg_table.mc_reg_table_entry[i].mclk_max) {
4187 break;
4188 }
4189 }
4190
4191 if ((i == data->tonga_mc_reg_table.num_entries) && (i > 0))
4192 --i;
4193
4194 tonga_convert_mc_registers(&data->tonga_mc_reg_table.mc_reg_table_entry[i],
4195 mc_reg_table_data, data->tonga_mc_reg_table.last, data->tonga_mc_reg_table.validflag);
4196
4197 return 0;
4198}
4199
4200int tonga_convert_mc_reg_table_to_smc(struct pp_hwmgr *hwmgr,
4201 SMU72_Discrete_MCRegisters *mc_reg_table)
4202{
4203 int result = 0;
4204 tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
4205 int res;
4206 uint32_t i;
4207
4208 for (i = 0; i < data->dpm_table.mclk_table.count; i++) {
4209 res = tonga_convert_mc_reg_table_entry_to_smc(
4210 hwmgr,
4211 data->dpm_table.mclk_table.dpm_levels[i].value,
4212 &mc_reg_table->data[i]
4213 );
4214
4215 if (0 != res)
4216 result = res;
4217 }
4218
4219 return result;
4220}
4221
4222int tonga_populate_initial_mc_reg_table(struct pp_hwmgr *hwmgr)
4223{
4224 int result;
4225 struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
4226
4227 memset(&data->mc_reg_table, 0x00, sizeof(SMU72_Discrete_MCRegisters));
4228 result = tonga_populate_mc_reg_address(hwmgr, &(data->mc_reg_table));
4229 PP_ASSERT_WITH_CODE(0 == result,
4230 "Failed to initialize MCRegTable for the MC register addresses!", return result;);
4231
4232 result = tonga_convert_mc_reg_table_to_smc(hwmgr, &data->mc_reg_table);
4233 PP_ASSERT_WITH_CODE(0 == result,
4234 "Failed to initialize MCRegTable for driver state!", return result;);
4235
4236 return tonga_copy_bytes_to_smc(hwmgr->smumgr, data->mc_reg_table_start,
4237 (uint8_t *)&data->mc_reg_table, sizeof(SMU72_Discrete_MCRegisters), data->sram_end);
4238}
4239
4240/**
4241 * Programs static screed detection parameters
4242 *
4243 * @param hwmgr the address of the powerplay hardware manager.
4244 * @return always 0
4245 */
4246int tonga_program_static_screen_threshold_parameters(struct pp_hwmgr *hwmgr)
4247{
4248 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
4249
4250 /* Set static screen threshold unit*/
4251 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device,
4252 CGS_IND_REG__SMC, CG_STATIC_SCREEN_PARAMETER, STATIC_SCREEN_THRESHOLD_UNIT,
4253 data->static_screen_threshold_unit);
4254 /* Set static screen threshold*/
4255 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device,
4256 CGS_IND_REG__SMC, CG_STATIC_SCREEN_PARAMETER, STATIC_SCREEN_THRESHOLD,
4257 data->static_screen_threshold);
4258
4259 return 0;
4260}
4261
4262/**
4263 * Setup display gap for glitch free memory clock switching.
4264 *
4265 * @param hwmgr the address of the powerplay hardware manager.
4266 * @return always 0
4267 */
4268int tonga_enable_display_gap(struct pp_hwmgr *hwmgr)
4269{
4270 uint32_t display_gap = cgs_read_ind_register(hwmgr->device,
4271 CGS_IND_REG__SMC, ixCG_DISPLAY_GAP_CNTL);
4272
4273 display_gap = PHM_SET_FIELD(display_gap,
4274 CG_DISPLAY_GAP_CNTL, DISP_GAP, DISPLAY_GAP_IGNORE);
4275
4276 display_gap = PHM_SET_FIELD(display_gap,
4277 CG_DISPLAY_GAP_CNTL, DISP_GAP_MCHG, DISPLAY_GAP_VBLANK);
4278
4279 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
4280 ixCG_DISPLAY_GAP_CNTL, display_gap);
4281
4282 return 0;
4283}
4284
4285/**
4286 * Programs activity state transition voting clients
4287 *
4288 * @param hwmgr the address of the powerplay hardware manager.
4289 * @return always 0
4290 */
4291int tonga_program_voting_clients(struct pp_hwmgr *hwmgr)
4292{
4293 tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend);
4294
4295 /* Clear reset for voting clients before enabling DPM */
4296 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
4297 SCLK_PWRMGT_CNTL, RESET_SCLK_CNT, 0);
4298 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
4299 SCLK_PWRMGT_CNTL, RESET_BUSY_CNT, 0);
4300
4301 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
4302 ixCG_FREQ_TRAN_VOTING_0, data->voting_rights_clients0);
4303 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
4304 ixCG_FREQ_TRAN_VOTING_1, data->voting_rights_clients1);
4305 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
4306 ixCG_FREQ_TRAN_VOTING_2, data->voting_rights_clients2);
4307 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
4308 ixCG_FREQ_TRAN_VOTING_3, data->voting_rights_clients3);
4309 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
4310 ixCG_FREQ_TRAN_VOTING_4, data->voting_rights_clients4);
4311 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
4312 ixCG_FREQ_TRAN_VOTING_5, data->voting_rights_clients5);
4313 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
4314 ixCG_FREQ_TRAN_VOTING_6, data->voting_rights_clients6);
4315 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
4316 ixCG_FREQ_TRAN_VOTING_7, data->voting_rights_clients7);
4317
4318 return 0;
4319}
4320
2377cd94
RZ
4321static void tonga_set_dpm_event_sources(struct pp_hwmgr *hwmgr, uint32_t sources)
4322{
4323 bool protection;
4324 enum DPM_EVENT_SRC src;
4325
4326 switch (sources) {
4327 default:
4328 printk(KERN_ERR "Unknown throttling event sources.");
4329 /* fall through */
4330 case 0:
4331 protection = false;
4332 /* src is unused */
4333 break;
4334 case (1 << PHM_AutoThrottleSource_Thermal):
4335 protection = true;
4336 src = DPM_EVENT_SRC_DIGITAL;
4337 break;
4338 case (1 << PHM_AutoThrottleSource_External):
4339 protection = true;
4340 src = DPM_EVENT_SRC_EXTERNAL;
4341 break;
4342 case (1 << PHM_AutoThrottleSource_External) |
4343 (1 << PHM_AutoThrottleSource_Thermal):
4344 protection = true;
4345 src = DPM_EVENT_SRC_DIGITAL_OR_EXTERNAL;
4346 break;
4347 }
4348 /* Order matters - don't enable thermal protection for the wrong source. */
4349 if (protection) {
4350 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_THERMAL_CTRL,
4351 DPM_EVENT_SRC, src);
4352 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT,
4353 THERMAL_PROTECTION_DIS,
4354 !phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
4355 PHM_PlatformCaps_ThermalController));
4356 } else
4357 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT,
4358 THERMAL_PROTECTION_DIS, 1);
4359}
4360
4361static int tonga_enable_auto_throttle_source(struct pp_hwmgr *hwmgr,
4362 PHM_AutoThrottleSource source)
4363{
4364 struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
4365
4366 if (!(data->active_auto_throttle_sources & (1 << source))) {
4367 data->active_auto_throttle_sources |= 1 << source;
4368 tonga_set_dpm_event_sources(hwmgr, data->active_auto_throttle_sources);
4369 }
4370 return 0;
4371}
4372
4373static int tonga_enable_thermal_auto_throttle(struct pp_hwmgr *hwmgr)
4374{
4375 return tonga_enable_auto_throttle_source(hwmgr, PHM_AutoThrottleSource_Thermal);
4376}
4377
4378static int tonga_disable_auto_throttle_source(struct pp_hwmgr *hwmgr,
4379 PHM_AutoThrottleSource source)
4380{
4381 struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
4382
4383 if (data->active_auto_throttle_sources & (1 << source)) {
4384 data->active_auto_throttle_sources &= ~(1 << source);
4385 tonga_set_dpm_event_sources(hwmgr, data->active_auto_throttle_sources);
4386 }
4387 return 0;
4388}
4389
4390static int tonga_disable_thermal_auto_throttle(struct pp_hwmgr *hwmgr)
4391{
4392 return tonga_disable_auto_throttle_source(hwmgr, PHM_AutoThrottleSource_Thermal);
4393}
c82baa28 4394
4395int tonga_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
4396{
4397 int tmp_result, result = 0;
4398
4399 tmp_result = tonga_check_for_dpm_stopped(hwmgr);
4400
4401 if (cf_tonga_voltage_control(hwmgr)) {
4402 tmp_result = tonga_enable_voltage_control(hwmgr);
4403 PP_ASSERT_WITH_CODE((0 == tmp_result),
4404 "Failed to enable voltage control!", result = tmp_result);
4405
4406 tmp_result = tonga_construct_voltage_tables(hwmgr);
4407 PP_ASSERT_WITH_CODE((0 == tmp_result),
4408 "Failed to contruct voltage tables!", result = tmp_result);
4409 }
4410
4411 tmp_result = tonga_initialize_mc_reg_table(hwmgr);
4412 PP_ASSERT_WITH_CODE((0 == tmp_result),
4413 "Failed to initialize MC reg table!", result = tmp_result);
4414
4415 tmp_result = tonga_program_static_screen_threshold_parameters(hwmgr);
4416 PP_ASSERT_WITH_CODE((0 == tmp_result),
4417 "Failed to program static screen threshold parameters!", result = tmp_result);
4418
4419 tmp_result = tonga_enable_display_gap(hwmgr);
4420 PP_ASSERT_WITH_CODE((0 == tmp_result),
4421 "Failed to enable display gap!", result = tmp_result);
4422
4423 tmp_result = tonga_program_voting_clients(hwmgr);
4424 PP_ASSERT_WITH_CODE((0 == tmp_result),
4425 "Failed to program voting clients!", result = tmp_result);
4426
4427 tmp_result = tonga_process_firmware_header(hwmgr);
4428 PP_ASSERT_WITH_CODE((0 == tmp_result),
4429 "Failed to process firmware header!", result = tmp_result);
4430
4431 tmp_result = tonga_initial_switch_from_arb_f0_to_f1(hwmgr);
4432 PP_ASSERT_WITH_CODE((0 == tmp_result),
4433 "Failed to initialize switch from ArbF0 to F1!", result = tmp_result);
4434
4435 tmp_result = tonga_init_smc_table(hwmgr);
4436 PP_ASSERT_WITH_CODE((0 == tmp_result),
4437 "Failed to initialize SMC table!", result = tmp_result);
4438
4439 tmp_result = tonga_init_arb_table_index(hwmgr);
4440 PP_ASSERT_WITH_CODE((0 == tmp_result),
4441 "Failed to initialize ARB table index!", result = tmp_result);
4442
2a702ccd
RZ
4443 tmp_result = tonga_populate_pm_fuses(hwmgr);
4444 PP_ASSERT_WITH_CODE((tmp_result == 0),
4445 "Failed to populate PM fuses!", result = tmp_result);
4446
c82baa28 4447 tmp_result = tonga_populate_initial_mc_reg_table(hwmgr);
4448 PP_ASSERT_WITH_CODE((0 == tmp_result),
4449 "Failed to populate initialize MC Reg table!", result = tmp_result);
4450
bbb207f3
RZ
4451 tmp_result = tonga_notify_smc_display_change(hwmgr, false);
4452 PP_ASSERT_WITH_CODE((0 == tmp_result),
4453 "Failed to notify no display!", result = tmp_result);
4454
c82baa28 4455 /* enable SCLK control */
4456 tmp_result = tonga_enable_sclk_control(hwmgr);
4457 PP_ASSERT_WITH_CODE((0 == tmp_result),
4458 "Failed to enable SCLK control!", result = tmp_result);
4459
4460 /* enable DPM */
4461 tmp_result = tonga_start_dpm(hwmgr);
4462 PP_ASSERT_WITH_CODE((0 == tmp_result),
4463 "Failed to start DPM!", result = tmp_result);
4464
2a702ccd
RZ
4465 tmp_result = tonga_enable_smc_cac(hwmgr);
4466 PP_ASSERT_WITH_CODE((tmp_result == 0),
4467 "Failed to enable SMC CAC!", result = tmp_result);
4468
4469 tmp_result = tonga_enable_power_containment(hwmgr);
4470 PP_ASSERT_WITH_CODE((tmp_result == 0),
4471 "Failed to enable power containment!", result = tmp_result);
4472
4473 tmp_result = tonga_power_control_set_level(hwmgr);
4474 PP_ASSERT_WITH_CODE((tmp_result == 0),
4475 "Failed to power control set level!", result = tmp_result);
4476
2377cd94
RZ
4477 tmp_result = tonga_enable_thermal_auto_throttle(hwmgr);
4478 PP_ASSERT_WITH_CODE((0 == tmp_result),
4479 "Failed to enable thermal auto throttle!", result = tmp_result);
4480
c82baa28 4481 return result;
4482}
4483
4484int tonga_disable_dpm_tasks(struct pp_hwmgr *hwmgr)
4485{
4486 int tmp_result, result = 0;
4487
4488 tmp_result = tonga_check_for_dpm_running(hwmgr);
4489 PP_ASSERT_WITH_CODE((0 == tmp_result),
4490 "SMC is still running!", return 0);
4491
2377cd94
RZ
4492 tmp_result = tonga_disable_thermal_auto_throttle(hwmgr);
4493 PP_ASSERT_WITH_CODE((tmp_result == 0),
4494 "Failed to disable thermal auto throttle!", result = tmp_result);
4495
c82baa28 4496 tmp_result = tonga_stop_dpm(hwmgr);
4497 PP_ASSERT_WITH_CODE((0 == tmp_result),
4498 "Failed to stop DPM!", result = tmp_result);
4499
4500 tmp_result = tonga_reset_to_default(hwmgr);
4501 PP_ASSERT_WITH_CODE((0 == tmp_result),
4502 "Failed to reset to default!", result = tmp_result);
4503
4504 return result;
4505}
4506
4507int tonga_reset_asic_tasks(struct pp_hwmgr *hwmgr)
4508{
4509 int result;
4510
4511 result = tonga_set_boot_state(hwmgr);
4512 if (0 != result)
4513 printk(KERN_ERR "[ powerplay ] Failed to reset asic via set boot state! \n");
4514
4515 return result;
4516}
4517
4518int tonga_hwmgr_backend_fini(struct pp_hwmgr *hwmgr)
4519{
92dea67d 4520 return phm_hwmgr_backend_fini(hwmgr);
c82baa28 4521}
4522
4523/**
4524 * Initializes the Volcanic Islands Hardware Manager
4525 *
4526 * @param hwmgr the address of the powerplay hardware manager.
4527 * @return 1 if success; otherwise appropriate error code.
4528 */
4529int tonga_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
4530{
4531 int result = 0;
4532 SMU72_Discrete_DpmTable *table = NULL;
76ad42c1 4533 tonga_hwmgr *data;
c82baa28 4534 pp_atomctrl_gpio_pin_assignment gpio_pin_assignment;
4535 struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
4536 phw_tonga_ulv_parm *ulv;
52b52a87 4537 struct cgs_system_info sys_info = {0};
c82baa28 4538
4539 PP_ASSERT_WITH_CODE((NULL != hwmgr),
4540 "Invalid Parameter!", return -1;);
4541
76ad42c1
EH
4542 data = kzalloc(sizeof(struct tonga_hwmgr), GFP_KERNEL);
4543 if (data == NULL)
4544 return -ENOMEM;
4545
4546 hwmgr->backend = data;
4547
ed5121a3 4548 data->dll_defaule_on = false;
c82baa28 4549 data->sram_end = SMC_RAM_END;
4550
4551 data->activity_target[0] = PPTONGA_TARGETACTIVITY_DFLT;
4552 data->activity_target[1] = PPTONGA_TARGETACTIVITY_DFLT;
4553 data->activity_target[2] = PPTONGA_TARGETACTIVITY_DFLT;
4554 data->activity_target[3] = PPTONGA_TARGETACTIVITY_DFLT;
4555 data->activity_target[4] = PPTONGA_TARGETACTIVITY_DFLT;
4556 data->activity_target[5] = PPTONGA_TARGETACTIVITY_DFLT;
4557 data->activity_target[6] = PPTONGA_TARGETACTIVITY_DFLT;
4558 data->activity_target[7] = PPTONGA_TARGETACTIVITY_DFLT;
4559
4560 data->vddc_vddci_delta = VDDC_VDDCI_DELTA;
4561 data->vddc_vddgfx_delta = VDDC_VDDGFX_DELTA;
4562 data->mclk_activity_target = PPTONGA_MCLK_TARGETACTIVITY_DFLT;
4563
4564 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
4565 PHM_PlatformCaps_DisableVoltageIsland);
4566
4567 data->sclk_dpm_key_disabled = 0;
4568 data->mclk_dpm_key_disabled = 0;
4569 data->pcie_dpm_key_disabled = 0;
4570 data->pcc_monitor_enabled = 0;
4571
4572 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
4573 PHM_PlatformCaps_UnTabledHardwareInterface);
4574
4575 data->gpio_debug = 0;
4576 data->engine_clock_data = 0;
4577 data->memory_clock_data = 0;
4578 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
4579 PHM_PlatformCaps_DynamicPatchPowerState);
4580
4581 /* need to set voltage control types before EVV patching*/
4582 data->voltage_control = TONGA_VOLTAGE_CONTROL_NONE;
4583 data->vdd_ci_control = TONGA_VOLTAGE_CONTROL_NONE;
4584 data->vdd_gfx_control = TONGA_VOLTAGE_CONTROL_NONE;
4585 data->mvdd_control = TONGA_VOLTAGE_CONTROL_NONE;
a2fb4934 4586 data->force_pcie_gen = PP_PCIEGenInvalid;
c82baa28 4587
3ec2cdb8 4588 if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr,
c82baa28 4589 VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_SVID2)) {
4590 data->voltage_control = TONGA_VOLTAGE_CONTROL_BY_SVID2;
4591 }
4592
4593 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
4594 PHM_PlatformCaps_ControlVDDGFX)) {
3ec2cdb8 4595 if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr,
c82baa28 4596 VOLTAGE_TYPE_VDDGFX, VOLTAGE_OBJ_SVID2)) {
4597 data->vdd_gfx_control = TONGA_VOLTAGE_CONTROL_BY_SVID2;
4598 }
4599 }
4600
4601 if (TONGA_VOLTAGE_CONTROL_NONE == data->vdd_gfx_control) {
4602 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
4603 PHM_PlatformCaps_ControlVDDGFX);
4604 }
4605
4606 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
4607 PHM_PlatformCaps_EnableMVDDControl)) {
3ec2cdb8 4608 if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr,
c82baa28 4609 VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_GPIO_LUT)) {
4610 data->mvdd_control = TONGA_VOLTAGE_CONTROL_BY_GPIO;
4611 }
4612 }
4613
4614 if (TONGA_VOLTAGE_CONTROL_NONE == data->mvdd_control) {
4615 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
4616 PHM_PlatformCaps_EnableMVDDControl);
4617 }
4618
4619 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
4620 PHM_PlatformCaps_ControlVDDCI)) {
3ec2cdb8 4621 if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr,
c82baa28 4622 VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_GPIO_LUT))
4623 data->vdd_ci_control = TONGA_VOLTAGE_CONTROL_BY_GPIO;
3ec2cdb8 4624 else if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr,
c82baa28 4625 VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_SVID2))
4626 data->vdd_ci_control = TONGA_VOLTAGE_CONTROL_BY_SVID2;
4627 }
4628
4629 if (TONGA_VOLTAGE_CONTROL_NONE == data->vdd_ci_control)
4630 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
4631 PHM_PlatformCaps_ControlVDDCI);
4632
4633 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
4634 PHM_PlatformCaps_TablelessHardwareInterface);
4635
4636 if (pptable_info->cac_dtp_table->usClockStretchAmount != 0)
4637 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
4638 PHM_PlatformCaps_ClockStretcher);
4639
4640 /* Initializes DPM default values*/
4641 tonga_initialize_dpm_defaults(hwmgr);
4642
4643 /* Get leakage voltage based on leakage ID.*/
4644 PP_ASSERT_WITH_CODE((0 == tonga_get_evv_voltage(hwmgr)),
4645 "Get EVV Voltage Failed. Abort Driver loading!", return -1);
4646
4647 tonga_complete_dependency_tables(hwmgr);
4648
4649 /* Parse pptable data read from VBIOS*/
4650 tonga_set_private_var_based_on_pptale(hwmgr);
4651
4652 /* ULV Support*/
4653 ulv = &(data->ulv);
ed5121a3 4654 ulv->ulv_supported = false;
c82baa28 4655
4656 /* Initalize Dynamic State Adjustment Rule Settings*/
4657 result = tonga_initializa_dynamic_state_adjustment_rule_settings(hwmgr);
aa22ae4b
AD
4658 if (result)
4659 printk(KERN_ERR "[ powerplay ] tonga_initializa_dynamic_state_adjustment_rule_settings failed!\n");
ed5121a3 4660 data->uvd_enabled = false;
c82baa28 4661
4662 table = &(data->smc_state_table);
4663
4664 /*
4665 * if ucGPIO_ID=VDDC_PCC_GPIO_PINID in GPIO_LUTable,
4666 * Peak Current Control feature is enabled and we should program PCC HW register
4667 */
e013c91c 4668 if (atomctrl_get_pp_assign_pin(hwmgr, VDDC_PCC_GPIO_PINID, &gpio_pin_assignment)) {
c82baa28 4669 uint32_t temp_reg = cgs_read_ind_register(hwmgr->device,
4670 CGS_IND_REG__SMC, ixCNB_PWRMGT_CNTL);
4671
4672 switch (gpio_pin_assignment.uc_gpio_pin_bit_shift) {
4673 case 0:
4674 temp_reg = PHM_SET_FIELD(temp_reg,
4675 CNB_PWRMGT_CNTL, GNB_SLOW_MODE, 0x1);
4676 break;
4677 case 1:
4678 temp_reg = PHM_SET_FIELD(temp_reg,
4679 CNB_PWRMGT_CNTL, GNB_SLOW_MODE, 0x2);
4680 break;
4681 case 2:
4682 temp_reg = PHM_SET_FIELD(temp_reg,
4683 CNB_PWRMGT_CNTL, GNB_SLOW, 0x1);
4684 break;
4685 case 3:
4686 temp_reg = PHM_SET_FIELD(temp_reg,
4687 CNB_PWRMGT_CNTL, FORCE_NB_PS1, 0x1);
4688 break;
4689 case 4:
4690 temp_reg = PHM_SET_FIELD(temp_reg,
4691 CNB_PWRMGT_CNTL, DPM_ENABLED, 0x1);
4692 break;
4693 default:
4694 printk(KERN_ERR "[ powerplay ] Failed to setup PCC HW register! \
4695 Wrong GPIO assigned for VDDC_PCC_GPIO_PINID! \n");
4696 break;
4697 }
4698 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
4699 ixCNB_PWRMGT_CNTL, temp_reg);
4700 }
4701
4702 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
4703 PHM_PlatformCaps_EnableSMU7ThermalManagement);
4704 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
4705 PHM_PlatformCaps_SMU7);
4706
ed5121a3 4707 data->vddc_phase_shed_control = false;
c82baa28 4708
3d5afb41
AD
4709 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
4710 PHM_PlatformCaps_UVDPowerGating);
f997e6f2
AD
4711 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
4712 PHM_PlatformCaps_VCEPowerGating);
52b52a87
AD
4713 sys_info.size = sizeof(struct cgs_system_info);
4714 sys_info.info_id = CGS_SYSTEM_INFO_PG_FLAGS;
4715 result = cgs_query_system_info(hwmgr->device, &sys_info);
4716 if (!result) {
4717 if (sys_info.value & AMD_PG_SUPPORT_UVD)
4718 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
4719 PHM_PlatformCaps_UVDPowerGating);
4720 if (sys_info.value & AMD_PG_SUPPORT_VCE)
4721 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
4722 PHM_PlatformCaps_VCEPowerGating);
4723 }
834b694c 4724
c82baa28 4725 if (0 == result) {
ed5121a3 4726 data->is_tlu_enabled = false;
c82baa28 4727 hwmgr->platform_descriptor.hardwareActivityPerformanceLevels =
4728 TONGA_MAX_HARDWARE_POWERLEVELS;
4729 hwmgr->platform_descriptor.hardwarePerformanceLevels = 2;
4730 hwmgr->platform_descriptor.minimumClocksReductionPercentage = 50;
4731
834b694c
AD
4732 sys_info.size = sizeof(struct cgs_system_info);
4733 sys_info.info_id = CGS_SYSTEM_INFO_PCIE_GEN_INFO;
4734 result = cgs_query_system_info(hwmgr->device, &sys_info);
4735 if (result)
d1371f8c 4736 data->pcie_gen_cap = AMDGPU_DEFAULT_PCIE_GEN_MASK;
834b694c
AD
4737 else
4738 data->pcie_gen_cap = (uint32_t)sys_info.value;
4739 if (data->pcie_gen_cap & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)
4740 data->pcie_spc_cap = 20;
4741 sys_info.size = sizeof(struct cgs_system_info);
4742 sys_info.info_id = CGS_SYSTEM_INFO_PCIE_MLW;
4743 result = cgs_query_system_info(hwmgr->device, &sys_info);
4744 if (result)
d1371f8c 4745 data->pcie_lane_cap = AMDGPU_DEFAULT_PCIE_MLW_MASK;
834b694c
AD
4746 else
4747 data->pcie_lane_cap = (uint32_t)sys_info.value;
c82baa28 4748 } else {
4749 /* Ignore return value in here, we are cleaning up a mess. */
4750 tonga_hwmgr_backend_fini(hwmgr);
4751 }
4752
4753 return result;
4754}
4755
4756static int tonga_force_dpm_level(struct pp_hwmgr *hwmgr,
4757 enum amd_dpm_forced_level level)
4758{
4759 int ret = 0;
4760
4761 switch (level) {
4762 case AMD_DPM_FORCED_LEVEL_HIGH:
4763 ret = tonga_force_dpm_highest(hwmgr);
4764 if (ret)
4765 return ret;
4766 break;
4767 case AMD_DPM_FORCED_LEVEL_LOW:
4768 ret = tonga_force_dpm_lowest(hwmgr);
4769 if (ret)
4770 return ret;
4771 break;
4772 case AMD_DPM_FORCED_LEVEL_AUTO:
4773 ret = tonga_unforce_dpm_levels(hwmgr);
4774 if (ret)
4775 return ret;
4776 break;
4777 default:
4778 break;
4779 }
4780
4781 hwmgr->dpm_level = level;
4782 return ret;
4783}
4784
4785static int tonga_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
4786 struct pp_power_state *prequest_ps,
4787 const struct pp_power_state *pcurrent_ps)
4788{
4789 struct tonga_power_state *tonga_ps =
4790 cast_phw_tonga_power_state(&prequest_ps->hardware);
4791
4792 uint32_t sclk;
4793 uint32_t mclk;
4794 struct PP_Clocks minimum_clocks = {0};
4795 bool disable_mclk_switching;
4796 bool disable_mclk_switching_for_frame_lock;
4797 struct cgs_display_info info = {0};
4798 const struct phm_clock_and_voltage_limits *max_limits;
4799 uint32_t i;
4800 tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
4801 struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
4802
4803 int32_t count;
4804 int32_t stable_pstate_sclk = 0, stable_pstate_mclk = 0;
4805
4806 data->battery_state = (PP_StateUILabel_Battery == prequest_ps->classification.ui_label);
4807
4808 PP_ASSERT_WITH_CODE(tonga_ps->performance_level_count == 2,
4809 "VI should always have 2 performance levels",
4810 );
4811
4812 max_limits = (PP_PowerSource_AC == hwmgr->power_source) ?
4813 &(hwmgr->dyn_state.max_clock_voltage_on_ac) :
4814 &(hwmgr->dyn_state.max_clock_voltage_on_dc);
4815
4816 if (PP_PowerSource_DC == hwmgr->power_source) {
4817 for (i = 0; i < tonga_ps->performance_level_count; i++) {
4818 if (tonga_ps->performance_levels[i].memory_clock > max_limits->mclk)
4819 tonga_ps->performance_levels[i].memory_clock = max_limits->mclk;
4820 if (tonga_ps->performance_levels[i].engine_clock > max_limits->sclk)
4821 tonga_ps->performance_levels[i].engine_clock = max_limits->sclk;
4822 }
4823 }
4824
4825 tonga_ps->vce_clocks.EVCLK = hwmgr->vce_arbiter.evclk;
4826 tonga_ps->vce_clocks.ECCLK = hwmgr->vce_arbiter.ecclk;
4827
4828 tonga_ps->acp_clk = hwmgr->acp_arbiter.acpclk;
4829
4830 cgs_get_active_displays_info(hwmgr->device, &info);
4831
4832 /*TO DO result = PHM_CheckVBlankTime(hwmgr, &vblankTooShort);*/
4833
4834 /* TO DO GetMinClockSettings(hwmgr->pPECI, &minimum_clocks); */
4835
4836 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState)) {
4837
4838 max_limits = &(hwmgr->dyn_state.max_clock_voltage_on_ac);
4839 stable_pstate_sclk = (max_limits->sclk * 75) / 100;
4840
4841 for (count = pptable_info->vdd_dep_on_sclk->count-1; count >= 0; count--) {
4842 if (stable_pstate_sclk >= pptable_info->vdd_dep_on_sclk->entries[count].clk) {
4843 stable_pstate_sclk = pptable_info->vdd_dep_on_sclk->entries[count].clk;
4844 break;
4845 }
4846 }
4847
4848 if (count < 0)
4849 stable_pstate_sclk = pptable_info->vdd_dep_on_sclk->entries[0].clk;
4850
4851 stable_pstate_mclk = max_limits->mclk;
4852
4853 minimum_clocks.engineClock = stable_pstate_sclk;
4854 minimum_clocks.memoryClock = stable_pstate_mclk;
4855 }
4856
4857 if (minimum_clocks.engineClock < hwmgr->gfx_arbiter.sclk)
4858 minimum_clocks.engineClock = hwmgr->gfx_arbiter.sclk;
4859
4860 if (minimum_clocks.memoryClock < hwmgr->gfx_arbiter.mclk)
4861 minimum_clocks.memoryClock = hwmgr->gfx_arbiter.mclk;
4862
4863 tonga_ps->sclk_threshold = hwmgr->gfx_arbiter.sclk_threshold;
4864
4865 if (0 != hwmgr->gfx_arbiter.sclk_over_drive) {
4866 PP_ASSERT_WITH_CODE((hwmgr->gfx_arbiter.sclk_over_drive <= hwmgr->platform_descriptor.overdriveLimit.engineClock),
4867 "Overdrive sclk exceeds limit",
4868 hwmgr->gfx_arbiter.sclk_over_drive = hwmgr->platform_descriptor.overdriveLimit.engineClock);
4869
4870 if (hwmgr->gfx_arbiter.sclk_over_drive >= hwmgr->gfx_arbiter.sclk)
4871 tonga_ps->performance_levels[1].engine_clock = hwmgr->gfx_arbiter.sclk_over_drive;
4872 }
4873
4874 if (0 != hwmgr->gfx_arbiter.mclk_over_drive) {
4875 PP_ASSERT_WITH_CODE((hwmgr->gfx_arbiter.mclk_over_drive <= hwmgr->platform_descriptor.overdriveLimit.memoryClock),
4876 "Overdrive mclk exceeds limit",
4877 hwmgr->gfx_arbiter.mclk_over_drive = hwmgr->platform_descriptor.overdriveLimit.memoryClock);
4878
4879 if (hwmgr->gfx_arbiter.mclk_over_drive >= hwmgr->gfx_arbiter.mclk)
4880 tonga_ps->performance_levels[1].memory_clock = hwmgr->gfx_arbiter.mclk_over_drive;
4881 }
4882
4883 disable_mclk_switching_for_frame_lock = phm_cap_enabled(
4884 hwmgr->platform_descriptor.platformCaps,
4885 PHM_PlatformCaps_DisableMclkSwitchingForFrameLock);
4886
4887 disable_mclk_switching = (1 < info.display_count) ||
4888 disable_mclk_switching_for_frame_lock;
4889
4890 sclk = tonga_ps->performance_levels[0].engine_clock;
4891 mclk = tonga_ps->performance_levels[0].memory_clock;
4892
4893 if (disable_mclk_switching)
4894 mclk = tonga_ps->performance_levels[tonga_ps->performance_level_count - 1].memory_clock;
4895
4896 if (sclk < minimum_clocks.engineClock)
4897 sclk = (minimum_clocks.engineClock > max_limits->sclk) ? max_limits->sclk : minimum_clocks.engineClock;
4898
4899 if (mclk < minimum_clocks.memoryClock)
4900 mclk = (minimum_clocks.memoryClock > max_limits->mclk) ? max_limits->mclk : minimum_clocks.memoryClock;
4901
4902 tonga_ps->performance_levels[0].engine_clock = sclk;
4903 tonga_ps->performance_levels[0].memory_clock = mclk;
4904
4905 tonga_ps->performance_levels[1].engine_clock =
4906 (tonga_ps->performance_levels[1].engine_clock >= tonga_ps->performance_levels[0].engine_clock) ?
4907 tonga_ps->performance_levels[1].engine_clock :
4908 tonga_ps->performance_levels[0].engine_clock;
4909
4910 if (disable_mclk_switching) {
4911 if (mclk < tonga_ps->performance_levels[1].memory_clock)
4912 mclk = tonga_ps->performance_levels[1].memory_clock;
4913
4914 tonga_ps->performance_levels[0].memory_clock = mclk;
4915 tonga_ps->performance_levels[1].memory_clock = mclk;
4916 } else {
4917 if (tonga_ps->performance_levels[1].memory_clock < tonga_ps->performance_levels[0].memory_clock)
4918 tonga_ps->performance_levels[1].memory_clock = tonga_ps->performance_levels[0].memory_clock;
4919 }
4920
4921 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState)) {
4922 for (i=0; i < tonga_ps->performance_level_count; i++) {
4923 tonga_ps->performance_levels[i].engine_clock = stable_pstate_sclk;
4924 tonga_ps->performance_levels[i].memory_clock = stable_pstate_mclk;
4925 tonga_ps->performance_levels[i].pcie_gen = data->pcie_gen_performance.max;
4926 tonga_ps->performance_levels[i].pcie_lane = data->pcie_gen_performance.max;
4927 }
4928 }
4929
4930 return 0;
4931}
4932
4933int tonga_get_power_state_size(struct pp_hwmgr *hwmgr)
4934{
4935 return sizeof(struct tonga_power_state);
4936}
4937
4938static int tonga_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low)
4939{
4940 struct pp_power_state *ps;
4941 struct tonga_power_state *tonga_ps;
4942
4943 if (hwmgr == NULL)
4944 return -EINVAL;
4945
4946 ps = hwmgr->request_ps;
4947
4948 if (ps == NULL)
4949 return -EINVAL;
4950
4951 tonga_ps = cast_phw_tonga_power_state(&ps->hardware);
4952
4953 if (low)
4954 return tonga_ps->performance_levels[0].memory_clock;
4955 else
4956 return tonga_ps->performance_levels[tonga_ps->performance_level_count-1].memory_clock;
4957}
4958
4959static int tonga_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low)
4960{
4961 struct pp_power_state *ps;
4962 struct tonga_power_state *tonga_ps;
4963
4964 if (hwmgr == NULL)
4965 return -EINVAL;
4966
4967 ps = hwmgr->request_ps;
4968
4969 if (ps == NULL)
4970 return -EINVAL;
4971
4972 tonga_ps = cast_phw_tonga_power_state(&ps->hardware);
4973
4974 if (low)
4975 return tonga_ps->performance_levels[0].engine_clock;
4976 else
4977 return tonga_ps->performance_levels[tonga_ps->performance_level_count-1].engine_clock;
4978}
4979
4980static uint16_t tonga_get_current_pcie_speed(
4981 struct pp_hwmgr *hwmgr)
4982{
4983 uint32_t speed_cntl = 0;
4984
4985 speed_cntl = cgs_read_ind_register(hwmgr->device,
4986 CGS_IND_REG__PCIE,
4987 ixPCIE_LC_SPEED_CNTL);
4988 return((uint16_t)PHM_GET_FIELD(speed_cntl,
4989 PCIE_LC_SPEED_CNTL, LC_CURRENT_DATA_RATE));
4990}
4991
4992static int tonga_get_current_pcie_lane_number(
4993 struct pp_hwmgr *hwmgr)
4994{
4995 uint32_t link_width;
4996
4997 link_width = PHM_READ_INDIRECT_FIELD(hwmgr->device,
4998 CGS_IND_REG__PCIE,
4999 PCIE_LC_LINK_WIDTH_CNTL,
5000 LC_LINK_WIDTH_RD);
5001
5002 PP_ASSERT_WITH_CODE((7 >= link_width),
5003 "Invalid PCIe lane width!", return 0);
5004
5005 return decode_pcie_lane_width(link_width);
5006}
5007
5008static int tonga_dpm_patch_boot_state(struct pp_hwmgr *hwmgr,
5009 struct pp_hw_power_state *hw_ps)
5010{
5011 struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
5012 struct tonga_power_state *ps = (struct tonga_power_state *)hw_ps;
5013 ATOM_FIRMWARE_INFO_V2_2 *fw_info;
5014 uint16_t size;
5015 uint8_t frev, crev;
5016 int index = GetIndexIntoMasterTable(DATA, FirmwareInfo);
5017
5018 /* First retrieve the Boot clocks and VDDC from the firmware info table.
5019 * We assume here that fw_info is unchanged if this call fails.
5020 */
5021 fw_info = (ATOM_FIRMWARE_INFO_V2_2 *)cgs_atom_get_data_table(
5022 hwmgr->device, index,
5023 &size, &frev, &crev);
5024 if (!fw_info)
5025 /* During a test, there is no firmware info table. */
5026 return 0;
5027
5028 /* Patch the state. */
5029 data->vbios_boot_state.sclk_bootup_value = le32_to_cpu(fw_info->ulDefaultEngineClock);
5030 data->vbios_boot_state.mclk_bootup_value = le32_to_cpu(fw_info->ulDefaultMemoryClock);
5031 data->vbios_boot_state.mvdd_bootup_value = le16_to_cpu(fw_info->usBootUpMVDDCVoltage);
5032 data->vbios_boot_state.vddc_bootup_value = le16_to_cpu(fw_info->usBootUpVDDCVoltage);
5033 data->vbios_boot_state.vddci_bootup_value = le16_to_cpu(fw_info->usBootUpVDDCIVoltage);
5034 data->vbios_boot_state.pcie_gen_bootup_value = tonga_get_current_pcie_speed(hwmgr);
5035 data->vbios_boot_state.pcie_lane_bootup_value =
5036 (uint16_t)tonga_get_current_pcie_lane_number(hwmgr);
5037
5038 /* set boot power state */
5039 ps->performance_levels[0].memory_clock = data->vbios_boot_state.mclk_bootup_value;
5040 ps->performance_levels[0].engine_clock = data->vbios_boot_state.sclk_bootup_value;
5041 ps->performance_levels[0].pcie_gen = data->vbios_boot_state.pcie_gen_bootup_value;
5042 ps->performance_levels[0].pcie_lane = data->vbios_boot_state.pcie_lane_bootup_value;
5043
5044 return 0;
5045}
5046
5047static int tonga_get_pp_table_entry_callback_func(struct pp_hwmgr *hwmgr,
5048 void *state, struct pp_power_state *power_state,
5049 void *pp_table, uint32_t classification_flag)
5050{
5051 struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
5052
5053 struct tonga_power_state *tonga_ps =
5054 (struct tonga_power_state *)(&(power_state->hardware));
5055
5056 struct tonga_performance_level *performance_level;
5057
5058 ATOM_Tonga_State *state_entry = (ATOM_Tonga_State *)state;
5059
5060 ATOM_Tonga_POWERPLAYTABLE *powerplay_table =
5061 (ATOM_Tonga_POWERPLAYTABLE *)pp_table;
5062
5063 ATOM_Tonga_SCLK_Dependency_Table *sclk_dep_table =
5064 (ATOM_Tonga_SCLK_Dependency_Table *)
c9fe74e6 5065 (((unsigned long)powerplay_table) +
c82baa28 5066 le16_to_cpu(powerplay_table->usSclkDependencyTableOffset));
5067
5068 ATOM_Tonga_MCLK_Dependency_Table *mclk_dep_table =
5069 (ATOM_Tonga_MCLK_Dependency_Table *)
c9fe74e6 5070 (((unsigned long)powerplay_table) +
c82baa28 5071 le16_to_cpu(powerplay_table->usMclkDependencyTableOffset));
5072
5073 /* The following fields are not initialized here: id orderedList allStatesList */
5074 power_state->classification.ui_label =
5075 (le16_to_cpu(state_entry->usClassification) &
5076 ATOM_PPLIB_CLASSIFICATION_UI_MASK) >>
5077 ATOM_PPLIB_CLASSIFICATION_UI_SHIFT;
5078 power_state->classification.flags = classification_flag;
5079 /* NOTE: There is a classification2 flag in BIOS that is not being used right now */
5080
5081 power_state->classification.temporary_state = false;
5082 power_state->classification.to_be_deleted = false;
5083
5084 power_state->validation.disallowOnDC =
5085 (0 != (le32_to_cpu(state_entry->ulCapsAndSettings) & ATOM_Tonga_DISALLOW_ON_DC));
5086
5087 power_state->pcie.lanes = 0;
5088
5089 power_state->display.disableFrameModulation = false;
5090 power_state->display.limitRefreshrate = false;
5091 power_state->display.enableVariBright =
5092 (0 != (le32_to_cpu(state_entry->ulCapsAndSettings) & ATOM_Tonga_ENABLE_VARIBRIGHT));
5093
5094 power_state->validation.supportedPowerLevels = 0;
5095 power_state->uvd_clocks.VCLK = 0;
5096 power_state->uvd_clocks.DCLK = 0;
5097 power_state->temperatures.min = 0;
5098 power_state->temperatures.max = 0;
5099
5100 performance_level = &(tonga_ps->performance_levels
5101 [tonga_ps->performance_level_count++]);
5102
5103 PP_ASSERT_WITH_CODE(
5104 (tonga_ps->performance_level_count < SMU72_MAX_LEVELS_GRAPHICS),
5105 "Performance levels exceeds SMC limit!",
5106 return -1);
5107
5108 PP_ASSERT_WITH_CODE(
5109 (tonga_ps->performance_level_count <=
5110 hwmgr->platform_descriptor.hardwareActivityPerformanceLevels),
5111 "Performance levels exceeds Driver limit!",
5112 return -1);
5113
5114 /* Performance levels are arranged from low to high. */
5115 performance_level->memory_clock =
5116 le32_to_cpu(mclk_dep_table->entries[state_entry->ucMemoryClockIndexLow].ulMclk);
5117
5118 performance_level->engine_clock =
5119 le32_to_cpu(sclk_dep_table->entries[state_entry->ucEngineClockIndexLow].ulSclk);
5120
5121 performance_level->pcie_gen = get_pcie_gen_support(
5122 data->pcie_gen_cap,
5123 state_entry->ucPCIEGenLow);
5124
5125 performance_level->pcie_lane = get_pcie_lane_support(
5126 data->pcie_lane_cap,
5127 state_entry->ucPCIELaneHigh);
5128
5129 performance_level =
5130 &(tonga_ps->performance_levels[tonga_ps->performance_level_count++]);
5131
5132 performance_level->memory_clock =
5133 le32_to_cpu(mclk_dep_table->entries[state_entry->ucMemoryClockIndexHigh].ulMclk);
5134
5135 performance_level->engine_clock =
5136 le32_to_cpu(sclk_dep_table->entries[state_entry->ucEngineClockIndexHigh].ulSclk);
5137
5138 performance_level->pcie_gen = get_pcie_gen_support(
5139 data->pcie_gen_cap,
5140 state_entry->ucPCIEGenHigh);
5141
5142 performance_level->pcie_lane = get_pcie_lane_support(
5143 data->pcie_lane_cap,
5144 state_entry->ucPCIELaneHigh);
5145
5146 return 0;
5147}
5148
5149static int tonga_get_pp_table_entry(struct pp_hwmgr *hwmgr,
5150 unsigned long entry_index, struct pp_power_state *ps)
5151{
5152 int result;
5153 struct tonga_power_state *tonga_ps;
5154 struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
5155
5156 struct phm_ppt_v1_information *table_info =
5157 (struct phm_ppt_v1_information *)(hwmgr->pptable);
5158
5159 struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table =
5160 table_info->vdd_dep_on_mclk;
5161
5162 ps->hardware.magic = PhwTonga_Magic;
5163
5164 tonga_ps = cast_phw_tonga_power_state(&(ps->hardware));
5165
e1aa5715 5166 result = get_powerplay_table_entry_v1_0(hwmgr, entry_index, ps,
c82baa28 5167 tonga_get_pp_table_entry_callback_func);
5168
5169 /* This is the earliest time we have all the dependency table and the VBIOS boot state
5170 * as PP_Tables_GetPowerPlayTableEntry retrieves the VBIOS boot state
5171 * if there is only one VDDCI/MCLK level, check if it's the same as VBIOS boot state
5172 */
5173 if (dep_mclk_table != NULL && dep_mclk_table->count == 1) {
5174 if (dep_mclk_table->entries[0].clk !=
5175 data->vbios_boot_state.mclk_bootup_value)
5176 printk(KERN_ERR "Single MCLK entry VDDCI/MCLK dependency table "
5177 "does not match VBIOS boot MCLK level");
5178 if (dep_mclk_table->entries[0].vddci !=
5179 data->vbios_boot_state.vddci_bootup_value)
5180 printk(KERN_ERR "Single VDDCI entry VDDCI/MCLK dependency table "
5181 "does not match VBIOS boot VDDCI level");
5182 }
5183
5184 /* set DC compatible flag if this state supports DC */
5185 if (!ps->validation.disallowOnDC)
5186 tonga_ps->dc_compatible = true;
5187
5188 if (ps->classification.flags & PP_StateClassificationFlag_ACPI)
5189 data->acpi_pcie_gen = tonga_ps->performance_levels[0].pcie_gen;
5190 else if (ps->classification.flags & PP_StateClassificationFlag_Boot) {
5191 if (data->bacos.best_match == 0xffff) {
5192 /* For V.I. use boot state as base BACO state */
5193 data->bacos.best_match = PP_StateClassificationFlag_Boot;
5194 data->bacos.performance_level = tonga_ps->performance_levels[0];
5195 }
5196 }
5197
5198 tonga_ps->uvd_clocks.VCLK = ps->uvd_clocks.VCLK;
5199 tonga_ps->uvd_clocks.DCLK = ps->uvd_clocks.DCLK;
5200
5201 if (!result) {
5202 uint32_t i;
5203
5204 switch (ps->classification.ui_label) {
5205 case PP_StateUILabel_Performance:
5206 data->use_pcie_performance_levels = true;
5207
5208 for (i = 0; i < tonga_ps->performance_level_count; i++) {
5209 if (data->pcie_gen_performance.max <
5210 tonga_ps->performance_levels[i].pcie_gen)
5211 data->pcie_gen_performance.max =
5212 tonga_ps->performance_levels[i].pcie_gen;
5213
5214 if (data->pcie_gen_performance.min >
5215 tonga_ps->performance_levels[i].pcie_gen)
5216 data->pcie_gen_performance.min =
5217 tonga_ps->performance_levels[i].pcie_gen;
5218
5219 if (data->pcie_lane_performance.max <
5220 tonga_ps->performance_levels[i].pcie_lane)
5221 data->pcie_lane_performance.max =
5222 tonga_ps->performance_levels[i].pcie_lane;
5223
5224 if (data->pcie_lane_performance.min >
5225 tonga_ps->performance_levels[i].pcie_lane)
5226 data->pcie_lane_performance.min =
5227 tonga_ps->performance_levels[i].pcie_lane;
5228 }
5229 break;
5230 case PP_StateUILabel_Battery:
5231 data->use_pcie_power_saving_levels = true;
5232
5233 for (i = 0; i < tonga_ps->performance_level_count; i++) {
5234 if (data->pcie_gen_power_saving.max <
5235 tonga_ps->performance_levels[i].pcie_gen)
5236 data->pcie_gen_power_saving.max =
5237 tonga_ps->performance_levels[i].pcie_gen;
5238
5239 if (data->pcie_gen_power_saving.min >
5240 tonga_ps->performance_levels[i].pcie_gen)
5241 data->pcie_gen_power_saving.min =
5242 tonga_ps->performance_levels[i].pcie_gen;
5243
5244 if (data->pcie_lane_power_saving.max <
5245 tonga_ps->performance_levels[i].pcie_lane)
5246 data->pcie_lane_power_saving.max =
5247 tonga_ps->performance_levels[i].pcie_lane;
5248
5249 if (data->pcie_lane_power_saving.min >
5250 tonga_ps->performance_levels[i].pcie_lane)
5251 data->pcie_lane_power_saving.min =
5252 tonga_ps->performance_levels[i].pcie_lane;
5253 }
5254 break;
5255 default:
5256 break;
5257 }
5258 }
5259 return 0;
5260}
5261
5262static void
5263tonga_print_current_perforce_level(struct pp_hwmgr *hwmgr, struct seq_file *m)
5264{
ab4f4b14 5265 uint32_t sclk, mclk, activity_percent;
9c5f8de6
RZ
5266 uint32_t offset;
5267 struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
c82baa28 5268
5269 smum_send_msg_to_smc(hwmgr->smumgr, (PPSMC_Msg)(PPSMC_MSG_API_GetSclkFrequency));
5270
5271 sclk = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0);
5272
5273 smum_send_msg_to_smc(hwmgr->smumgr, (PPSMC_Msg)(PPSMC_MSG_API_GetMclkFrequency));
5274
5275 mclk = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0);
5276 seq_printf(m, "\n [ mclk ]: %u MHz\n\n [ sclk ]: %u MHz\n", mclk/100, sclk/100);
9c5f8de6 5277
9c5f8de6 5278 offset = data->soft_regs_start + offsetof(SMU72_SoftRegisters, AverageGraphicsActivity);
ab4f4b14
RZ
5279 activity_percent = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset);
5280 activity_percent += 0x80;
5281 activity_percent >>= 8;
9c5f8de6 5282
ab4f4b14 5283 seq_printf(m, "\n [GPU load]: %u%%\n\n", activity_percent > 100 ? 100 : activity_percent);
9c5f8de6 5284
d27d4941
RZ
5285 seq_printf(m, "uvd %sabled\n", data->uvd_power_gated ? "dis" : "en");
5286
5287 seq_printf(m, "vce %sabled\n", data->vce_power_gated ? "dis" : "en");
c82baa28 5288}
5289
5290static int tonga_find_dpm_states_clocks_in_dpm_table(struct pp_hwmgr *hwmgr, const void *input)
5291{
5292 const struct phm_set_power_state_input *states = (const struct phm_set_power_state_input *)input;
5293 const struct tonga_power_state *tonga_ps = cast_const_phw_tonga_power_state(states->pnew_state);
5294 struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
5295 struct tonga_single_dpm_table *psclk_table = &(data->dpm_table.sclk_table);
5296 uint32_t sclk = tonga_ps->performance_levels[tonga_ps->performance_level_count-1].engine_clock;
5297 struct tonga_single_dpm_table *pmclk_table = &(data->dpm_table.mclk_table);
5298 uint32_t mclk = tonga_ps->performance_levels[tonga_ps->performance_level_count-1].memory_clock;
5299 struct PP_Clocks min_clocks = {0};
5300 uint32_t i;
5301 struct cgs_display_info info = {0};
5302
5303 data->need_update_smu7_dpm_table = 0;
5304
5305 for (i = 0; i < psclk_table->count; i++) {
5306 if (sclk == psclk_table->dpm_levels[i].value)
5307 break;
5308 }
5309
5310 if (i >= psclk_table->count)
5311 data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_SCLK;
5312 else {
5313 /* TODO: Check SCLK in DAL's minimum clocks in case DeepSleep divider update is required.*/
5314 if(data->display_timing.min_clock_insr != min_clocks.engineClockInSR)
5315 data->need_update_smu7_dpm_table |= DPMTABLE_UPDATE_SCLK;
5316 }
5317
5318 for (i=0; i < pmclk_table->count; i++) {
5319 if (mclk == pmclk_table->dpm_levels[i].value)
5320 break;
5321 }
5322
5323 if (i >= pmclk_table->count)
5324 data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_MCLK;
5325
5326 cgs_get_active_displays_info(hwmgr->device, &info);
5327
5328 if (data->display_timing.num_existing_displays != info.display_count)
5329 data->need_update_smu7_dpm_table |= DPMTABLE_UPDATE_MCLK;
5330
5331 return 0;
5332}
5333
5334static uint16_t tonga_get_maximum_link_speed(struct pp_hwmgr *hwmgr, const struct tonga_power_state *hw_ps)
5335{
5336 uint32_t i;
5337 uint32_t sclk, max_sclk = 0;
5338 struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
5339 struct tonga_dpm_table *pdpm_table = &data->dpm_table;
5340
5341 for (i = 0; i < hw_ps->performance_level_count; i++) {
5342 sclk = hw_ps->performance_levels[i].engine_clock;
5343 if (max_sclk < sclk)
5344 max_sclk = sclk;
5345 }
5346
5347 for (i = 0; i < pdpm_table->sclk_table.count; i++) {
5348 if (pdpm_table->sclk_table.dpm_levels[i].value == max_sclk)
5349 return (uint16_t) ((i >= pdpm_table->pcie_speed_table.count) ?
5350 pdpm_table->pcie_speed_table.dpm_levels[pdpm_table->pcie_speed_table.count-1].value :
5351 pdpm_table->pcie_speed_table.dpm_levels[i].value);
5352 }
5353
5354 return 0;
5355}
5356
5357static int tonga_request_link_speed_change_before_state_change(struct pp_hwmgr *hwmgr, const void *input)
5358{
5359 const struct phm_set_power_state_input *states = (const struct phm_set_power_state_input *)input;
5360 struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
5361 const struct tonga_power_state *tonga_nps = cast_const_phw_tonga_power_state(states->pnew_state);
5362 const struct tonga_power_state *tonga_cps = cast_const_phw_tonga_power_state(states->pcurrent_state);
5363
5364 uint16_t target_link_speed = tonga_get_maximum_link_speed(hwmgr, tonga_nps);
5365 uint16_t current_link_speed;
5366
5367 if (data->force_pcie_gen == PP_PCIEGenInvalid)
5368 current_link_speed = tonga_get_maximum_link_speed(hwmgr, tonga_cps);
5369 else
5370 current_link_speed = data->force_pcie_gen;
5371
5372 data->force_pcie_gen = PP_PCIEGenInvalid;
5373 data->pspp_notify_required = false;
5374 if (target_link_speed > current_link_speed) {
5375 switch(target_link_speed) {
5376 case PP_PCIEGen3:
5377 if (0 == acpi_pcie_perf_request(hwmgr->device, PCIE_PERF_REQ_GEN3, false))
5378 break;
5379 data->force_pcie_gen = PP_PCIEGen2;
5380 if (current_link_speed == PP_PCIEGen2)
5381 break;
5382 case PP_PCIEGen2:
5383 if (0 == acpi_pcie_perf_request(hwmgr->device, PCIE_PERF_REQ_GEN2, false))
5384 break;
5385 default:
5386 data->force_pcie_gen = tonga_get_current_pcie_speed(hwmgr);
5387 break;
5388 }
5389 } else {
5390 if (target_link_speed < current_link_speed)
5391 data->pspp_notify_required = true;
5392 }
5393
5394 return 0;
5395}
5396
5397static int tonga_freeze_sclk_mclk_dpm(struct pp_hwmgr *hwmgr)
5398{
5399 struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
5400
5401 if (0 == data->need_update_smu7_dpm_table)
5402 return 0;
5403
5404 if ((0 == data->sclk_dpm_key_disabled) &&
5405 (data->need_update_smu7_dpm_table &
5406 (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_UPDATE_SCLK))) {
4ba27f9b
EC
5407 PP_ASSERT_WITH_CODE(!tonga_is_dpm_running(hwmgr),
5408 "Trying to freeze SCLK DPM when DPM is disabled",
c82baa28 5409 );
5410 PP_ASSERT_WITH_CODE(
5411 0 == smum_send_msg_to_smc(hwmgr->smumgr,
5412 PPSMC_MSG_SCLKDPM_FreezeLevel),
5413 "Failed to freeze SCLK DPM during FreezeSclkMclkDPM Function!",
5414 return -1);
5415 }
5416
5417 if ((0 == data->mclk_dpm_key_disabled) &&
5418 (data->need_update_smu7_dpm_table &
5419 DPMTABLE_OD_UPDATE_MCLK)) {
4ba27f9b
EC
5420 PP_ASSERT_WITH_CODE(!tonga_is_dpm_running(hwmgr),
5421 "Trying to freeze MCLK DPM when DPM is disabled",
c82baa28 5422 );
5423 PP_ASSERT_WITH_CODE(
5424 0 == smum_send_msg_to_smc(hwmgr->smumgr,
5425 PPSMC_MSG_MCLKDPM_FreezeLevel),
5426 "Failed to freeze MCLK DPM during FreezeSclkMclkDPM Function!",
5427 return -1);
5428 }
5429
5430 return 0;
5431}
5432
5433static int tonga_populate_and_upload_sclk_mclk_dpm_levels(struct pp_hwmgr *hwmgr, const void *input)
5434{
5435 int result = 0;
5436
5437 const struct phm_set_power_state_input *states = (const struct phm_set_power_state_input *)input;
5438 const struct tonga_power_state *tonga_ps = cast_const_phw_tonga_power_state(states->pnew_state);
5439 struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
5440 uint32_t sclk = tonga_ps->performance_levels[tonga_ps->performance_level_count-1].engine_clock;
5441 uint32_t mclk = tonga_ps->performance_levels[tonga_ps->performance_level_count-1].memory_clock;
5442 struct tonga_dpm_table *pdpm_table = &data->dpm_table;
5443
5444 struct tonga_dpm_table *pgolden_dpm_table = &data->golden_dpm_table;
5445 uint32_t dpm_count, clock_percent;
5446 uint32_t i;
5447
5448 if (0 == data->need_update_smu7_dpm_table)
5449 return 0;
5450
5451 if (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_SCLK) {
5452 pdpm_table->sclk_table.dpm_levels[pdpm_table->sclk_table.count-1].value = sclk;
5453
5454 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_OD6PlusinACSupport) ||
5455 phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_OD6PlusinDCSupport)) {
5456 /* Need to do calculation based on the golden DPM table
5457 * as the Heatmap GPU Clock axis is also based on the default values
5458 */
5459 PP_ASSERT_WITH_CODE(
5460 (pgolden_dpm_table->sclk_table.dpm_levels[pgolden_dpm_table->sclk_table.count-1].value != 0),
5461 "Divide by 0!",
5462 return -1);
5463 dpm_count = pdpm_table->sclk_table.count < 2 ? 0 : pdpm_table->sclk_table.count-2;
5464 for (i = dpm_count; i > 1; i--) {
5465 if (sclk > pgolden_dpm_table->sclk_table.dpm_levels[pgolden_dpm_table->sclk_table.count-1].value) {
5466 clock_percent = ((sclk - pgolden_dpm_table->sclk_table.dpm_levels[pgolden_dpm_table->sclk_table.count-1].value)*100) /
5467 pgolden_dpm_table->sclk_table.dpm_levels[pgolden_dpm_table->sclk_table.count-1].value;
5468
5469 pdpm_table->sclk_table.dpm_levels[i].value =
5470 pgolden_dpm_table->sclk_table.dpm_levels[i].value +
5471 (pgolden_dpm_table->sclk_table.dpm_levels[i].value * clock_percent)/100;
5472
5473 } else if (pgolden_dpm_table->sclk_table.dpm_levels[pdpm_table->sclk_table.count-1].value > sclk) {
5474 clock_percent = ((pgolden_dpm_table->sclk_table.dpm_levels[pgolden_dpm_table->sclk_table.count-1].value - sclk)*100) /
5475 pgolden_dpm_table->sclk_table.dpm_levels[pgolden_dpm_table->sclk_table.count-1].value;
5476
5477 pdpm_table->sclk_table.dpm_levels[i].value =
5478 pgolden_dpm_table->sclk_table.dpm_levels[i].value -
5479 (pgolden_dpm_table->sclk_table.dpm_levels[i].value * clock_percent)/100;
5480 } else
5481 pdpm_table->sclk_table.dpm_levels[i].value =
5482 pgolden_dpm_table->sclk_table.dpm_levels[i].value;
5483 }
5484 }
5485 }
5486
5487 if (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK) {
5488 pdpm_table->mclk_table.dpm_levels[pdpm_table->mclk_table.count-1].value = mclk;
5489
5490 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_OD6PlusinACSupport) ||
5491 phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_OD6PlusinDCSupport)) {
5492
5493 PP_ASSERT_WITH_CODE(
5494 (pgolden_dpm_table->mclk_table.dpm_levels[pgolden_dpm_table->mclk_table.count-1].value != 0),
5495 "Divide by 0!",
5496 return -1);
5497 dpm_count = pdpm_table->mclk_table.count < 2? 0 : pdpm_table->mclk_table.count-2;
5498 for (i = dpm_count; i > 1; i--) {
5499 if (mclk > pgolden_dpm_table->mclk_table.dpm_levels[pgolden_dpm_table->mclk_table.count-1].value) {
5500 clock_percent = ((mclk - pgolden_dpm_table->mclk_table.dpm_levels[pgolden_dpm_table->mclk_table.count-1].value)*100) /
5501 pgolden_dpm_table->mclk_table.dpm_levels[pgolden_dpm_table->mclk_table.count-1].value;
5502
5503 pdpm_table->mclk_table.dpm_levels[i].value =
5504 pgolden_dpm_table->mclk_table.dpm_levels[i].value +
5505 (pgolden_dpm_table->mclk_table.dpm_levels[i].value * clock_percent)/100;
5506
5507 } else if (pgolden_dpm_table->mclk_table.dpm_levels[pdpm_table->mclk_table.count-1].value > mclk) {
5508 clock_percent = ((pgolden_dpm_table->mclk_table.dpm_levels[pgolden_dpm_table->mclk_table.count-1].value - mclk)*100) /
5509 pgolden_dpm_table->mclk_table.dpm_levels[pgolden_dpm_table->mclk_table.count-1].value;
5510
5511 pdpm_table->mclk_table.dpm_levels[i].value =
5512 pgolden_dpm_table->mclk_table.dpm_levels[i].value -
5513 (pgolden_dpm_table->mclk_table.dpm_levels[i].value * clock_percent)/100;
5514 } else
5515 pdpm_table->mclk_table.dpm_levels[i].value = pgolden_dpm_table->mclk_table.dpm_levels[i].value;
5516 }
5517 }
5518 }
5519
5520 if (data->need_update_smu7_dpm_table & (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_UPDATE_SCLK)) {
e2ed8a13 5521 result = tonga_populate_all_graphic_levels(hwmgr);
c82baa28 5522 PP_ASSERT_WITH_CODE((0 == result),
5523 "Failed to populate SCLK during PopulateNewDPMClocksStates Function!",
5524 return result);
5525 }
5526
5527 if (data->need_update_smu7_dpm_table & (DPMTABLE_OD_UPDATE_MCLK + DPMTABLE_UPDATE_MCLK)) {
5528 /*populate MCLK dpm table to SMU7 */
5529 result = tonga_populate_all_memory_levels(hwmgr);
5530 PP_ASSERT_WITH_CODE((0 == result),
5531 "Failed to populate MCLK during PopulateNewDPMClocksStates Function!",
5532 return result);
5533 }
5534
5535 return result;
5536}
5537
5538static int tonga_trim_single_dpm_states(struct pp_hwmgr *hwmgr,
5539 struct tonga_single_dpm_table * pdpm_table,
5540 uint32_t low_limit, uint32_t high_limit)
5541{
5542 uint32_t i;
5543
5544 for (i = 0; i < pdpm_table->count; i++) {
5545 if ((pdpm_table->dpm_levels[i].value < low_limit) ||
5546 (pdpm_table->dpm_levels[i].value > high_limit))
5547 pdpm_table->dpm_levels[i].enabled = false;
5548 else
5549 pdpm_table->dpm_levels[i].enabled = true;
5550 }
5551 return 0;
5552}
5553
5554static int tonga_trim_dpm_states(struct pp_hwmgr *hwmgr, const struct tonga_power_state *hw_state)
5555{
c82baa28 5556 struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
5557 uint32_t high_limit_count;
5558
5559 PP_ASSERT_WITH_CODE((hw_state->performance_level_count >= 1),
5560 "power state did not have any performance level",
5561 return -1);
5562
5563 high_limit_count = (1 == hw_state->performance_level_count) ? 0: 1;
5564
5565 tonga_trim_single_dpm_states(hwmgr,
5566 &(data->dpm_table.sclk_table),
5567 hw_state->performance_levels[0].engine_clock,
5568 hw_state->performance_levels[high_limit_count].engine_clock);
5569
5570 tonga_trim_single_dpm_states(hwmgr,
5571 &(data->dpm_table.mclk_table),
5572 hw_state->performance_levels[0].memory_clock,
5573 hw_state->performance_levels[high_limit_count].memory_clock);
5574
538f1ef3 5575 return 0;
c82baa28 5576}
5577
5578static int tonga_generate_dpm_level_enable_mask(struct pp_hwmgr *hwmgr, const void *input)
5579{
5580 int result;
5581 const struct phm_set_power_state_input *states = (const struct phm_set_power_state_input *)input;
5582 struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
5583 const struct tonga_power_state *tonga_ps = cast_const_phw_tonga_power_state(states->pnew_state);
5584
c82baa28 5585 result = tonga_trim_dpm_states(hwmgr, tonga_ps);
5586 if (0 != result)
5587 return result;
5588
5589 data->dpm_level_enable_mask.sclk_dpm_enable_mask = tonga_get_dpm_level_enable_mask_value(&data->dpm_table.sclk_table);
5590 data->dpm_level_enable_mask.mclk_dpm_enable_mask = tonga_get_dpm_level_enable_mask_value(&data->dpm_table.mclk_table);
5591 data->last_mclk_dpm_enable_mask = data->dpm_level_enable_mask.mclk_dpm_enable_mask;
5592 if (data->uvd_enabled)
5593 data->dpm_level_enable_mask.mclk_dpm_enable_mask &= 0xFFFFFFFE;
5594
5595 data->dpm_level_enable_mask.pcie_dpm_enable_mask = tonga_get_dpm_level_enable_mask_value(&data->dpm_table.pcie_speed_table);
5596
5597 return 0;
5598}
5599
0859ed3d 5600int tonga_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable)
c82baa28 5601{
0859ed3d 5602 return smum_send_msg_to_smc(hwmgr->smumgr, enable ?
c82baa28 5603 (PPSMC_Msg)PPSMC_MSG_VCEDPM_Enable :
5604 (PPSMC_Msg)PPSMC_MSG_VCEDPM_Disable);
5605}
5606
0859ed3d
RZ
5607int tonga_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable)
5608{
5609 return smum_send_msg_to_smc(hwmgr->smumgr, enable ?
5610 (PPSMC_Msg)PPSMC_MSG_UVDDPM_Enable :
5611 (PPSMC_Msg)PPSMC_MSG_UVDDPM_Disable);
5612}
5613
5614int tonga_update_uvd_dpm(struct pp_hwmgr *hwmgr, bool bgate)
5615{
5616 struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
5617 uint32_t mm_boot_level_offset, mm_boot_level_value;
5618 struct phm_ppt_v1_information *ptable_information = (struct phm_ppt_v1_information *)(hwmgr->pptable);
5619
5620 if (!bgate) {
5621 data->smc_state_table.UvdBootLevel = (uint8_t) (ptable_information->mm_dep_table->count - 1);
5622 mm_boot_level_offset = data->dpm_table_start + offsetof(SMU72_Discrete_DpmTable, UvdBootLevel);
5623 mm_boot_level_offset /= 4;
5624 mm_boot_level_offset *= 4;
5625 mm_boot_level_value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, mm_boot_level_offset);
5626 mm_boot_level_value &= 0x00FFFFFF;
5627 mm_boot_level_value |= data->smc_state_table.UvdBootLevel << 24;
5628 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value);
5629
5630 if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_UVDDPM) ||
5631 phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState))
5632 smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
5633 PPSMC_MSG_UVDDPM_SetEnabledMask,
5634 (uint32_t)(1 << data->smc_state_table.UvdBootLevel));
5635 }
5636
5637 return tonga_enable_disable_uvd_dpm(hwmgr, !bgate);
5638}
5639
5640int tonga_update_vce_dpm(struct pp_hwmgr *hwmgr, const void *input)
c82baa28 5641{
5642 const struct phm_set_power_state_input *states = (const struct phm_set_power_state_input *)input;
5643 struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
5644 const struct tonga_power_state *tonga_nps = cast_const_phw_tonga_power_state(states->pnew_state);
5645 const struct tonga_power_state *tonga_cps = cast_const_phw_tonga_power_state(states->pcurrent_state);
5646
5647 uint32_t mm_boot_level_offset, mm_boot_level_value;
5648 struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
5649
0859ed3d 5650 if (tonga_nps->vce_clocks.EVCLK > 0 && (tonga_cps == NULL || tonga_cps->vce_clocks.EVCLK == 0)) {
c82baa28 5651 data->smc_state_table.VceBootLevel = (uint8_t) (pptable_info->mm_dep_table->count - 1);
5652
5653 mm_boot_level_offset = data->dpm_table_start + offsetof(SMU72_Discrete_DpmTable, VceBootLevel);
5654 mm_boot_level_offset /= 4;
5655 mm_boot_level_offset *= 4;
5656 mm_boot_level_value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, mm_boot_level_offset);
5657 mm_boot_level_value &= 0xFF00FFFF;
5658 mm_boot_level_value |= data->smc_state_table.VceBootLevel << 16;
5659 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value);
5660
0859ed3d
RZ
5661 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState))
5662 smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
5663 PPSMC_MSG_VCEDPM_SetEnabledMask,
5664 (uint32_t)(1 << data->smc_state_table.VceBootLevel));
c82baa28 5665
0859ed3d
RZ
5666 tonga_enable_disable_vce_dpm(hwmgr, true);
5667 } else if (tonga_nps->vce_clocks.EVCLK == 0 && tonga_cps != NULL && tonga_cps->vce_clocks.EVCLK > 0)
5668 tonga_enable_disable_vce_dpm(hwmgr, false);
c82baa28 5669
5670 return 0;
5671}
5672
5673static int tonga_update_and_upload_mc_reg_table(struct pp_hwmgr *hwmgr)
5674{
5675 struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
5676
5677 uint32_t address;
5678 int32_t result;
5679
5680 if (0 == (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK))
5681 return 0;
5682
5683
5684 memset(&data->mc_reg_table, 0, sizeof(SMU72_Discrete_MCRegisters));
5685
5686 result = tonga_convert_mc_reg_table_to_smc(hwmgr, &(data->mc_reg_table));
5687
5688 if(result != 0)
5689 return result;
5690
5691
5692 address = data->mc_reg_table_start + (uint32_t)offsetof(SMU72_Discrete_MCRegisters, data[0]);
5693
5694 return tonga_copy_bytes_to_smc(hwmgr->smumgr, address,
5695 (uint8_t *)&data->mc_reg_table.data[0],
5696 sizeof(SMU72_Discrete_MCRegisterSet) * data->dpm_table.mclk_table.count,
5697 data->sram_end);
5698}
5699
5700static int tonga_program_memory_timing_parameters_conditionally(struct pp_hwmgr *hwmgr)
5701{
5702 struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
5703
5704 if (data->need_update_smu7_dpm_table &
5705 (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_OD_UPDATE_MCLK))
5706 return tonga_program_memory_timing_parameters(hwmgr);
5707
5708 return 0;
5709}
5710
5711static int tonga_unfreeze_sclk_mclk_dpm(struct pp_hwmgr *hwmgr)
5712{
5713 struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
5714
5715 if (0 == data->need_update_smu7_dpm_table)
5716 return 0;
5717
5718 if ((0 == data->sclk_dpm_key_disabled) &&
5719 (data->need_update_smu7_dpm_table &
5720 (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_UPDATE_SCLK))) {
5721
4ba27f9b
EC
5722 PP_ASSERT_WITH_CODE(!tonga_is_dpm_running(hwmgr),
5723 "Trying to Unfreeze SCLK DPM when DPM is disabled",
c82baa28 5724 );
5725 PP_ASSERT_WITH_CODE(
5726 0 == smum_send_msg_to_smc(hwmgr->smumgr,
5727 PPSMC_MSG_SCLKDPM_UnfreezeLevel),
5728 "Failed to unfreeze SCLK DPM during UnFreezeSclkMclkDPM Function!",
5729 return -1);
5730 }
5731
5732 if ((0 == data->mclk_dpm_key_disabled) &&
5733 (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK)) {
5734
4ba27f9b
EC
5735 PP_ASSERT_WITH_CODE(!tonga_is_dpm_running(hwmgr),
5736 "Trying to Unfreeze MCLK DPM when DPM is disabled",
c82baa28 5737 );
5738 PP_ASSERT_WITH_CODE(
5739 0 == smum_send_msg_to_smc(hwmgr->smumgr,
5740 PPSMC_MSG_SCLKDPM_UnfreezeLevel),
5741 "Failed to unfreeze MCLK DPM during UnFreezeSclkMclkDPM Function!",
5742 return -1);
5743 }
5744
5745 data->need_update_smu7_dpm_table = 0;
5746
5747 return 0;
5748}
5749
5750static int tonga_notify_link_speed_change_after_state_change(struct pp_hwmgr *hwmgr, const void *input)
5751{
5752 const struct phm_set_power_state_input *states = (const struct phm_set_power_state_input *)input;
5753 struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
5754 const struct tonga_power_state *tonga_ps = cast_const_phw_tonga_power_state(states->pnew_state);
5755 uint16_t target_link_speed = tonga_get_maximum_link_speed(hwmgr, tonga_ps);
5756 uint8_t request;
5757
5758 if (data->pspp_notify_required ||
5759 data->pcie_performance_request) {
5760 if (target_link_speed == PP_PCIEGen3)
5761 request = PCIE_PERF_REQ_GEN3;
5762 else if (target_link_speed == PP_PCIEGen2)
5763 request = PCIE_PERF_REQ_GEN2;
5764 else
5765 request = PCIE_PERF_REQ_GEN1;
5766
5767 if(request == PCIE_PERF_REQ_GEN1 && tonga_get_current_pcie_speed(hwmgr) > 0) {
5768 data->pcie_performance_request = false;
5769 return 0;
5770 }
5771
5772 if (0 != acpi_pcie_perf_request(hwmgr->device, request, false)) {
5773 if (PP_PCIEGen2 == target_link_speed)
5774 printk("PSPP request to switch to Gen2 from Gen3 Failed!");
5775 else
5776 printk("PSPP request to switch to Gen1 from Gen2 Failed!");
5777 }
5778 }
5779
5780 data->pcie_performance_request = false;
5781 return 0;
5782}
5783
5784static int tonga_set_power_state_tasks(struct pp_hwmgr *hwmgr, const void *input)
5785{
5786 int tmp_result, result = 0;
5787
5788 tmp_result = tonga_find_dpm_states_clocks_in_dpm_table(hwmgr, input);
5789 PP_ASSERT_WITH_CODE((0 == tmp_result), "Failed to find DPM states clocks in DPM table!", result = tmp_result);
5790
5791 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PCIEPerformanceRequest)) {
5792 tmp_result = tonga_request_link_speed_change_before_state_change(hwmgr, input);
5793 PP_ASSERT_WITH_CODE((0 == tmp_result), "Failed to request link speed change before state change!", result = tmp_result);
5794 }
5795
5796 tmp_result = tonga_freeze_sclk_mclk_dpm(hwmgr);
5797 PP_ASSERT_WITH_CODE((0 == tmp_result), "Failed to freeze SCLK MCLK DPM!", result = tmp_result);
5798
5799 tmp_result = tonga_populate_and_upload_sclk_mclk_dpm_levels(hwmgr, input);
5800 PP_ASSERT_WITH_CODE((0 == tmp_result), "Failed to populate and upload SCLK MCLK DPM levels!", result = tmp_result);
5801
5802 tmp_result = tonga_generate_dpm_level_enable_mask(hwmgr, input);
5803 PP_ASSERT_WITH_CODE((0 == tmp_result), "Failed to generate DPM level enabled mask!", result = tmp_result);
5804
5805 tmp_result = tonga_update_vce_dpm(hwmgr, input);
5806 PP_ASSERT_WITH_CODE((0 == tmp_result), "Failed to update VCE DPM!", result = tmp_result);
5807
5808 tmp_result = tonga_update_sclk_threshold(hwmgr);
5809 PP_ASSERT_WITH_CODE((0 == tmp_result), "Failed to update SCLK threshold!", result = tmp_result);
5810
5811 tmp_result = tonga_update_and_upload_mc_reg_table(hwmgr);
5812 PP_ASSERT_WITH_CODE((0 == tmp_result), "Failed to upload MC reg table!", result = tmp_result);
5813
5814 tmp_result = tonga_program_memory_timing_parameters_conditionally(hwmgr);
5815 PP_ASSERT_WITH_CODE((0 == tmp_result), "Failed to program memory timing parameters!", result = tmp_result);
5816
5817 tmp_result = tonga_unfreeze_sclk_mclk_dpm(hwmgr);
5818 PP_ASSERT_WITH_CODE((0 == tmp_result), "Failed to unfreeze SCLK MCLK DPM!", result = tmp_result);
5819
5820 tmp_result = tonga_upload_dpm_level_enable_mask(hwmgr);
5821 PP_ASSERT_WITH_CODE((0 == tmp_result), "Failed to upload DPM level enabled mask!", result = tmp_result);
5822
5823 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PCIEPerformanceRequest)) {
5824 tmp_result = tonga_notify_link_speed_change_after_state_change(hwmgr, input);
5825 PP_ASSERT_WITH_CODE((0 == tmp_result), "Failed to notify link speed change after state change!", result = tmp_result);
5826 }
5827
5828 return result;
5829}
5830
1e4854e9
RZ
5831/**
5832* Set maximum target operating fan output PWM
5833*
5834* @param pHwMgr: the address of the powerplay hardware manager.
5835* @param usMaxFanPwm: max operating fan PWM in percents
5836* @return The response that came from the SMC.
5837*/
5838static int tonga_set_max_fan_pwm_output(struct pp_hwmgr *hwmgr, uint16_t us_max_fan_pwm)
5839{
5840 hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanPWM = us_max_fan_pwm;
5841
5842 if (phm_is_hw_access_blocked(hwmgr))
5843 return 0;
5844
c15c8d70 5845 return (0 == smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, PPSMC_MSG_SetFanPwmMax, us_max_fan_pwm) ? 0 : -1);
1e4854e9 5846}
bbb207f3
RZ
5847
5848int tonga_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr)
5849{
5850 uint32_t num_active_displays = 0;
5851 struct cgs_display_info info = {0};
5852 info.mode_info = NULL;
5853
5854 cgs_get_active_displays_info(hwmgr->device, &info);
5855
5856 num_active_displays = info.display_count;
5857
5858 if (num_active_displays > 1) /* to do && (pHwMgr->pPECI->displayConfiguration.bMultiMonitorInSync != TRUE)) */
5859 tonga_notify_smc_display_change(hwmgr, false);
5860 else
5861 tonga_notify_smc_display_change(hwmgr, true);
5862
5863 return 0;
5864}
5865
5866/**
5867* Programs the display gap
5868*
5869* @param hwmgr the address of the powerplay hardware manager.
5870* @return always OK
5871*/
5872int tonga_program_display_gap(struct pp_hwmgr *hwmgr)
5873{
5874 struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
5875 uint32_t num_active_displays = 0;
5876 uint32_t display_gap = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_DISPLAY_GAP_CNTL);
5877 uint32_t display_gap2;
5878 uint32_t pre_vbi_time_in_us;
5879 uint32_t frame_time_in_us;
5880 uint32_t ref_clock;
5881 uint32_t refresh_rate = 0;
5882 struct cgs_display_info info = {0};
5883 struct cgs_mode_info mode_info;
5884
5885 info.mode_info = &mode_info;
5886
5887 cgs_get_active_displays_info(hwmgr->device, &info);
5888 num_active_displays = info.display_count;
5889
5890 display_gap = PHM_SET_FIELD(display_gap, CG_DISPLAY_GAP_CNTL, DISP_GAP, (num_active_displays > 0)? DISPLAY_GAP_VBLANK_OR_WM : DISPLAY_GAP_IGNORE);
5891 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_DISPLAY_GAP_CNTL, display_gap);
5892
5893 ref_clock = mode_info.ref_clock;
5894 refresh_rate = mode_info.refresh_rate;
5895
5896 if(0 == refresh_rate)
5897 refresh_rate = 60;
5898
5899 frame_time_in_us = 1000000 / refresh_rate;
5900
5901 pre_vbi_time_in_us = frame_time_in_us - 200 - mode_info.vblank_time_us;
5902 display_gap2 = pre_vbi_time_in_us * (ref_clock / 100);
5903
5904 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_DISPLAY_GAP_CNTL2, display_gap2);
5905
5906 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, data->soft_regs_start + offsetof(SMU72_SoftRegisters, PreVBlankGap), 0x64);
5907
5908 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, data->soft_regs_start + offsetof(SMU72_SoftRegisters, VBlankTimeout), (frame_time_in_us - pre_vbi_time_in_us));
5909
5910 if (num_active_displays == 1)
5911 tonga_notify_smc_display_change(hwmgr, true);
5912
5913 return 0;
5914}
5915
5916int tonga_display_configuration_changed_task(struct pp_hwmgr *hwmgr)
5917{
5918
5919 tonga_program_display_gap(hwmgr);
5920
5921 /* to do PhwTonga_CacUpdateDisplayConfiguration(pHwMgr); */
5922 return 0;
5923}
5924
1e4854e9
RZ
5925/**
5926* Set maximum target operating fan output RPM
5927*
5928* @param pHwMgr: the address of the powerplay hardware manager.
5929* @param usMaxFanRpm: max operating fan RPM value.
5930* @return The response that came from the SMC.
5931*/
5932static int tonga_set_max_fan_rpm_output(struct pp_hwmgr *hwmgr, uint16_t us_max_fan_pwm)
5933{
5934 hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanRPM = us_max_fan_pwm;
5935
5936 if (phm_is_hw_access_blocked(hwmgr))
5937 return 0;
5938
c15c8d70 5939 return (0 == smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, PPSMC_MSG_SetFanRpmMax, us_max_fan_pwm) ? 0 : -1);
1e4854e9
RZ
5940}
5941
5942uint32_t tonga_get_xclk(struct pp_hwmgr *hwmgr)
5943{
5944 uint32_t reference_clock;
5945 uint32_t tc;
5946 uint32_t divide;
5947
5948 ATOM_FIRMWARE_INFO *fw_info;
5949 uint16_t size;
5950 uint8_t frev, crev;
5951 int index = GetIndexIntoMasterTable(DATA, FirmwareInfo);
5952
5953 tc = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_CLKPIN_CNTL_2, MUX_TCLK_TO_XCLK);
5954
5955 if (tc)
5956 return TCLK;
5957
5958 fw_info = (ATOM_FIRMWARE_INFO *)cgs_atom_get_data_table(hwmgr->device, index,
5959 &size, &frev, &crev);
5960
5961 if (!fw_info)
5962 return 0;
5963
dcf799e5 5964 reference_clock = le16_to_cpu(fw_info->usReferenceClock);
1e4854e9
RZ
5965
5966 divide = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_CLKPIN_CNTL, XTALIN_DIVIDE);
5967
5968 if (0 != divide)
5969 return reference_clock / 4;
5970
5971 return reference_clock;
5972}
5973
5974int tonga_dpm_set_interrupt_state(void *private_data,
5975 unsigned src_id, unsigned type,
5976 int enabled)
5977{
5978 uint32_t cg_thermal_int;
5979 struct pp_hwmgr *hwmgr = ((struct pp_eventmgr *)private_data)->hwmgr;
5980
5981 if (hwmgr == NULL)
5982 return -EINVAL;
5983
5984 switch (type) {
5985 case AMD_THERMAL_IRQ_LOW_TO_HIGH:
5986 if (enabled) {
5987 cg_thermal_int = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_THERMAL_INT);
5988 cg_thermal_int |= CG_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK;
5989 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_THERMAL_INT, cg_thermal_int);
5990 } else {
5991 cg_thermal_int = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_THERMAL_INT);
5992 cg_thermal_int &= ~CG_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK;
5993 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_THERMAL_INT, cg_thermal_int);
5994 }
5995 break;
5996
5997 case AMD_THERMAL_IRQ_HIGH_TO_LOW:
5998 if (enabled) {
5999 cg_thermal_int = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_THERMAL_INT);
6000 cg_thermal_int |= CG_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK;
6001 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_THERMAL_INT, cg_thermal_int);
6002 } else {
6003 cg_thermal_int = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_THERMAL_INT);
6004 cg_thermal_int &= ~CG_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK;
6005 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_THERMAL_INT, cg_thermal_int);
6006 }
6007 break;
6008 default:
6009 break;
6010 }
6011 return 0;
6012}
6013
6014int tonga_register_internal_thermal_interrupt(struct pp_hwmgr *hwmgr,
6015 const void *thermal_interrupt_info)
6016{
6017 int result;
6018 const struct pp_interrupt_registration_info *info =
6019 (const struct pp_interrupt_registration_info *)thermal_interrupt_info;
6020
6021 if (info == NULL)
6022 return -EINVAL;
6023
6024 result = cgs_add_irq_source(hwmgr->device, 230, AMD_THERMAL_IRQ_LAST,
6025 tonga_dpm_set_interrupt_state,
6026 info->call_back, info->context);
6027
6028 if (result)
6029 return -EINVAL;
6030
6031 result = cgs_add_irq_source(hwmgr->device, 231, AMD_THERMAL_IRQ_LAST,
6032 tonga_dpm_set_interrupt_state,
6033 info->call_back, info->context);
6034
6035 if (result)
6036 return -EINVAL;
6037
6038 return 0;
6039}
6040
e829ecdb
RZ
6041bool tonga_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr)
6042{
6043 struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
6044 bool is_update_required = false;
6045 struct cgs_display_info info = {0,0,NULL};
6046
6047 cgs_get_active_displays_info(hwmgr->device, &info);
6048
6049 if (data->display_timing.num_existing_displays != info.display_count)
6050 is_update_required = true;
6051/* TO DO NEED TO GET DEEP SLEEP CLOCK FROM DAL
6052 if (phm_cap_enabled(hwmgr->hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) {
6053 cgs_get_min_clock_settings(hwmgr->device, &min_clocks);
6054 if(min_clocks.engineClockInSR != data->display_timing.minClockInSR)
6055 is_update_required = true;
6056*/
6057 return is_update_required;
6058}
6059
6060static inline bool tonga_are_power_levels_equal(const struct tonga_performance_level *pl1,
6061 const struct tonga_performance_level *pl2)
6062{
6063 return ((pl1->memory_clock == pl2->memory_clock) &&
6064 (pl1->engine_clock == pl2->engine_clock) &&
6065 (pl1->pcie_gen == pl2->pcie_gen) &&
6066 (pl1->pcie_lane == pl2->pcie_lane));
6067}
6068
6069int tonga_check_states_equal(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *pstate1, const struct pp_hw_power_state *pstate2, bool *equal)
6070{
6071 const struct tonga_power_state *psa = cast_const_phw_tonga_power_state(pstate1);
6072 const struct tonga_power_state *psb = cast_const_phw_tonga_power_state(pstate2);
6073 int i;
6074
c15c8d70 6075 if (equal == NULL || psa == NULL || psb == NULL)
e829ecdb
RZ
6076 return -EINVAL;
6077
6078 /* If the two states don't even have the same number of performance levels they cannot be the same state. */
6079 if (psa->performance_level_count != psb->performance_level_count) {
6080 *equal = false;
6081 return 0;
6082 }
6083
6084 for (i = 0; i < psa->performance_level_count; i++) {
6085 if (!tonga_are_power_levels_equal(&(psa->performance_levels[i]), &(psb->performance_levels[i]))) {
6086 /* If we have found even one performance level pair that is different the states are different. */
6087 *equal = false;
6088 return 0;
6089 }
6090 }
6091
6092 /* If all performance levels are the same try to use the UVD clocks to break the tie.*/
6093 *equal = ((psa->uvd_clocks.VCLK == psb->uvd_clocks.VCLK) && (psa->uvd_clocks.DCLK == psb->uvd_clocks.DCLK));
6094 *equal &= ((psa->vce_clocks.EVCLK == psb->vce_clocks.EVCLK) && (psa->vce_clocks.ECCLK == psb->vce_clocks.ECCLK));
6095 *equal &= (psa->sclk_threshold == psb->sclk_threshold);
6096 *equal &= (psa->acp_clk == psb->acp_clk);
6097
6098 return 0;
6099}
6100
9dcfc193
EH
6101static int tonga_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode)
6102{
6103 if (mode) {
6104 /* stop auto-manage */
6105 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
6106 PHM_PlatformCaps_MicrocodeFanControl))
6107 tonga_fan_ctrl_stop_smc_fan_control(hwmgr);
6108 tonga_fan_ctrl_set_static_mode(hwmgr, mode);
6109 } else
6110 /* restart auto-manage */
6111 tonga_fan_ctrl_reset_fan_speed_to_default(hwmgr);
6112
6113 return 0;
6114}
6115
6116static int tonga_get_fan_control_mode(struct pp_hwmgr *hwmgr)
6117{
6118 if (hwmgr->fan_ctrl_is_in_default_mode)
6119 return hwmgr->fan_ctrl_default_mode;
6120 else
6121 return PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
6122 CG_FDO_CTRL2, FDO_PWM_MODE);
6123}
6124
5d37a63d 6125static int tonga_force_clock_level(struct pp_hwmgr *hwmgr,
5632708f 6126 enum pp_clock_type type, uint32_t mask)
5d37a63d
EH
6127{
6128 struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
6129
6130 if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL)
6131 return -EINVAL;
6132
6133 switch (type) {
6134 case PP_SCLK:
6135 if (!data->sclk_dpm_key_disabled)
6136 smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
6137 PPSMC_MSG_SCLKDPM_SetEnabledMask,
5632708f 6138 data->dpm_level_enable_mask.sclk_dpm_enable_mask & mask);
5d37a63d
EH
6139 break;
6140 case PP_MCLK:
6141 if (!data->mclk_dpm_key_disabled)
6142 smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
6143 PPSMC_MSG_MCLKDPM_SetEnabledMask,
5632708f 6144 data->dpm_level_enable_mask.mclk_dpm_enable_mask & mask);
5d37a63d
EH
6145 break;
6146 case PP_PCIE:
5632708f
EH
6147 {
6148 uint32_t tmp = mask & data->dpm_level_enable_mask.pcie_dpm_enable_mask;
6149 uint32_t level = 0;
6150
6151 while (tmp >>= 1)
6152 level++;
6153
5d37a63d
EH
6154 if (!data->pcie_dpm_key_disabled)
6155 smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
6156 PPSMC_MSG_PCIeDPM_ForceLevel,
5632708f 6157 level);
5d37a63d 6158 break;
5632708f 6159 }
5d37a63d
EH
6160 default:
6161 break;
6162 }
6163
6164 return 0;
6165}
6166
6167static int tonga_print_clock_levels(struct pp_hwmgr *hwmgr,
6168 enum pp_clock_type type, char *buf)
6169{
6170 struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
6171 struct tonga_single_dpm_table *sclk_table = &(data->dpm_table.sclk_table);
6172 struct tonga_single_dpm_table *mclk_table = &(data->dpm_table.mclk_table);
6173 struct tonga_single_dpm_table *pcie_table = &(data->dpm_table.pcie_speed_table);
6174 int i, now, size = 0;
6175 uint32_t clock, pcie_speed;
6176
6177 switch (type) {
6178 case PP_SCLK:
6179 smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_API_GetSclkFrequency);
6180 clock = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0);
6181
6182 for (i = 0; i < sclk_table->count; i++) {
6183 if (clock > sclk_table->dpm_levels[i].value)
6184 continue;
6185 break;
6186 }
6187 now = i;
6188
6189 for (i = 0; i < sclk_table->count; i++)
6190 size += sprintf(buf + size, "%d: %uMhz %s\n",
6191 i, sclk_table->dpm_levels[i].value / 100,
6192 (i == now) ? "*" : "");
6193 break;
6194 case PP_MCLK:
6195 smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_API_GetMclkFrequency);
6196 clock = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0);
6197
6198 for (i = 0; i < mclk_table->count; i++) {
6199 if (clock > mclk_table->dpm_levels[i].value)
6200 continue;
6201 break;
6202 }
6203 now = i;
6204
6205 for (i = 0; i < mclk_table->count; i++)
6206 size += sprintf(buf + size, "%d: %uMhz %s\n",
6207 i, mclk_table->dpm_levels[i].value / 100,
6208 (i == now) ? "*" : "");
6209 break;
6210 case PP_PCIE:
6211 pcie_speed = tonga_get_current_pcie_speed(hwmgr);
6212 for (i = 0; i < pcie_table->count; i++) {
6213 if (pcie_speed != pcie_table->dpm_levels[i].value)
6214 continue;
6215 break;
6216 }
6217 now = i;
6218
6219 for (i = 0; i < pcie_table->count; i++)
6220 size += sprintf(buf + size, "%d: %s %s\n", i,
6221 (pcie_table->dpm_levels[i].value == 0) ? "2.5GB, x8" :
6222 (pcie_table->dpm_levels[i].value == 1) ? "5.0GB, x16" :
6223 (pcie_table->dpm_levels[i].value == 2) ? "8.0GB, x16" : "",
6224 (i == now) ? "*" : "");
6225 break;
6226 default:
6227 break;
6228 }
6229 return size;
6230}
6231
9ccd4e13
EH
6232static int tonga_get_sclk_od(struct pp_hwmgr *hwmgr)
6233{
6234 struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
6235 struct tonga_single_dpm_table *sclk_table = &(data->dpm_table.sclk_table);
6236 struct tonga_single_dpm_table *golden_sclk_table =
6237 &(data->golden_dpm_table.sclk_table);
6238 int value;
6239
6240 value = (sclk_table->dpm_levels[sclk_table->count - 1].value -
6241 golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value) *
6242 100 /
6243 golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value;
6244
6245 return value;
6246}
6247
6248static int tonga_set_sclk_od(struct pp_hwmgr *hwmgr, uint32_t value)
6249{
6250 struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
6251 struct tonga_single_dpm_table *golden_sclk_table =
6252 &(data->golden_dpm_table.sclk_table);
6253 struct pp_power_state *ps;
6254 struct tonga_power_state *tonga_ps;
6255
6256 if (value > 20)
6257 value = 20;
6258
6259 ps = hwmgr->request_ps;
6260
6261 if (ps == NULL)
6262 return -EINVAL;
6263
6264 tonga_ps = cast_phw_tonga_power_state(&ps->hardware);
6265
6266 tonga_ps->performance_levels[tonga_ps->performance_level_count - 1].engine_clock =
6267 golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value *
6268 value / 100 +
6269 golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value;
6270
6271 return 0;
6272}
6273
f715d5b3
EH
6274static int tonga_get_mclk_od(struct pp_hwmgr *hwmgr)
6275{
6276 struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
6277 struct tonga_single_dpm_table *mclk_table = &(data->dpm_table.mclk_table);
6278 struct tonga_single_dpm_table *golden_mclk_table =
6279 &(data->golden_dpm_table.mclk_table);
6280 int value;
6281
6282 value = (mclk_table->dpm_levels[mclk_table->count - 1].value -
6283 golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value) *
6284 100 /
6285 golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value;
6286
6287 return value;
6288}
6289
6290static int tonga_set_mclk_od(struct pp_hwmgr *hwmgr, uint32_t value)
6291{
6292 struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
6293 struct tonga_single_dpm_table *golden_mclk_table =
6294 &(data->golden_dpm_table.mclk_table);
6295 struct pp_power_state *ps;
6296 struct tonga_power_state *tonga_ps;
6297
6298 if (value > 20)
6299 value = 20;
6300
6301 ps = hwmgr->request_ps;
6302
6303 if (ps == NULL)
6304 return -EINVAL;
6305
6306 tonga_ps = cast_phw_tonga_power_state(&ps->hardware);
6307
6308 tonga_ps->performance_levels[tonga_ps->performance_level_count - 1].memory_clock =
6309 golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value *
6310 value / 100 +
6311 golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value;
6312
6313 return 0;
6314}
6315
c82baa28 6316static const struct pp_hwmgr_func tonga_hwmgr_funcs = {
6317 .backend_init = &tonga_hwmgr_backend_init,
6318 .backend_fini = &tonga_hwmgr_backend_fini,
6319 .asic_setup = &tonga_setup_asic_task,
6320 .dynamic_state_management_enable = &tonga_enable_dpm_tasks,
57461af7 6321 .dynamic_state_management_disable = &tonga_disable_dpm_tasks,
c82baa28 6322 .apply_state_adjust_rules = tonga_apply_state_adjust_rules,
6323 .force_dpm_level = &tonga_force_dpm_level,
6324 .power_state_set = tonga_set_power_state_tasks,
6325 .get_power_state_size = tonga_get_power_state_size,
6326 .get_mclk = tonga_dpm_get_mclk,
6327 .get_sclk = tonga_dpm_get_sclk,
6328 .patch_boot_state = tonga_dpm_patch_boot_state,
6329 .get_pp_table_entry = tonga_get_pp_table_entry,
e1aa5715 6330 .get_num_of_pp_table_entries = get_number_of_powerplay_table_entries_v1_0,
c82baa28 6331 .print_current_perforce_level = tonga_print_current_perforce_level,
0859ed3d
RZ
6332 .powerdown_uvd = tonga_phm_powerdown_uvd,
6333 .powergate_uvd = tonga_phm_powergate_uvd,
6334 .powergate_vce = tonga_phm_powergate_vce,
6335 .disable_clock_power_gating = tonga_phm_disable_clock_power_gating,
ce90dbd9 6336 .update_clock_gatings = tonga_phm_update_clock_gatings,
bbb207f3
RZ
6337 .notify_smc_display_config_after_ps_adjustment = tonga_notify_smc_display_config_after_ps_adjustment,
6338 .display_config_changed = tonga_display_configuration_changed_task,
1e4854e9
RZ
6339 .set_max_fan_pwm_output = tonga_set_max_fan_pwm_output,
6340 .set_max_fan_rpm_output = tonga_set_max_fan_rpm_output,
6341 .get_temperature = tonga_thermal_get_temperature,
6342 .stop_thermal_controller = tonga_thermal_stop_thermal_controller,
6343 .get_fan_speed_info = tonga_fan_ctrl_get_fan_speed_info,
6344 .get_fan_speed_percent = tonga_fan_ctrl_get_fan_speed_percent,
6345 .set_fan_speed_percent = tonga_fan_ctrl_set_fan_speed_percent,
6346 .reset_fan_speed_to_default = tonga_fan_ctrl_reset_fan_speed_to_default,
6347 .get_fan_speed_rpm = tonga_fan_ctrl_get_fan_speed_rpm,
6348 .set_fan_speed_rpm = tonga_fan_ctrl_set_fan_speed_rpm,
6349 .uninitialize_thermal_controller = tonga_thermal_ctrl_uninitialize_thermal_controller,
6350 .register_internal_thermal_interrupt = tonga_register_internal_thermal_interrupt,
e829ecdb
RZ
6351 .check_smc_update_required_for_display_configuration = tonga_check_smc_update_required_for_display_configuration,
6352 .check_states_equal = tonga_check_states_equal,
9dcfc193
EH
6353 .set_fan_control_mode = tonga_set_fan_control_mode,
6354 .get_fan_control_mode = tonga_get_fan_control_mode,
5d37a63d
EH
6355 .force_clock_level = tonga_force_clock_level,
6356 .print_clock_levels = tonga_print_clock_levels,
9ccd4e13
EH
6357 .get_sclk_od = tonga_get_sclk_od,
6358 .set_sclk_od = tonga_set_sclk_od,
f715d5b3
EH
6359 .get_mclk_od = tonga_get_mclk_od,
6360 .set_mclk_od = tonga_set_mclk_od,
c82baa28 6361};
6362
6363int tonga_hwmgr_init(struct pp_hwmgr *hwmgr)
6364{
c82baa28 6365 hwmgr->hwmgr_func = &tonga_hwmgr_funcs;
e1aa5715 6366 hwmgr->pptable_func = &pptable_v1_0_funcs;
1e4854e9 6367 pp_tonga_thermal_initialize(hwmgr);
c82baa28 6368 return 0;
6369}
6370