Linux-libre 4.11.5-gnu
[librecmc/linux-libre.git] / drivers / gpu / drm / amd / powerplay / smumgr / polaris10_smc.c
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
24 #include "pp_debug.h"
25 #include "polaris10_smc.h"
26 #include "smu7_dyn_defaults.h"
27
28 #include "smu7_hwmgr.h"
29 #include "hardwaremanager.h"
30 #include "ppatomctrl.h"
31 #include "cgs_common.h"
32 #include "atombios.h"
33 #include "polaris10_smumgr.h"
34 #include "pppcielanes.h"
35
36 #include "smu_ucode_xfer_vi.h"
37 #include "smu74_discrete.h"
38 #include "smu/smu_7_1_3_d.h"
39 #include "smu/smu_7_1_3_sh_mask.h"
40 #include "gmc/gmc_8_1_d.h"
41 #include "gmc/gmc_8_1_sh_mask.h"
42 #include "oss/oss_3_0_d.h"
43 #include "gca/gfx_8_0_d.h"
44 #include "bif/bif_5_0_d.h"
45 #include "bif/bif_5_0_sh_mask.h"
46 #include "dce/dce_10_0_d.h"
47 #include "dce/dce_10_0_sh_mask.h"
48 #include "polaris10_pwrvirus.h"
49 #include "smu7_ppsmc.h"
50 #include "smu7_smumgr.h"
51
52 #define POLARIS10_SMC_SIZE 0x20000
53 #define VOLTAGE_VID_OFFSET_SCALE1   625
54 #define VOLTAGE_VID_OFFSET_SCALE2   100
55 #define POWERTUNE_DEFAULT_SET_MAX    1
56 #define VDDC_VDDCI_DELTA            200
57 #define MC_CG_ARB_FREQ_F1           0x0b
58
59 static const struct polaris10_pt_defaults polaris10_power_tune_data_set_array[POWERTUNE_DEFAULT_SET_MAX] = {
60         /* sviLoadLIneEn, SviLoadLineVddC, TDC_VDDC_ThrottleReleaseLimitPerc, TDC_MAWt,
61          * TdcWaterfallCtl, DTEAmbientTempBase, DisplayCac, BAPM_TEMP_GRADIENT */
62         { 1, 0xF, 0xFD, 0x19, 5, 45, 0, 0xB0000,
63         { 0x79, 0x253, 0x25D, 0xAE, 0x72, 0x80, 0x83, 0x86, 0x6F, 0xC8, 0xC9, 0xC9, 0x2F, 0x4D, 0x61},
64         { 0x17C, 0x172, 0x180, 0x1BC, 0x1B3, 0x1BD, 0x206, 0x200, 0x203, 0x25D, 0x25A, 0x255, 0x2C3, 0x2C5, 0x2B4 } },
65 };
66
67 static const sclkFcwRange_t Range_Table[NUM_SCLK_RANGE] = {
68                         {VCO_2_4, POSTDIV_DIV_BY_16,  75, 160, 112},
69                         {VCO_3_6, POSTDIV_DIV_BY_16, 112, 224, 160},
70                         {VCO_2_4, POSTDIV_DIV_BY_8,   75, 160, 112},
71                         {VCO_3_6, POSTDIV_DIV_BY_8,  112, 224, 160},
72                         {VCO_2_4, POSTDIV_DIV_BY_4,   75, 160, 112},
73                         {VCO_3_6, POSTDIV_DIV_BY_4,  112, 216, 160},
74                         {VCO_2_4, POSTDIV_DIV_BY_2,   75, 160, 108},
75                         {VCO_3_6, POSTDIV_DIV_BY_2,  112, 216, 160} };
76
77 static int polaris10_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr,
78                 struct phm_ppt_v1_clock_voltage_dependency_table *dep_table,
79                 uint32_t clock, SMU_VoltageLevel *voltage, uint32_t *mvdd)
80 {
81         uint32_t i;
82         uint16_t vddci;
83         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
84
85         *voltage = *mvdd = 0;
86
87         /* clock - voltage dependency table is empty table */
88         if (dep_table->count == 0)
89                 return -EINVAL;
90
91         for (i = 0; i < dep_table->count; i++) {
92                 /* find first sclk bigger than request */
93                 if (dep_table->entries[i].clk >= clock) {
94                         *voltage |= (dep_table->entries[i].vddc *
95                                         VOLTAGE_SCALE) << VDDC_SHIFT;
96                         if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control)
97                                 *voltage |= (data->vbios_boot_state.vddci_bootup_value *
98                                                 VOLTAGE_SCALE) << VDDCI_SHIFT;
99                         else if (dep_table->entries[i].vddci)
100                                 *voltage |= (dep_table->entries[i].vddci *
101                                                 VOLTAGE_SCALE) << VDDCI_SHIFT;
102                         else {
103                                 vddci = phm_find_closest_vddci(&(data->vddci_voltage_table),
104                                                 (dep_table->entries[i].vddc -
105                                                                 (uint16_t)VDDC_VDDCI_DELTA));
106                                 *voltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT;
107                         }
108
109                         if (SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control)
110                                 *mvdd = data->vbios_boot_state.mvdd_bootup_value *
111                                         VOLTAGE_SCALE;
112                         else if (dep_table->entries[i].mvdd)
113                                 *mvdd = (uint32_t) dep_table->entries[i].mvdd *
114                                         VOLTAGE_SCALE;
115
116                         *voltage |= 1 << PHASES_SHIFT;
117                         return 0;
118                 }
119         }
120
121         /* sclk is bigger than max sclk in the dependence table */
122         *voltage |= (dep_table->entries[i - 1].vddc * VOLTAGE_SCALE) << VDDC_SHIFT;
123
124         if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control)
125                 *voltage |= (data->vbios_boot_state.vddci_bootup_value *
126                                 VOLTAGE_SCALE) << VDDCI_SHIFT;
127         else if (dep_table->entries[i-1].vddci) {
128                 vddci = phm_find_closest_vddci(&(data->vddci_voltage_table),
129                                 (dep_table->entries[i].vddc -
130                                                 (uint16_t)VDDC_VDDCI_DELTA));
131                 *voltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT;
132         }
133
134         if (SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control)
135                 *mvdd = data->vbios_boot_state.mvdd_bootup_value * VOLTAGE_SCALE;
136         else if (dep_table->entries[i].mvdd)
137                 *mvdd = (uint32_t) dep_table->entries[i - 1].mvdd * VOLTAGE_SCALE;
138
139         return 0;
140 }
141
142 static uint16_t scale_fan_gain_settings(uint16_t raw_setting)
143 {
144         uint32_t tmp;
145         tmp = raw_setting * 4096 / 100;
146         return (uint16_t)tmp;
147 }
148
149 static int polaris10_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr)
150 {
151         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend);
152
153         const struct polaris10_pt_defaults *defaults = smu_data->power_tune_defaults;
154         SMU74_Discrete_DpmTable  *table = &(smu_data->smc_state_table);
155         struct phm_ppt_v1_information *table_info =
156                         (struct phm_ppt_v1_information *)(hwmgr->pptable);
157         struct phm_cac_tdp_table *cac_dtp_table = table_info->cac_dtp_table;
158         struct pp_advance_fan_control_parameters *fan_table =
159                         &hwmgr->thermal_controller.advanceFanControlParameters;
160         int i, j, k;
161         const uint16_t *pdef1;
162         const uint16_t *pdef2;
163
164         table->DefaultTdp = PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table->usTDP * 128));
165         table->TargetTdp  = PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table->usTDP * 128));
166
167         PP_ASSERT_WITH_CODE(cac_dtp_table->usTargetOperatingTemp <= 255,
168                                 "Target Operating Temp is out of Range!",
169                                 );
170
171         table->TemperatureLimitEdge = PP_HOST_TO_SMC_US(
172                         cac_dtp_table->usTargetOperatingTemp * 256);
173         table->TemperatureLimitHotspot = PP_HOST_TO_SMC_US(
174                         cac_dtp_table->usTemperatureLimitHotspot * 256);
175         table->FanGainEdge = PP_HOST_TO_SMC_US(
176                         scale_fan_gain_settings(fan_table->usFanGainEdge));
177         table->FanGainHotspot = PP_HOST_TO_SMC_US(
178                         scale_fan_gain_settings(fan_table->usFanGainHotspot));
179
180         pdef1 = defaults->BAPMTI_R;
181         pdef2 = defaults->BAPMTI_RC;
182
183         for (i = 0; i < SMU74_DTE_ITERATIONS; i++) {
184                 for (j = 0; j < SMU74_DTE_SOURCES; j++) {
185                         for (k = 0; k < SMU74_DTE_SINKS; k++) {
186                                 table->BAPMTI_R[i][j][k] = PP_HOST_TO_SMC_US(*pdef1);
187                                 table->BAPMTI_RC[i][j][k] = PP_HOST_TO_SMC_US(*pdef2);
188                                 pdef1++;
189                                 pdef2++;
190                         }
191                 }
192         }
193
194         return 0;
195 }
196
197 static int polaris10_populate_svi_load_line(struct pp_hwmgr *hwmgr)
198 {
199         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend);
200         const struct polaris10_pt_defaults *defaults = smu_data->power_tune_defaults;
201
202         smu_data->power_tune_table.SviLoadLineEn = defaults->SviLoadLineEn;
203         smu_data->power_tune_table.SviLoadLineVddC = defaults->SviLoadLineVddC;
204         smu_data->power_tune_table.SviLoadLineTrimVddC = 3;
205         smu_data->power_tune_table.SviLoadLineOffsetVddC = 0;
206
207         return 0;
208 }
209
210 static int polaris10_populate_tdc_limit(struct pp_hwmgr *hwmgr)
211 {
212         uint16_t tdc_limit;
213         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend);
214         struct phm_ppt_v1_information *table_info =
215                         (struct phm_ppt_v1_information *)(hwmgr->pptable);
216         const struct polaris10_pt_defaults *defaults = smu_data->power_tune_defaults;
217
218         tdc_limit = (uint16_t)(table_info->cac_dtp_table->usTDC * 128);
219         smu_data->power_tune_table.TDC_VDDC_PkgLimit =
220                         CONVERT_FROM_HOST_TO_SMC_US(tdc_limit);
221         smu_data->power_tune_table.TDC_VDDC_ThrottleReleaseLimitPerc =
222                         defaults->TDC_VDDC_ThrottleReleaseLimitPerc;
223         smu_data->power_tune_table.TDC_MAWt = defaults->TDC_MAWt;
224
225         return 0;
226 }
227
228 static int polaris10_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset)
229 {
230         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend);
231         const struct polaris10_pt_defaults *defaults = smu_data->power_tune_defaults;
232         uint32_t temp;
233
234         if (smu7_read_smc_sram_dword(hwmgr->smumgr,
235                         fuse_table_offset +
236                         offsetof(SMU74_Discrete_PmFuses, TdcWaterfallCtl),
237                         (uint32_t *)&temp, SMC_RAM_END))
238                 PP_ASSERT_WITH_CODE(false,
239                                 "Attempt to read PmFuses.DW6 (SviLoadLineEn) from SMC Failed!",
240                                 return -EINVAL);
241         else {
242                 smu_data->power_tune_table.TdcWaterfallCtl = defaults->TdcWaterfallCtl;
243                 smu_data->power_tune_table.LPMLTemperatureMin =
244                                 (uint8_t)((temp >> 16) & 0xff);
245                 smu_data->power_tune_table.LPMLTemperatureMax =
246                                 (uint8_t)((temp >> 8) & 0xff);
247                 smu_data->power_tune_table.Reserved = (uint8_t)(temp & 0xff);
248         }
249         return 0;
250 }
251
252 static int polaris10_populate_temperature_scaler(struct pp_hwmgr *hwmgr)
253 {
254         int i;
255         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend);
256
257         /* Currently not used. Set all to zero. */
258         for (i = 0; i < 16; i++)
259                 smu_data->power_tune_table.LPMLTemperatureScaler[i] = 0;
260
261         return 0;
262 }
263
264 static int polaris10_populate_fuzzy_fan(struct pp_hwmgr *hwmgr)
265 {
266         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend);
267
268 /* TO DO move to hwmgr */
269         if ((hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity & (1 << 15))
270                 || 0 == hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity)
271                 hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity =
272                         hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity;
273
274         smu_data->power_tune_table.FuzzyFan_PwmSetDelta = PP_HOST_TO_SMC_US(
275                                 hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity);
276         return 0;
277 }
278
279 static int polaris10_populate_gnb_lpml(struct pp_hwmgr *hwmgr)
280 {
281         int i;
282         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend);
283
284         /* Currently not used. Set all to zero. */
285         for (i = 0; i < 16; i++)
286                 smu_data->power_tune_table.GnbLPML[i] = 0;
287
288         return 0;
289 }
290
291 static int polaris10_min_max_vgnb_lpml_id_from_bapm_vddc(struct pp_hwmgr *hwmgr)
292 {
293         return 0;
294 }
295
296 static int polaris10_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr)
297 {
298         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend);
299         struct phm_ppt_v1_information *table_info =
300                         (struct phm_ppt_v1_information *)(hwmgr->pptable);
301         uint16_t hi_sidd = smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd;
302         uint16_t lo_sidd = smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd;
303         struct phm_cac_tdp_table *cac_table = table_info->cac_dtp_table;
304
305         hi_sidd = (uint16_t)(cac_table->usHighCACLeakage / 100 * 256);
306         lo_sidd = (uint16_t)(cac_table->usLowCACLeakage / 100 * 256);
307
308         smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd =
309                         CONVERT_FROM_HOST_TO_SMC_US(hi_sidd);
310         smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd =
311                         CONVERT_FROM_HOST_TO_SMC_US(lo_sidd);
312
313         return 0;
314 }
315
316 static int polaris10_populate_pm_fuses(struct pp_hwmgr *hwmgr)
317 {
318         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend);
319         uint32_t pm_fuse_table_offset;
320
321         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
322                         PHM_PlatformCaps_PowerContainment)) {
323                 if (smu7_read_smc_sram_dword(hwmgr->smumgr,
324                                 SMU7_FIRMWARE_HEADER_LOCATION +
325                                 offsetof(SMU74_Firmware_Header, PmFuseTable),
326                                 &pm_fuse_table_offset, SMC_RAM_END))
327                         PP_ASSERT_WITH_CODE(false,
328                                         "Attempt to get pm_fuse_table_offset Failed!",
329                                         return -EINVAL);
330
331                 if (polaris10_populate_svi_load_line(hwmgr))
332                         PP_ASSERT_WITH_CODE(false,
333                                         "Attempt to populate SviLoadLine Failed!",
334                                         return -EINVAL);
335
336                 if (polaris10_populate_tdc_limit(hwmgr))
337                         PP_ASSERT_WITH_CODE(false,
338                                         "Attempt to populate TDCLimit Failed!", return -EINVAL);
339
340                 if (polaris10_populate_dw8(hwmgr, pm_fuse_table_offset))
341                         PP_ASSERT_WITH_CODE(false,
342                                         "Attempt to populate TdcWaterfallCtl, "
343                                         "LPMLTemperature Min and Max Failed!",
344                                         return -EINVAL);
345
346                 if (0 != polaris10_populate_temperature_scaler(hwmgr))
347                         PP_ASSERT_WITH_CODE(false,
348                                         "Attempt to populate LPMLTemperatureScaler Failed!",
349                                         return -EINVAL);
350
351                 if (polaris10_populate_fuzzy_fan(hwmgr))
352                         PP_ASSERT_WITH_CODE(false,
353                                         "Attempt to populate Fuzzy Fan Control parameters Failed!",
354                                         return -EINVAL);
355
356                 if (polaris10_populate_gnb_lpml(hwmgr))
357                         PP_ASSERT_WITH_CODE(false,
358                                         "Attempt to populate GnbLPML Failed!",
359                                         return -EINVAL);
360
361                 if (polaris10_min_max_vgnb_lpml_id_from_bapm_vddc(hwmgr))
362                         PP_ASSERT_WITH_CODE(false,
363                                         "Attempt to populate GnbLPML Min and Max Vid Failed!",
364                                         return -EINVAL);
365
366                 if (polaris10_populate_bapm_vddc_base_leakage_sidd(hwmgr))
367                         PP_ASSERT_WITH_CODE(false,
368                                         "Attempt to populate BapmVddCBaseLeakage Hi and Lo "
369                                         "Sidd Failed!", return -EINVAL);
370
371                 if (smu7_copy_bytes_to_smc(hwmgr->smumgr, pm_fuse_table_offset,
372                                 (uint8_t *)&smu_data->power_tune_table,
373                                 (sizeof(struct SMU74_Discrete_PmFuses) - 92), SMC_RAM_END))
374                         PP_ASSERT_WITH_CODE(false,
375                                         "Attempt to download PmFuseTable Failed!",
376                                         return -EINVAL);
377         }
378         return 0;
379 }
380
381 /**
382  * Mvdd table preparation for SMC.
383  *
384  * @param    *hwmgr The address of the hardware manager.
385  * @param    *table The SMC DPM table structure to be populated.
386  * @return   0
387  */
388 static int polaris10_populate_smc_mvdd_table(struct pp_hwmgr *hwmgr,
389                         SMU74_Discrete_DpmTable *table)
390 {
391         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
392         uint32_t count, level;
393
394         if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) {
395                 count = data->mvdd_voltage_table.count;
396                 if (count > SMU_MAX_SMIO_LEVELS)
397                         count = SMU_MAX_SMIO_LEVELS;
398                 for (level = 0; level < count; level++) {
399                         table->SmioTable2.Pattern[level].Voltage =
400                                 PP_HOST_TO_SMC_US(data->mvdd_voltage_table.entries[count].value * VOLTAGE_SCALE);
401                         /* Index into DpmTable.Smio. Drive bits from Smio entry to get this voltage level.*/
402                         table->SmioTable2.Pattern[level].Smio =
403                                 (uint8_t) level;
404                         table->Smio[level] |=
405                                 data->mvdd_voltage_table.entries[level].smio_low;
406                 }
407                 table->SmioMask2 = data->mvdd_voltage_table.mask_low;
408
409                 table->MvddLevelCount = (uint32_t) PP_HOST_TO_SMC_UL(count);
410         }
411
412         return 0;
413 }
414
415 static int polaris10_populate_smc_vddci_table(struct pp_hwmgr *hwmgr,
416                                         struct SMU74_Discrete_DpmTable *table)
417 {
418         uint32_t count, level;
419         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
420
421         count = data->vddci_voltage_table.count;
422
423         if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) {
424                 if (count > SMU_MAX_SMIO_LEVELS)
425                         count = SMU_MAX_SMIO_LEVELS;
426                 for (level = 0; level < count; ++level) {
427                         table->SmioTable1.Pattern[level].Voltage =
428                                 PP_HOST_TO_SMC_US(data->vddci_voltage_table.entries[level].value * VOLTAGE_SCALE);
429                         table->SmioTable1.Pattern[level].Smio = (uint8_t) level;
430
431                         table->Smio[level] |= data->vddci_voltage_table.entries[level].smio_low;
432                 }
433         }
434
435         table->SmioMask1 = data->vddci_voltage_table.mask_low;
436
437         return 0;
438 }
439
440 /**
441 * Preparation of vddc and vddgfx CAC tables for SMC.
442 *
443 * @param    hwmgr  the address of the hardware manager
444 * @param    table  the SMC DPM table structure to be populated
445 * @return   always 0
446 */
447 static int polaris10_populate_cac_table(struct pp_hwmgr *hwmgr,
448                 struct SMU74_Discrete_DpmTable *table)
449 {
450         uint32_t count;
451         uint8_t index;
452         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
453         struct phm_ppt_v1_information *table_info =
454                         (struct phm_ppt_v1_information *)(hwmgr->pptable);
455         struct phm_ppt_v1_voltage_lookup_table *lookup_table =
456                         table_info->vddc_lookup_table;
457         /* tables is already swapped, so in order to use the value from it,
458          * we need to swap it back.
459          * We are populating vddc CAC data to BapmVddc table
460          * in split and merged mode
461          */
462         for (count = 0; count < lookup_table->count; count++) {
463                 index = phm_get_voltage_index(lookup_table,
464                                 data->vddc_voltage_table.entries[count].value);
465                 table->BapmVddcVidLoSidd[count] = convert_to_vid(lookup_table->entries[index].us_cac_low);
466                 table->BapmVddcVidHiSidd[count] = convert_to_vid(lookup_table->entries[index].us_cac_mid);
467                 table->BapmVddcVidHiSidd2[count] = convert_to_vid(lookup_table->entries[index].us_cac_high);
468         }
469
470         return 0;
471 }
472
473 /**
474 * Preparation of voltage tables for SMC.
475 *
476 * @param    hwmgr   the address of the hardware manager
477 * @param    table   the SMC DPM table structure to be populated
478 * @return   always  0
479 */
480
481 static int polaris10_populate_smc_voltage_tables(struct pp_hwmgr *hwmgr,
482                 struct SMU74_Discrete_DpmTable *table)
483 {
484         polaris10_populate_smc_vddci_table(hwmgr, table);
485         polaris10_populate_smc_mvdd_table(hwmgr, table);
486         polaris10_populate_cac_table(hwmgr, table);
487
488         return 0;
489 }
490
491 static int polaris10_populate_ulv_level(struct pp_hwmgr *hwmgr,
492                 struct SMU74_Discrete_Ulv *state)
493 {
494         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
495         struct phm_ppt_v1_information *table_info =
496                         (struct phm_ppt_v1_information *)(hwmgr->pptable);
497         struct pp_smumgr *smumgr = hwmgr->smumgr;
498
499         state->CcPwrDynRm = 0;
500         state->CcPwrDynRm1 = 0;
501
502         state->VddcOffset = (uint16_t) table_info->us_ulv_voltage_offset;
503         state->VddcOffsetVid = (uint8_t)(table_info->us_ulv_voltage_offset *
504                         VOLTAGE_VID_OFFSET_SCALE2 / VOLTAGE_VID_OFFSET_SCALE1);
505
506         if (smumgr->chip_id == CHIP_POLARIS12 || smumgr->is_kicker)
507                 state->VddcPhase = data->vddc_phase_shed_control ^ 0x3;
508         else
509                 state->VddcPhase = (data->vddc_phase_shed_control) ? 0 : 1;
510
511         CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm);
512         CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm1);
513         CONVERT_FROM_HOST_TO_SMC_US(state->VddcOffset);
514
515         return 0;
516 }
517
518 static int polaris10_populate_ulv_state(struct pp_hwmgr *hwmgr,
519                 struct SMU74_Discrete_DpmTable *table)
520 {
521         return polaris10_populate_ulv_level(hwmgr, &table->Ulv);
522 }
523
524 static int polaris10_populate_smc_link_level(struct pp_hwmgr *hwmgr,
525                 struct SMU74_Discrete_DpmTable *table)
526 {
527         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
528         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend);
529         struct smu7_dpm_table *dpm_table = &data->dpm_table;
530         int i;
531
532         /* Index (dpm_table->pcie_speed_table.count)
533          * is reserved for PCIE boot level. */
534         for (i = 0; i <= dpm_table->pcie_speed_table.count; i++) {
535                 table->LinkLevel[i].PcieGenSpeed  =
536                                 (uint8_t)dpm_table->pcie_speed_table.dpm_levels[i].value;
537                 table->LinkLevel[i].PcieLaneCount = (uint8_t)encode_pcie_lane_width(
538                                 dpm_table->pcie_speed_table.dpm_levels[i].param1);
539                 table->LinkLevel[i].EnabledForActivity = 1;
540                 table->LinkLevel[i].SPC = (uint8_t)(data->pcie_spc_cap & 0xff);
541                 table->LinkLevel[i].DownThreshold = PP_HOST_TO_SMC_UL(5);
542                 table->LinkLevel[i].UpThreshold = PP_HOST_TO_SMC_UL(30);
543         }
544
545         smu_data->smc_state_table.LinkLevelCount =
546                         (uint8_t)dpm_table->pcie_speed_table.count;
547
548 /* To Do move to hwmgr */
549         data->dpm_level_enable_mask.pcie_dpm_enable_mask =
550                         phm_get_dpm_level_enable_mask_value(&dpm_table->pcie_speed_table);
551
552         return 0;
553 }
554
555
556 static void polaris10_get_sclk_range_table(struct pp_hwmgr *hwmgr,
557                                    SMU74_Discrete_DpmTable  *table)
558 {
559         struct pp_smumgr *smumgr = hwmgr->smumgr;
560         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend);
561         uint32_t i, ref_clk;
562
563         struct pp_atom_ctrl_sclk_range_table range_table_from_vbios = { { {0} } };
564
565         ref_clk = smu7_get_xclk(hwmgr);
566
567         if (0 == atomctrl_get_smc_sclk_range_table(hwmgr, &range_table_from_vbios)) {
568                 for (i = 0; i < NUM_SCLK_RANGE; i++) {
569                         table->SclkFcwRangeTable[i].vco_setting = range_table_from_vbios.entry[i].ucVco_setting;
570                         table->SclkFcwRangeTable[i].postdiv = range_table_from_vbios.entry[i].ucPostdiv;
571                         table->SclkFcwRangeTable[i].fcw_pcc = range_table_from_vbios.entry[i].usFcw_pcc;
572
573                         table->SclkFcwRangeTable[i].fcw_trans_upper = range_table_from_vbios.entry[i].usFcw_trans_upper;
574                         table->SclkFcwRangeTable[i].fcw_trans_lower = range_table_from_vbios.entry[i].usRcw_trans_lower;
575
576                         CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_pcc);
577                         CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_trans_upper);
578                         CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_trans_lower);
579                 }
580                 return;
581         }
582
583         for (i = 0; i < NUM_SCLK_RANGE; i++) {
584                 smu_data->range_table[i].trans_lower_frequency = (ref_clk * Range_Table[i].fcw_trans_lower) >> Range_Table[i].postdiv;
585                 smu_data->range_table[i].trans_upper_frequency = (ref_clk * Range_Table[i].fcw_trans_upper) >> Range_Table[i].postdiv;
586
587                 table->SclkFcwRangeTable[i].vco_setting = Range_Table[i].vco_setting;
588                 table->SclkFcwRangeTable[i].postdiv = Range_Table[i].postdiv;
589                 table->SclkFcwRangeTable[i].fcw_pcc = Range_Table[i].fcw_pcc;
590
591                 table->SclkFcwRangeTable[i].fcw_trans_upper = Range_Table[i].fcw_trans_upper;
592                 table->SclkFcwRangeTable[i].fcw_trans_lower = Range_Table[i].fcw_trans_lower;
593
594                 CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_pcc);
595                 CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_trans_upper);
596                 CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_trans_lower);
597         }
598 }
599
600 /**
601 * Calculates the SCLK dividers using the provided engine clock
602 *
603 * @param    hwmgr  the address of the hardware manager
604 * @param    clock  the engine clock to use to populate the structure
605 * @param    sclk   the SMC SCLK structure to be populated
606 */
607 static int polaris10_calculate_sclk_params(struct pp_hwmgr *hwmgr,
608                 uint32_t clock, SMU_SclkSetting *sclk_setting)
609 {
610         struct pp_smumgr *smumgr = hwmgr->smumgr;
611         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend);
612         const SMU74_Discrete_DpmTable *table = &(smu_data->smc_state_table);
613         struct pp_atomctrl_clock_dividers_ai dividers;
614         uint32_t ref_clock;
615         uint32_t pcc_target_percent, pcc_target_freq, ss_target_percent, ss_target_freq;
616         uint8_t i;
617         int result;
618         uint64_t temp;
619
620         sclk_setting->SclkFrequency = clock;
621         /* get the engine clock dividers for this clock value */
622         result = atomctrl_get_engine_pll_dividers_ai(hwmgr, clock,  &dividers);
623         if (result == 0) {
624                 sclk_setting->Fcw_int = dividers.usSclk_fcw_int;
625                 sclk_setting->Fcw_frac = dividers.usSclk_fcw_frac;
626                 sclk_setting->Pcc_fcw_int = dividers.usPcc_fcw_int;
627                 sclk_setting->PllRange = dividers.ucSclkPllRange;
628                 sclk_setting->Sclk_slew_rate = 0x400;
629                 sclk_setting->Pcc_up_slew_rate = dividers.usPcc_fcw_slew_frac;
630                 sclk_setting->Pcc_down_slew_rate = 0xffff;
631                 sclk_setting->SSc_En = dividers.ucSscEnable;
632                 sclk_setting->Fcw1_int = dividers.usSsc_fcw1_int;
633                 sclk_setting->Fcw1_frac = dividers.usSsc_fcw1_frac;
634                 sclk_setting->Sclk_ss_slew_rate = dividers.usSsc_fcw_slew_frac;
635                 return result;
636         }
637
638         ref_clock = smu7_get_xclk(hwmgr);
639
640         for (i = 0; i < NUM_SCLK_RANGE; i++) {
641                 if (clock > smu_data->range_table[i].trans_lower_frequency
642                 && clock <= smu_data->range_table[i].trans_upper_frequency) {
643                         sclk_setting->PllRange = i;
644                         break;
645                 }
646         }
647
648         sclk_setting->Fcw_int = (uint16_t)((clock << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv) / ref_clock);
649         temp = clock << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv;
650         temp <<= 0x10;
651         do_div(temp, ref_clock);
652         sclk_setting->Fcw_frac = temp & 0xffff;
653
654         pcc_target_percent = 10; /*  Hardcode 10% for now. */
655         pcc_target_freq = clock - (clock * pcc_target_percent / 100);
656         sclk_setting->Pcc_fcw_int = (uint16_t)((pcc_target_freq << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv) / ref_clock);
657
658         ss_target_percent = 2; /*  Hardcode 2% for now. */
659         sclk_setting->SSc_En = 0;
660         if (ss_target_percent) {
661                 sclk_setting->SSc_En = 1;
662                 ss_target_freq = clock - (clock * ss_target_percent / 100);
663                 sclk_setting->Fcw1_int = (uint16_t)((ss_target_freq << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv) / ref_clock);
664                 temp = ss_target_freq << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv;
665                 temp <<= 0x10;
666                 do_div(temp, ref_clock);
667                 sclk_setting->Fcw1_frac = temp & 0xffff;
668         }
669
670         return 0;
671 }
672
673 /**
674 * Populates single SMC SCLK structure using the provided engine clock
675 *
676 * @param    hwmgr      the address of the hardware manager
677 * @param    clock the engine clock to use to populate the structure
678 * @param    sclk        the SMC SCLK structure to be populated
679 */
680
681 static int polaris10_populate_single_graphic_level(struct pp_hwmgr *hwmgr,
682                 uint32_t clock, uint16_t sclk_al_threshold,
683                 struct SMU74_Discrete_GraphicsLevel *level)
684 {
685         int result;
686         /* PP_Clocks minClocks; */
687         uint32_t mvdd;
688         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
689         struct phm_ppt_v1_information *table_info =
690                         (struct phm_ppt_v1_information *)(hwmgr->pptable);
691         SMU_SclkSetting curr_sclk_setting = { 0 };
692
693         result = polaris10_calculate_sclk_params(hwmgr, clock, &curr_sclk_setting);
694
695         /* populate graphics levels */
696         result = polaris10_get_dependency_volt_by_clk(hwmgr,
697                         table_info->vdd_dep_on_sclk, clock,
698                         &level->MinVoltage, &mvdd);
699
700         PP_ASSERT_WITH_CODE((0 == result),
701                         "can not find VDDC voltage value for "
702                         "VDDC engine clock dependency table",
703                         return result);
704         level->ActivityLevel = sclk_al_threshold;
705
706         level->CcPwrDynRm = 0;
707         level->CcPwrDynRm1 = 0;
708         level->EnabledForActivity = 0;
709         level->EnabledForThrottle = 1;
710         level->UpHyst = 10;
711         level->DownHyst = 0;
712         level->VoltageDownHyst = 0;
713         level->PowerThrottle = 0;
714         data->display_timing.min_clock_in_sr = hwmgr->display_config.min_core_set_clock_in_sr;
715
716         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep))
717                 level->DeepSleepDivId = smu7_get_sleep_divider_id_from_clock(clock,
718                                                                 hwmgr->display_config.min_core_set_clock_in_sr);
719
720         /* Default to slow, highest DPM level will be
721          * set to PPSMC_DISPLAY_WATERMARK_LOW later.
722          */
723         if (data->update_up_hyst)
724                 level->UpHyst = (uint8_t)data->up_hyst;
725         if (data->update_down_hyst)
726                 level->DownHyst = (uint8_t)data->down_hyst;
727
728         level->SclkSetting = curr_sclk_setting;
729
730         CONVERT_FROM_HOST_TO_SMC_UL(level->MinVoltage);
731         CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm);
732         CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm1);
733         CONVERT_FROM_HOST_TO_SMC_US(level->ActivityLevel);
734         CONVERT_FROM_HOST_TO_SMC_UL(level->SclkSetting.SclkFrequency);
735         CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Fcw_int);
736         CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Fcw_frac);
737         CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Pcc_fcw_int);
738         CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Sclk_slew_rate);
739         CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Pcc_up_slew_rate);
740         CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Pcc_down_slew_rate);
741         CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Fcw1_int);
742         CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Fcw1_frac);
743         CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Sclk_ss_slew_rate);
744         return 0;
745 }
746
747 /**
748 * Populates all SMC SCLK levels' structure based on the trimmed allowed dpm engine clock states
749 *
750 * @param    hwmgr      the address of the hardware manager
751 */
752 int polaris10_populate_all_graphic_levels(struct pp_hwmgr *hwmgr)
753 {
754         struct pp_smumgr *smumgr = hwmgr->smumgr;
755         struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend);
756         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend);
757         struct smu7_dpm_table *dpm_table = &hw_data->dpm_table;
758         struct phm_ppt_v1_information *table_info =
759                         (struct phm_ppt_v1_information *)(hwmgr->pptable);
760         struct phm_ppt_v1_pcie_table *pcie_table = table_info->pcie_table;
761         uint8_t pcie_entry_cnt = (uint8_t) hw_data->dpm_table.pcie_speed_table.count;
762         int result = 0;
763         uint32_t array = smu_data->smu7_data.dpm_table_start +
764                         offsetof(SMU74_Discrete_DpmTable, GraphicsLevel);
765         uint32_t array_size = sizeof(struct SMU74_Discrete_GraphicsLevel) *
766                         SMU74_MAX_LEVELS_GRAPHICS;
767         struct SMU74_Discrete_GraphicsLevel *levels =
768                         smu_data->smc_state_table.GraphicsLevel;
769         uint32_t i, max_entry;
770         uint8_t hightest_pcie_level_enabled = 0,
771                 lowest_pcie_level_enabled = 0,
772                 mid_pcie_level_enabled = 0,
773                 count = 0;
774
775         polaris10_get_sclk_range_table(hwmgr, &(smu_data->smc_state_table));
776
777         for (i = 0; i < dpm_table->sclk_table.count; i++) {
778
779                 result = polaris10_populate_single_graphic_level(hwmgr,
780                                 dpm_table->sclk_table.dpm_levels[i].value,
781                                 (uint16_t)smu_data->activity_target[i],
782                                 &(smu_data->smc_state_table.GraphicsLevel[i]));
783                 if (result)
784                         return result;
785
786                 /* Making sure only DPM level 0-1 have Deep Sleep Div ID populated. */
787                 if (i > 1)
788                         levels[i].DeepSleepDivId = 0;
789         }
790         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
791                                         PHM_PlatformCaps_SPLLShutdownSupport))
792                 smu_data->smc_state_table.GraphicsLevel[0].SclkSetting.SSc_En = 0;
793
794         smu_data->smc_state_table.GraphicsLevel[0].EnabledForActivity = 1;
795         smu_data->smc_state_table.GraphicsDpmLevelCount =
796                         (uint8_t)dpm_table->sclk_table.count;
797         hw_data->dpm_level_enable_mask.sclk_dpm_enable_mask =
798                         phm_get_dpm_level_enable_mask_value(&dpm_table->sclk_table);
799
800
801         if (pcie_table != NULL) {
802                 PP_ASSERT_WITH_CODE((1 <= pcie_entry_cnt),
803                                 "There must be 1 or more PCIE levels defined in PPTable.",
804                                 return -EINVAL);
805                 max_entry = pcie_entry_cnt - 1;
806                 for (i = 0; i < dpm_table->sclk_table.count; i++)
807                         levels[i].pcieDpmLevel =
808                                         (uint8_t) ((i < max_entry) ? i : max_entry);
809         } else {
810                 while (hw_data->dpm_level_enable_mask.pcie_dpm_enable_mask &&
811                                 ((hw_data->dpm_level_enable_mask.pcie_dpm_enable_mask &
812                                                 (1 << (hightest_pcie_level_enabled + 1))) != 0))
813                         hightest_pcie_level_enabled++;
814
815                 while (hw_data->dpm_level_enable_mask.pcie_dpm_enable_mask &&
816                                 ((hw_data->dpm_level_enable_mask.pcie_dpm_enable_mask &
817                                                 (1 << lowest_pcie_level_enabled)) == 0))
818                         lowest_pcie_level_enabled++;
819
820                 while ((count < hightest_pcie_level_enabled) &&
821                                 ((hw_data->dpm_level_enable_mask.pcie_dpm_enable_mask &
822                                                 (1 << (lowest_pcie_level_enabled + 1 + count))) == 0))
823                         count++;
824
825                 mid_pcie_level_enabled = (lowest_pcie_level_enabled + 1 + count) <
826                                 hightest_pcie_level_enabled ?
827                                                 (lowest_pcie_level_enabled + 1 + count) :
828                                                 hightest_pcie_level_enabled;
829
830                 /* set pcieDpmLevel to hightest_pcie_level_enabled */
831                 for (i = 2; i < dpm_table->sclk_table.count; i++)
832                         levels[i].pcieDpmLevel = hightest_pcie_level_enabled;
833
834                 /* set pcieDpmLevel to lowest_pcie_level_enabled */
835                 levels[0].pcieDpmLevel = lowest_pcie_level_enabled;
836
837                 /* set pcieDpmLevel to mid_pcie_level_enabled */
838                 levels[1].pcieDpmLevel = mid_pcie_level_enabled;
839         }
840         /* level count will send to smc once at init smc table and never change */
841         result = smu7_copy_bytes_to_smc(smumgr, array, (uint8_t *)levels,
842                         (uint32_t)array_size, SMC_RAM_END);
843
844         return result;
845 }
846
847
848 static int polaris10_populate_single_memory_level(struct pp_hwmgr *hwmgr,
849                 uint32_t clock, struct SMU74_Discrete_MemoryLevel *mem_level)
850 {
851         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
852         struct phm_ppt_v1_information *table_info =
853                         (struct phm_ppt_v1_information *)(hwmgr->pptable);
854         int result = 0;
855         struct cgs_display_info info = {0, 0, NULL};
856         uint32_t mclk_stutter_mode_threshold = 40000;
857
858         cgs_get_active_displays_info(hwmgr->device, &info);
859
860         if (table_info->vdd_dep_on_mclk) {
861                 result = polaris10_get_dependency_volt_by_clk(hwmgr,
862                                 table_info->vdd_dep_on_mclk, clock,
863                                 &mem_level->MinVoltage, &mem_level->MinMvdd);
864                 PP_ASSERT_WITH_CODE((0 == result),
865                                 "can not find MinVddc voltage value from memory "
866                                 "VDDC voltage dependency table", return result);
867         }
868
869         mem_level->MclkFrequency = clock;
870         mem_level->EnabledForThrottle = 1;
871         mem_level->EnabledForActivity = 0;
872         mem_level->UpHyst = 0;
873         mem_level->DownHyst = 100;
874         mem_level->VoltageDownHyst = 0;
875         mem_level->ActivityLevel = (uint16_t)data->mclk_activity_target;
876         mem_level->StutterEnable = false;
877         mem_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW;
878
879         data->display_timing.num_existing_displays = info.display_count;
880
881         if (mclk_stutter_mode_threshold &&
882                 (clock <= mclk_stutter_mode_threshold) &&
883                 (SMUM_READ_FIELD(hwmgr->device, DPG_PIPE_STUTTER_CONTROL,
884                                 STUTTER_ENABLE) & 0x1))
885                 mem_level->StutterEnable = true;
886
887         if (!result) {
888                 CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MinMvdd);
889                 CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MclkFrequency);
890                 CONVERT_FROM_HOST_TO_SMC_US(mem_level->ActivityLevel);
891                 CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MinVoltage);
892         }
893         return result;
894 }
895
896 /**
897 * Populates all SMC MCLK levels' structure based on the trimmed allowed dpm memory clock states
898 *
899 * @param    hwmgr      the address of the hardware manager
900 */
901 int polaris10_populate_all_memory_levels(struct pp_hwmgr *hwmgr)
902 {
903         struct pp_smumgr *smumgr = hwmgr->smumgr;
904         struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend);
905         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend);
906         struct smu7_dpm_table *dpm_table = &hw_data->dpm_table;
907         int result;
908         /* populate MCLK dpm table to SMU7 */
909         uint32_t array = smu_data->smu7_data.dpm_table_start +
910                         offsetof(SMU74_Discrete_DpmTable, MemoryLevel);
911         uint32_t array_size = sizeof(SMU74_Discrete_MemoryLevel) *
912                         SMU74_MAX_LEVELS_MEMORY;
913         struct SMU74_Discrete_MemoryLevel *levels =
914                         smu_data->smc_state_table.MemoryLevel;
915         uint32_t i;
916
917         for (i = 0; i < dpm_table->mclk_table.count; i++) {
918                 PP_ASSERT_WITH_CODE((0 != dpm_table->mclk_table.dpm_levels[i].value),
919                                 "can not populate memory level as memory clock is zero",
920                                 return -EINVAL);
921                 result = polaris10_populate_single_memory_level(hwmgr,
922                                 dpm_table->mclk_table.dpm_levels[i].value,
923                                 &levels[i]);
924                 if (i == dpm_table->mclk_table.count - 1) {
925                         levels[i].DisplayWatermark = PPSMC_DISPLAY_WATERMARK_HIGH;
926                         levels[i].EnabledForActivity = 1;
927                 }
928                 if (result)
929                         return result;
930         }
931
932         /* In order to prevent MC activity from stutter mode to push DPM up,
933          * the UVD change complements this by putting the MCLK in
934          * a higher state by default such that we are not affected by
935          * up threshold or and MCLK DPM latency.
936          */
937         levels[0].ActivityLevel = 0x1f;
938         CONVERT_FROM_HOST_TO_SMC_US(levels[0].ActivityLevel);
939
940         smu_data->smc_state_table.MemoryDpmLevelCount =
941                         (uint8_t)dpm_table->mclk_table.count;
942         hw_data->dpm_level_enable_mask.mclk_dpm_enable_mask =
943                         phm_get_dpm_level_enable_mask_value(&dpm_table->mclk_table);
944
945         /* level count will send to smc once at init smc table and never change */
946         result = smu7_copy_bytes_to_smc(hwmgr->smumgr, array, (uint8_t *)levels,
947                         (uint32_t)array_size, SMC_RAM_END);
948
949         return result;
950 }
951
952 /**
953 * Populates the SMC MVDD structure using the provided memory clock.
954 *
955 * @param    hwmgr      the address of the hardware manager
956 * @param    mclk        the MCLK value to be used in the decision if MVDD should be high or low.
957 * @param    voltage     the SMC VOLTAGE structure to be populated
958 */
959 static int polaris10_populate_mvdd_value(struct pp_hwmgr *hwmgr,
960                 uint32_t mclk, SMIO_Pattern *smio_pat)
961 {
962         const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
963         struct phm_ppt_v1_information *table_info =
964                         (struct phm_ppt_v1_information *)(hwmgr->pptable);
965         uint32_t i = 0;
966
967         if (SMU7_VOLTAGE_CONTROL_NONE != data->mvdd_control) {
968                 /* find mvdd value which clock is more than request */
969                 for (i = 0; i < table_info->vdd_dep_on_mclk->count; i++) {
970                         if (mclk <= table_info->vdd_dep_on_mclk->entries[i].clk) {
971                                 smio_pat->Voltage = data->mvdd_voltage_table.entries[i].value;
972                                 break;
973                         }
974                 }
975                 PP_ASSERT_WITH_CODE(i < table_info->vdd_dep_on_mclk->count,
976                                 "MVDD Voltage is outside the supported range.",
977                                 return -EINVAL);
978         } else
979                 return -EINVAL;
980
981         return 0;
982 }
983
984 static int polaris10_populate_smc_acpi_level(struct pp_hwmgr *hwmgr,
985                 SMU74_Discrete_DpmTable *table)
986 {
987         int result = 0;
988         uint32_t sclk_frequency;
989         const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
990         struct phm_ppt_v1_information *table_info =
991                         (struct phm_ppt_v1_information *)(hwmgr->pptable);
992         SMIO_Pattern vol_level;
993         uint32_t mvdd;
994         uint16_t us_mvdd;
995
996         table->ACPILevel.Flags &= ~PPSMC_SWSTATE_FLAG_DC;
997
998         /* Get MinVoltage and Frequency from DPM0,
999          * already converted to SMC_UL */
1000         sclk_frequency = data->vbios_boot_state.sclk_bootup_value;
1001         result = polaris10_get_dependency_volt_by_clk(hwmgr,
1002                         table_info->vdd_dep_on_sclk,
1003                         sclk_frequency,
1004                         &table->ACPILevel.MinVoltage, &mvdd);
1005         PP_ASSERT_WITH_CODE((0 == result),
1006                         "Cannot find ACPI VDDC voltage value "
1007                         "in Clock Dependency Table",
1008                         );
1009
1010         result = polaris10_calculate_sclk_params(hwmgr, sclk_frequency,  &(table->ACPILevel.SclkSetting));
1011         PP_ASSERT_WITH_CODE(result == 0, "Error retrieving Engine Clock dividers from VBIOS.", return result);
1012
1013         table->ACPILevel.DeepSleepDivId = 0;
1014         table->ACPILevel.CcPwrDynRm = 0;
1015         table->ACPILevel.CcPwrDynRm1 = 0;
1016
1017         CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.Flags);
1018         CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.MinVoltage);
1019         CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm);
1020         CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm1);
1021
1022         CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SclkSetting.SclkFrequency);
1023         CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Fcw_int);
1024         CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Fcw_frac);
1025         CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Pcc_fcw_int);
1026         CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Sclk_slew_rate);
1027         CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Pcc_up_slew_rate);
1028         CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Pcc_down_slew_rate);
1029         CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Fcw1_int);
1030         CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Fcw1_frac);
1031         CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Sclk_ss_slew_rate);
1032
1033
1034         /* Get MinVoltage and Frequency from DPM0, already converted to SMC_UL */
1035         table->MemoryACPILevel.MclkFrequency = data->vbios_boot_state.mclk_bootup_value;
1036         result = polaris10_get_dependency_volt_by_clk(hwmgr,
1037                         table_info->vdd_dep_on_mclk,
1038                         table->MemoryACPILevel.MclkFrequency,
1039                         &table->MemoryACPILevel.MinVoltage, &mvdd);
1040         PP_ASSERT_WITH_CODE((0 == result),
1041                         "Cannot find ACPI VDDCI voltage value "
1042                         "in Clock Dependency Table",
1043                         );
1044
1045         us_mvdd = 0;
1046         if ((SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control) ||
1047                         (data->mclk_dpm_key_disabled))
1048                 us_mvdd = data->vbios_boot_state.mvdd_bootup_value;
1049         else {
1050                 if (!polaris10_populate_mvdd_value(hwmgr,
1051                                 data->dpm_table.mclk_table.dpm_levels[0].value,
1052                                 &vol_level))
1053                         us_mvdd = vol_level.Voltage;
1054         }
1055
1056         if (0 == polaris10_populate_mvdd_value(hwmgr, 0, &vol_level))
1057                 table->MemoryACPILevel.MinMvdd = PP_HOST_TO_SMC_UL(vol_level.Voltage);
1058         else
1059                 table->MemoryACPILevel.MinMvdd = 0;
1060
1061         table->MemoryACPILevel.StutterEnable = false;
1062
1063         table->MemoryACPILevel.EnabledForThrottle = 0;
1064         table->MemoryACPILevel.EnabledForActivity = 0;
1065         table->MemoryACPILevel.UpHyst = 0;
1066         table->MemoryACPILevel.DownHyst = 100;
1067         table->MemoryACPILevel.VoltageDownHyst = 0;
1068         table->MemoryACPILevel.ActivityLevel =
1069                         PP_HOST_TO_SMC_US((uint16_t)data->mclk_activity_target);
1070
1071         CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MclkFrequency);
1072         CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MinVoltage);
1073
1074         return result;
1075 }
1076
1077 static int polaris10_populate_smc_vce_level(struct pp_hwmgr *hwmgr,
1078                 SMU74_Discrete_DpmTable *table)
1079 {
1080         int result = -EINVAL;
1081         uint8_t count;
1082         struct pp_atomctrl_clock_dividers_vi dividers;
1083         struct phm_ppt_v1_information *table_info =
1084                         (struct phm_ppt_v1_information *)(hwmgr->pptable);
1085         struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table =
1086                         table_info->mm_dep_table;
1087         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1088         uint32_t vddci;
1089
1090         table->VceLevelCount = (uint8_t)(mm_table->count);
1091         table->VceBootLevel = 0;
1092
1093         for (count = 0; count < table->VceLevelCount; count++) {
1094                 table->VceLevel[count].Frequency = mm_table->entries[count].eclk;
1095                 table->VceLevel[count].MinVoltage = 0;
1096                 table->VceLevel[count].MinVoltage |=
1097                                 (mm_table->entries[count].vddc * VOLTAGE_SCALE) << VDDC_SHIFT;
1098
1099                 if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control)
1100                         vddci = (uint32_t)phm_find_closest_vddci(&(data->vddci_voltage_table),
1101                                                 mm_table->entries[count].vddc - VDDC_VDDCI_DELTA);
1102                 else if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control)
1103                         vddci = mm_table->entries[count].vddc - VDDC_VDDCI_DELTA;
1104                 else
1105                         vddci = (data->vbios_boot_state.vddci_bootup_value * VOLTAGE_SCALE) << VDDCI_SHIFT;
1106
1107
1108                 table->VceLevel[count].MinVoltage |=
1109                                 (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT;
1110                 table->VceLevel[count].MinVoltage |= 1 << PHASES_SHIFT;
1111
1112                 /*retrieve divider value for VBIOS */
1113                 result = atomctrl_get_dfs_pll_dividers_vi(hwmgr,
1114                                 table->VceLevel[count].Frequency, &dividers);
1115                 PP_ASSERT_WITH_CODE((0 == result),
1116                                 "can not find divide id for VCE engine clock",
1117                                 return result);
1118
1119                 table->VceLevel[count].Divider = (uint8_t)dividers.pll_post_divider;
1120
1121                 CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].Frequency);
1122                 CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].MinVoltage);
1123         }
1124         return result;
1125 }
1126
1127
1128 static int polaris10_populate_smc_samu_level(struct pp_hwmgr *hwmgr,
1129                 SMU74_Discrete_DpmTable *table)
1130 {
1131         int result = -EINVAL;
1132         uint8_t count;
1133         struct pp_atomctrl_clock_dividers_vi dividers;
1134         struct phm_ppt_v1_information *table_info =
1135                         (struct phm_ppt_v1_information *)(hwmgr->pptable);
1136         struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table =
1137                         table_info->mm_dep_table;
1138         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1139         uint32_t vddci;
1140
1141         table->SamuBootLevel = 0;
1142         table->SamuLevelCount = (uint8_t)(mm_table->count);
1143
1144         for (count = 0; count < table->SamuLevelCount; count++) {
1145                 /* not sure whether we need evclk or not */
1146                 table->SamuLevel[count].MinVoltage = 0;
1147                 table->SamuLevel[count].Frequency = mm_table->entries[count].samclock;
1148                 table->SamuLevel[count].MinVoltage |= (mm_table->entries[count].vddc *
1149                                 VOLTAGE_SCALE) << VDDC_SHIFT;
1150
1151                 if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control)
1152                         vddci = (uint32_t)phm_find_closest_vddci(&(data->vddci_voltage_table),
1153                                                 mm_table->entries[count].vddc - VDDC_VDDCI_DELTA);
1154                 else if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control)
1155                         vddci = mm_table->entries[count].vddc - VDDC_VDDCI_DELTA;
1156                 else
1157                         vddci = (data->vbios_boot_state.vddci_bootup_value * VOLTAGE_SCALE) << VDDCI_SHIFT;
1158
1159                 table->SamuLevel[count].MinVoltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT;
1160                 table->SamuLevel[count].MinVoltage |= 1 << PHASES_SHIFT;
1161
1162                 /* retrieve divider value for VBIOS */
1163                 result = atomctrl_get_dfs_pll_dividers_vi(hwmgr,
1164                                 table->SamuLevel[count].Frequency, &dividers);
1165                 PP_ASSERT_WITH_CODE((0 == result),
1166                                 "can not find divide id for samu clock", return result);
1167
1168                 table->SamuLevel[count].Divider = (uint8_t)dividers.pll_post_divider;
1169
1170                 CONVERT_FROM_HOST_TO_SMC_UL(table->SamuLevel[count].Frequency);
1171                 CONVERT_FROM_HOST_TO_SMC_UL(table->SamuLevel[count].MinVoltage);
1172         }
1173         return result;
1174 }
1175
1176 static int polaris10_populate_memory_timing_parameters(struct pp_hwmgr *hwmgr,
1177                 int32_t eng_clock, int32_t mem_clock,
1178                 SMU74_Discrete_MCArbDramTimingTableEntry *arb_regs)
1179 {
1180         uint32_t dram_timing;
1181         uint32_t dram_timing2;
1182         uint32_t burst_time;
1183         int result;
1184
1185         result = atomctrl_set_engine_dram_timings_rv770(hwmgr,
1186                         eng_clock, mem_clock);
1187         PP_ASSERT_WITH_CODE(result == 0,
1188                         "Error calling VBIOS to set DRAM_TIMING.", return result);
1189
1190         dram_timing = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING);
1191         dram_timing2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2);
1192         burst_time = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0);
1193
1194
1195         arb_regs->McArbDramTiming  = PP_HOST_TO_SMC_UL(dram_timing);
1196         arb_regs->McArbDramTiming2 = PP_HOST_TO_SMC_UL(dram_timing2);
1197         arb_regs->McArbBurstTime   = (uint8_t)burst_time;
1198
1199         return 0;
1200 }
1201
1202 static int polaris10_program_memory_timing_parameters(struct pp_hwmgr *hwmgr)
1203 {
1204         struct pp_smumgr *smumgr = hwmgr->smumgr;
1205         struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend);
1206         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend);
1207         struct SMU74_Discrete_MCArbDramTimingTable arb_regs;
1208         uint32_t i, j;
1209         int result = 0;
1210
1211         for (i = 0; i < hw_data->dpm_table.sclk_table.count; i++) {
1212                 for (j = 0; j < hw_data->dpm_table.mclk_table.count; j++) {
1213                         result = polaris10_populate_memory_timing_parameters(hwmgr,
1214                                         hw_data->dpm_table.sclk_table.dpm_levels[i].value,
1215                                         hw_data->dpm_table.mclk_table.dpm_levels[j].value,
1216                                         &arb_regs.entries[i][j]);
1217                         if (result == 0)
1218                                 result = atomctrl_set_ac_timing_ai(hwmgr, hw_data->dpm_table.mclk_table.dpm_levels[j].value, j);
1219                         if (result != 0)
1220                                 return result;
1221                 }
1222         }
1223
1224         result = smu7_copy_bytes_to_smc(
1225                         hwmgr->smumgr,
1226                         smu_data->smu7_data.arb_table_start,
1227                         (uint8_t *)&arb_regs,
1228                         sizeof(SMU74_Discrete_MCArbDramTimingTable),
1229                         SMC_RAM_END);
1230         return result;
1231 }
1232
1233 static int polaris10_populate_smc_uvd_level(struct pp_hwmgr *hwmgr,
1234                 struct SMU74_Discrete_DpmTable *table)
1235 {
1236         int result = -EINVAL;
1237         uint8_t count;
1238         struct pp_atomctrl_clock_dividers_vi dividers;
1239         struct phm_ppt_v1_information *table_info =
1240                         (struct phm_ppt_v1_information *)(hwmgr->pptable);
1241         struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table =
1242                         table_info->mm_dep_table;
1243         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1244         uint32_t vddci;
1245
1246         table->UvdLevelCount = (uint8_t)(mm_table->count);
1247         table->UvdBootLevel = 0;
1248
1249         for (count = 0; count < table->UvdLevelCount; count++) {
1250                 table->UvdLevel[count].MinVoltage = 0;
1251                 table->UvdLevel[count].VclkFrequency = mm_table->entries[count].vclk;
1252                 table->UvdLevel[count].DclkFrequency = mm_table->entries[count].dclk;
1253                 table->UvdLevel[count].MinVoltage |= (mm_table->entries[count].vddc *
1254                                 VOLTAGE_SCALE) << VDDC_SHIFT;
1255
1256                 if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control)
1257                         vddci = (uint32_t)phm_find_closest_vddci(&(data->vddci_voltage_table),
1258                                                 mm_table->entries[count].vddc - VDDC_VDDCI_DELTA);
1259                 else if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control)
1260                         vddci = mm_table->entries[count].vddc - VDDC_VDDCI_DELTA;
1261                 else
1262                         vddci = (data->vbios_boot_state.vddci_bootup_value * VOLTAGE_SCALE) << VDDCI_SHIFT;
1263
1264                 table->UvdLevel[count].MinVoltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT;
1265                 table->UvdLevel[count].MinVoltage |= 1 << PHASES_SHIFT;
1266
1267                 /* retrieve divider value for VBIOS */
1268                 result = atomctrl_get_dfs_pll_dividers_vi(hwmgr,
1269                                 table->UvdLevel[count].VclkFrequency, &dividers);
1270                 PP_ASSERT_WITH_CODE((0 == result),
1271                                 "can not find divide id for Vclk clock", return result);
1272
1273                 table->UvdLevel[count].VclkDivider = (uint8_t)dividers.pll_post_divider;
1274
1275                 result = atomctrl_get_dfs_pll_dividers_vi(hwmgr,
1276                                 table->UvdLevel[count].DclkFrequency, &dividers);
1277                 PP_ASSERT_WITH_CODE((0 == result),
1278                                 "can not find divide id for Dclk clock", return result);
1279
1280                 table->UvdLevel[count].DclkDivider = (uint8_t)dividers.pll_post_divider;
1281
1282                 CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].VclkFrequency);
1283                 CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].DclkFrequency);
1284                 CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].MinVoltage);
1285         }
1286
1287         return result;
1288 }
1289
1290 static int polaris10_populate_smc_boot_level(struct pp_hwmgr *hwmgr,
1291                 struct SMU74_Discrete_DpmTable *table)
1292 {
1293         int result = 0;
1294         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1295
1296         table->GraphicsBootLevel = 0;
1297         table->MemoryBootLevel = 0;
1298
1299         /* find boot level from dpm table */
1300         result = phm_find_boot_level(&(data->dpm_table.sclk_table),
1301                         data->vbios_boot_state.sclk_bootup_value,
1302                         (uint32_t *)&(table->GraphicsBootLevel));
1303
1304         result = phm_find_boot_level(&(data->dpm_table.mclk_table),
1305                         data->vbios_boot_state.mclk_bootup_value,
1306                         (uint32_t *)&(table->MemoryBootLevel));
1307
1308         table->BootVddc  = data->vbios_boot_state.vddc_bootup_value *
1309                         VOLTAGE_SCALE;
1310         table->BootVddci = data->vbios_boot_state.vddci_bootup_value *
1311                         VOLTAGE_SCALE;
1312         table->BootMVdd  = data->vbios_boot_state.mvdd_bootup_value *
1313                         VOLTAGE_SCALE;
1314
1315         CONVERT_FROM_HOST_TO_SMC_US(table->BootVddc);
1316         CONVERT_FROM_HOST_TO_SMC_US(table->BootVddci);
1317         CONVERT_FROM_HOST_TO_SMC_US(table->BootMVdd);
1318
1319         return 0;
1320 }
1321
1322 static int polaris10_populate_smc_initailial_state(struct pp_hwmgr *hwmgr)
1323 {
1324         struct pp_smumgr *smumgr = hwmgr->smumgr;
1325         struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend);
1326         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend);
1327         struct phm_ppt_v1_information *table_info =
1328                         (struct phm_ppt_v1_information *)(hwmgr->pptable);
1329         uint8_t count, level;
1330
1331         count = (uint8_t)(table_info->vdd_dep_on_sclk->count);
1332
1333         for (level = 0; level < count; level++) {
1334                 if (table_info->vdd_dep_on_sclk->entries[level].clk >=
1335                                 hw_data->vbios_boot_state.sclk_bootup_value) {
1336                         smu_data->smc_state_table.GraphicsBootLevel = level;
1337                         break;
1338                 }
1339         }
1340
1341         count = (uint8_t)(table_info->vdd_dep_on_mclk->count);
1342         for (level = 0; level < count; level++) {
1343                 if (table_info->vdd_dep_on_mclk->entries[level].clk >=
1344                                 hw_data->vbios_boot_state.mclk_bootup_value) {
1345                         smu_data->smc_state_table.MemoryBootLevel = level;
1346                         break;
1347                 }
1348         }
1349
1350         return 0;
1351 }
1352
1353
1354 static int polaris10_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr)
1355 {
1356         uint32_t ro, efuse, volt_without_cks, volt_with_cks, value, max, min;
1357         struct pp_smumgr *smumgr = hwmgr->smumgr;
1358         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend);
1359
1360         uint8_t i, stretch_amount, stretch_amount2, volt_offset = 0;
1361         struct phm_ppt_v1_information *table_info =
1362                         (struct phm_ppt_v1_information *)(hwmgr->pptable);
1363         struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table =
1364                         table_info->vdd_dep_on_sclk;
1365
1366         stretch_amount = (uint8_t)table_info->cac_dtp_table->usClockStretchAmount;
1367
1368         /* Read SMU_Eefuse to read and calculate RO and determine
1369          * if the part is SS or FF. if RO >= 1660MHz, part is FF.
1370          */
1371         efuse = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC,
1372                         ixSMU_EFUSE_0 + (67 * 4));
1373         efuse &= 0xFF000000;
1374         efuse = efuse >> 24;
1375
1376         if (hwmgr->chip_id == CHIP_POLARIS10) {
1377                 min = 1000;
1378                 max = 2300;
1379         } else {
1380                 min = 1100;
1381                 max = 2100;
1382         }
1383
1384         ro = efuse * (max - min) / 255 + min;
1385
1386         /* Populate Sclk_CKS_masterEn0_7 and Sclk_voltageOffset */
1387         for (i = 0; i < sclk_table->count; i++) {
1388                 smu_data->smc_state_table.Sclk_CKS_masterEn0_7 |=
1389                                 sclk_table->entries[i].cks_enable << i;
1390                 if (hwmgr->chip_id == CHIP_POLARIS10) {
1391                         volt_without_cks = (uint32_t)((2753594000U + (sclk_table->entries[i].clk/100) * 136418 - (ro - 70) * 1000000) / \
1392                                                 (2424180 - (sclk_table->entries[i].clk/100) * 1132925/1000));
1393                         volt_with_cks = (uint32_t)((2797202000U + sclk_table->entries[i].clk/100 * 3232 - (ro - 65) * 1000000) / \
1394                                         (2522480 - sclk_table->entries[i].clk/100 * 115764/100));
1395                 } else {
1396                         volt_without_cks = (uint32_t)((2416794800U + (sclk_table->entries[i].clk/100) * 1476925/10 - (ro - 50) * 1000000) / \
1397                                                 (2625416 - (sclk_table->entries[i].clk/100) * (12586807/10000)));
1398                         volt_with_cks = (uint32_t)((2999656000U - sclk_table->entries[i].clk/100 * 392803 - (ro - 44) * 1000000) / \
1399                                         (3422454 - sclk_table->entries[i].clk/100 * (18886376/10000)));
1400                 }
1401
1402                 if (volt_without_cks >= volt_with_cks)
1403                         volt_offset = (uint8_t)(((volt_without_cks - volt_with_cks +
1404                                         sclk_table->entries[i].cks_voffset) * 100 + 624) / 625);
1405
1406                 smu_data->smc_state_table.Sclk_voltageOffset[i] = volt_offset;
1407         }
1408
1409         smu_data->smc_state_table.LdoRefSel = (table_info->cac_dtp_table->ucCKS_LDO_REFSEL != 0) ? table_info->cac_dtp_table->ucCKS_LDO_REFSEL : 6;
1410         /* Populate CKS Lookup Table */
1411         if (stretch_amount == 1 || stretch_amount == 2 || stretch_amount == 5)
1412                 stretch_amount2 = 0;
1413         else if (stretch_amount == 3 || stretch_amount == 4)
1414                 stretch_amount2 = 1;
1415         else {
1416                 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
1417                                 PHM_PlatformCaps_ClockStretcher);
1418                 PP_ASSERT_WITH_CODE(false,
1419                                 "Stretch Amount in PPTable not supported\n",
1420                                 return -EINVAL);
1421         }
1422
1423         value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixPWR_CKS_CNTL);
1424         value &= 0xFFFFFFFE;
1425         cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixPWR_CKS_CNTL, value);
1426
1427         return 0;
1428 }
1429
1430 /**
1431 * Populates the SMC VRConfig field in DPM table.
1432 *
1433 * @param    hwmgr   the address of the hardware manager
1434 * @param    table   the SMC DPM table structure to be populated
1435 * @return   always 0
1436 */
1437 static int polaris10_populate_vr_config(struct pp_hwmgr *hwmgr,
1438                 struct SMU74_Discrete_DpmTable *table)
1439 {
1440         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1441         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend);
1442         uint16_t config;
1443
1444         config = VR_MERGED_WITH_VDDC;
1445         table->VRConfig |= (config << VRCONF_VDDGFX_SHIFT);
1446
1447         /* Set Vddc Voltage Controller */
1448         if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) {
1449                 config = VR_SVI2_PLANE_1;
1450                 table->VRConfig |= config;
1451         } else {
1452                 PP_ASSERT_WITH_CODE(false,
1453                                 "VDDC should be on SVI2 control in merged mode!",
1454                                 );
1455         }
1456         /* Set Vddci Voltage Controller */
1457         if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) {
1458                 config = VR_SVI2_PLANE_2;  /* only in merged mode */
1459                 table->VRConfig |= (config << VRCONF_VDDCI_SHIFT);
1460         } else if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) {
1461                 config = VR_SMIO_PATTERN_1;
1462                 table->VRConfig |= (config << VRCONF_VDDCI_SHIFT);
1463         } else {
1464                 config = VR_STATIC_VOLTAGE;
1465                 table->VRConfig |= (config << VRCONF_VDDCI_SHIFT);
1466         }
1467         /* Set Mvdd Voltage Controller */
1468         if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->mvdd_control) {
1469                 config = VR_SVI2_PLANE_2;
1470                 table->VRConfig |= (config << VRCONF_MVDD_SHIFT);
1471                 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, smu_data->smu7_data.soft_regs_start +
1472                         offsetof(SMU74_SoftRegisters, AllowMvddSwitch), 0x1);
1473         } else {
1474                 config = VR_STATIC_VOLTAGE;
1475                 table->VRConfig |= (config << VRCONF_MVDD_SHIFT);
1476         }
1477
1478         return 0;
1479 }
1480
1481
1482 static int polaris10_populate_avfs_parameters(struct pp_hwmgr *hwmgr)
1483 {
1484         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1485         struct pp_smumgr *smumgr = hwmgr->smumgr;
1486         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend);
1487
1488         SMU74_Discrete_DpmTable  *table = &(smu_data->smc_state_table);
1489         int result = 0;
1490         struct pp_atom_ctrl__avfs_parameters avfs_params = {0};
1491         AVFS_meanNsigma_t AVFS_meanNsigma = { {0} };
1492         AVFS_Sclk_Offset_t AVFS_SclkOffset = { {0} };
1493         uint32_t tmp, i;
1494
1495         struct phm_ppt_v1_information *table_info =
1496                         (struct phm_ppt_v1_information *)hwmgr->pptable;
1497         struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table =
1498                         table_info->vdd_dep_on_sclk;
1499
1500
1501         if (smu_data->avfs.avfs_btc_status == AVFS_BTC_NOTSUPPORTED)
1502                 return result;
1503
1504         result = atomctrl_get_avfs_information(hwmgr, &avfs_params);
1505
1506         if (0 == result) {
1507                 table->BTCGB_VDROOP_TABLE[0].a0  = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSON_a0);
1508                 table->BTCGB_VDROOP_TABLE[0].a1  = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSON_a1);
1509                 table->BTCGB_VDROOP_TABLE[0].a2  = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSON_a2);
1510                 table->BTCGB_VDROOP_TABLE[1].a0  = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a0);
1511                 table->BTCGB_VDROOP_TABLE[1].a1  = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a1);
1512                 table->BTCGB_VDROOP_TABLE[1].a2  = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a2);
1513                 table->AVFSGB_VDROOP_TABLE[0].m1 = PP_HOST_TO_SMC_UL(avfs_params.ulAVFSGB_FUSE_TABLE_CKSON_m1);
1514                 table->AVFSGB_VDROOP_TABLE[0].m2 = PP_HOST_TO_SMC_US(avfs_params.usAVFSGB_FUSE_TABLE_CKSON_m2);
1515                 table->AVFSGB_VDROOP_TABLE[0].b  = PP_HOST_TO_SMC_UL(avfs_params.ulAVFSGB_FUSE_TABLE_CKSON_b);
1516                 table->AVFSGB_VDROOP_TABLE[0].m1_shift = 24;
1517                 table->AVFSGB_VDROOP_TABLE[0].m2_shift  = 12;
1518                 table->AVFSGB_VDROOP_TABLE[1].m1 = PP_HOST_TO_SMC_UL(avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_m1);
1519                 table->AVFSGB_VDROOP_TABLE[1].m2 = PP_HOST_TO_SMC_US(avfs_params.usAVFSGB_FUSE_TABLE_CKSOFF_m2);
1520                 table->AVFSGB_VDROOP_TABLE[1].b  = PP_HOST_TO_SMC_UL(avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_b);
1521                 table->AVFSGB_VDROOP_TABLE[1].m1_shift = 24;
1522                 table->AVFSGB_VDROOP_TABLE[1].m2_shift  = 12;
1523                 table->MaxVoltage                = PP_HOST_TO_SMC_US(avfs_params.usMaxVoltage_0_25mv);
1524                 AVFS_meanNsigma.Aconstant[0]      = PP_HOST_TO_SMC_UL(avfs_params.ulAVFS_meanNsigma_Acontant0);
1525                 AVFS_meanNsigma.Aconstant[1]      = PP_HOST_TO_SMC_UL(avfs_params.ulAVFS_meanNsigma_Acontant1);
1526                 AVFS_meanNsigma.Aconstant[2]      = PP_HOST_TO_SMC_UL(avfs_params.ulAVFS_meanNsigma_Acontant2);
1527                 AVFS_meanNsigma.DC_tol_sigma      = PP_HOST_TO_SMC_US(avfs_params.usAVFS_meanNsigma_DC_tol_sigma);
1528                 AVFS_meanNsigma.Platform_mean     = PP_HOST_TO_SMC_US(avfs_params.usAVFS_meanNsigma_Platform_mean);
1529                 AVFS_meanNsigma.PSM_Age_CompFactor = PP_HOST_TO_SMC_US(avfs_params.usPSM_Age_ComFactor);
1530                 AVFS_meanNsigma.Platform_sigma     = PP_HOST_TO_SMC_US(avfs_params.usAVFS_meanNsigma_Platform_sigma);
1531
1532                 for (i = 0; i < NUM_VFT_COLUMNS; i++) {
1533                         AVFS_meanNsigma.Static_Voltage_Offset[i] = (uint8_t)(sclk_table->entries[i].cks_voffset * 100 / 625);
1534                         AVFS_SclkOffset.Sclk_Offset[i] = PP_HOST_TO_SMC_US((uint16_t)(sclk_table->entries[i].sclk_offset) / 100);
1535                 }
1536
1537                 result = smu7_read_smc_sram_dword(smumgr,
1538                                 SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU74_Firmware_Header, AvfsMeanNSigma),
1539                                 &tmp, SMC_RAM_END);
1540
1541                 smu7_copy_bytes_to_smc(smumgr,
1542                                         tmp,
1543                                         (uint8_t *)&AVFS_meanNsigma,
1544                                         sizeof(AVFS_meanNsigma_t),
1545                                         SMC_RAM_END);
1546
1547                 result = smu7_read_smc_sram_dword(smumgr,
1548                                 SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU74_Firmware_Header, AvfsSclkOffsetTable),
1549                                 &tmp, SMC_RAM_END);
1550                 smu7_copy_bytes_to_smc(smumgr,
1551                                         tmp,
1552                                         (uint8_t *)&AVFS_SclkOffset,
1553                                         sizeof(AVFS_Sclk_Offset_t),
1554                                         SMC_RAM_END);
1555
1556                 data->avfs_vdroop_override_setting = (avfs_params.ucEnableGB_VDROOP_TABLE_CKSON << BTCGB0_Vdroop_Enable_SHIFT) |
1557                                                 (avfs_params.ucEnableGB_VDROOP_TABLE_CKSOFF << BTCGB1_Vdroop_Enable_SHIFT) |
1558                                                 (avfs_params.ucEnableGB_FUSE_TABLE_CKSON << AVFSGB0_Vdroop_Enable_SHIFT) |
1559                                                 (avfs_params.ucEnableGB_FUSE_TABLE_CKSOFF << AVFSGB1_Vdroop_Enable_SHIFT);
1560                 data->apply_avfs_cks_off_voltage = (avfs_params.ucEnableApplyAVFS_CKS_OFF_Voltage == 1) ? true : false;
1561         }
1562         return result;
1563 }
1564
1565
1566 /**
1567 * Initialize the ARB DRAM timing table's index field.
1568 *
1569 * @param    hwmgr  the address of the powerplay hardware manager.
1570 * @return   always 0
1571 */
1572 static int polaris10_init_arb_table_index(struct pp_smumgr *smumgr)
1573 {
1574         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend);
1575         uint32_t tmp;
1576         int result;
1577
1578         /* This is a read-modify-write on the first byte of the ARB table.
1579          * The first byte in the SMU73_Discrete_MCArbDramTimingTable structure
1580          * is the field 'current'.
1581          * This solution is ugly, but we never write the whole table only
1582          * individual fields in it.
1583          * In reality this field should not be in that structure
1584          * but in a soft register.
1585          */
1586         result = smu7_read_smc_sram_dword(smumgr,
1587                         smu_data->smu7_data.arb_table_start, &tmp, SMC_RAM_END);
1588
1589         if (result)
1590                 return result;
1591
1592         tmp &= 0x00FFFFFF;
1593         tmp |= ((uint32_t)MC_CG_ARB_FREQ_F1) << 24;
1594
1595         return smu7_write_smc_sram_dword(smumgr,
1596                         smu_data->smu7_data.arb_table_start, tmp, SMC_RAM_END);
1597 }
1598
1599 static void polaris10_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr)
1600 {
1601         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend);
1602         struct  phm_ppt_v1_information *table_info =
1603                         (struct  phm_ppt_v1_information *)(hwmgr->pptable);
1604
1605         if (table_info &&
1606                         table_info->cac_dtp_table->usPowerTuneDataSetID <= POWERTUNE_DEFAULT_SET_MAX &&
1607                         table_info->cac_dtp_table->usPowerTuneDataSetID)
1608                 smu_data->power_tune_defaults =
1609                                 &polaris10_power_tune_data_set_array
1610                                 [table_info->cac_dtp_table->usPowerTuneDataSetID - 1];
1611         else
1612                 smu_data->power_tune_defaults = &polaris10_power_tune_data_set_array[0];
1613
1614 }
1615
1616 /**
1617 * Initializes the SMC table and uploads it
1618 *
1619 * @param    hwmgr  the address of the powerplay hardware manager.
1620 * @return   always 0
1621 */
1622 int polaris10_init_smc_table(struct pp_hwmgr *hwmgr)
1623 {
1624         int result;
1625         struct pp_smumgr *smumgr = hwmgr->smumgr;
1626         struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend);
1627         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend);
1628         struct phm_ppt_v1_information *table_info =
1629                         (struct phm_ppt_v1_information *)(hwmgr->pptable);
1630         struct SMU74_Discrete_DpmTable *table = &(smu_data->smc_state_table);
1631         uint8_t i;
1632         struct pp_atomctrl_gpio_pin_assignment gpio_pin;
1633         pp_atomctrl_clock_dividers_vi dividers;
1634
1635         polaris10_initialize_power_tune_defaults(hwmgr);
1636
1637         if (SMU7_VOLTAGE_CONTROL_NONE != hw_data->voltage_control)
1638                 polaris10_populate_smc_voltage_tables(hwmgr, table);
1639
1640         table->SystemFlags = 0;
1641         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1642                         PHM_PlatformCaps_AutomaticDCTransition))
1643                 table->SystemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC;
1644
1645         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1646                         PHM_PlatformCaps_StepVddc))
1647                 table->SystemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC;
1648
1649         if (hw_data->is_memory_gddr5)
1650                 table->SystemFlags |= PPSMC_SYSTEMFLAG_GDDR5;
1651
1652         if (hw_data->ulv_supported && table_info->us_ulv_voltage_offset) {
1653                 result = polaris10_populate_ulv_state(hwmgr, table);
1654                 PP_ASSERT_WITH_CODE(0 == result,
1655                                 "Failed to initialize ULV state!", return result);
1656                 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
1657                                 ixCG_ULV_PARAMETER, SMU7_CGULVPARAMETER_DFLT);
1658         }
1659
1660         result = polaris10_populate_smc_link_level(hwmgr, table);
1661         PP_ASSERT_WITH_CODE(0 == result,
1662                         "Failed to initialize Link Level!", return result);
1663
1664         result = polaris10_populate_all_graphic_levels(hwmgr);
1665         PP_ASSERT_WITH_CODE(0 == result,
1666                         "Failed to initialize Graphics Level!", return result);
1667
1668         result = polaris10_populate_all_memory_levels(hwmgr);
1669         PP_ASSERT_WITH_CODE(0 == result,
1670                         "Failed to initialize Memory Level!", return result);
1671
1672         result = polaris10_populate_smc_acpi_level(hwmgr, table);
1673         PP_ASSERT_WITH_CODE(0 == result,
1674                         "Failed to initialize ACPI Level!", return result);
1675
1676         result = polaris10_populate_smc_vce_level(hwmgr, table);
1677         PP_ASSERT_WITH_CODE(0 == result,
1678                         "Failed to initialize VCE Level!", return result);
1679
1680         result = polaris10_populate_smc_samu_level(hwmgr, table);
1681         PP_ASSERT_WITH_CODE(0 == result,
1682                         "Failed to initialize SAMU Level!", return result);
1683
1684         /* Since only the initial state is completely set up at this point
1685          * (the other states are just copies of the boot state) we only
1686          * need to populate the  ARB settings for the initial state.
1687          */
1688         result = polaris10_program_memory_timing_parameters(hwmgr);
1689         PP_ASSERT_WITH_CODE(0 == result,
1690                         "Failed to Write ARB settings for the initial state.", return result);
1691
1692         result = polaris10_populate_smc_uvd_level(hwmgr, table);
1693         PP_ASSERT_WITH_CODE(0 == result,
1694                         "Failed to initialize UVD Level!", return result);
1695
1696         result = polaris10_populate_smc_boot_level(hwmgr, table);
1697         PP_ASSERT_WITH_CODE(0 == result,
1698                         "Failed to initialize Boot Level!", return result);
1699
1700         result = polaris10_populate_smc_initailial_state(hwmgr);
1701         PP_ASSERT_WITH_CODE(0 == result,
1702                         "Failed to initialize Boot State!", return result);
1703
1704         result = polaris10_populate_bapm_parameters_in_dpm_table(hwmgr);
1705         PP_ASSERT_WITH_CODE(0 == result,
1706                         "Failed to populate BAPM Parameters!", return result);
1707
1708         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1709                         PHM_PlatformCaps_ClockStretcher)) {
1710                 result = polaris10_populate_clock_stretcher_data_table(hwmgr);
1711                 PP_ASSERT_WITH_CODE(0 == result,
1712                                 "Failed to populate Clock Stretcher Data Table!",
1713                                 return result);
1714         }
1715
1716         result = polaris10_populate_avfs_parameters(hwmgr);
1717         PP_ASSERT_WITH_CODE(0 == result, "Failed to populate AVFS Parameters!", return result;);
1718
1719         table->CurrSclkPllRange = 0xff;
1720         table->GraphicsVoltageChangeEnable  = 1;
1721         table->GraphicsThermThrottleEnable  = 1;
1722         table->GraphicsInterval = 1;
1723         table->VoltageInterval  = 1;
1724         table->ThermalInterval  = 1;
1725         table->TemperatureLimitHigh =
1726                         table_info->cac_dtp_table->usTargetOperatingTemp *
1727                         SMU7_Q88_FORMAT_CONVERSION_UNIT;
1728         table->TemperatureLimitLow  =
1729                         (table_info->cac_dtp_table->usTargetOperatingTemp - 1) *
1730                         SMU7_Q88_FORMAT_CONVERSION_UNIT;
1731         table->MemoryVoltageChangeEnable = 1;
1732         table->MemoryInterval = 1;
1733         table->VoltageResponseTime = 0;
1734         table->PhaseResponseTime = 0;
1735         table->MemoryThermThrottleEnable = 1;
1736         table->PCIeBootLinkLevel = 0;
1737         table->PCIeGenInterval = 1;
1738         table->VRConfig = 0;
1739
1740         result = polaris10_populate_vr_config(hwmgr, table);
1741         PP_ASSERT_WITH_CODE(0 == result,
1742                         "Failed to populate VRConfig setting!", return result);
1743
1744         table->ThermGpio = 17;
1745         table->SclkStepSize = 0x4000;
1746
1747         if (atomctrl_get_pp_assign_pin(hwmgr, VDDC_VRHOT_GPIO_PINID, &gpio_pin)) {
1748                 table->VRHotGpio = gpio_pin.uc_gpio_pin_bit_shift;
1749         } else {
1750                 table->VRHotGpio = SMU7_UNUSED_GPIO_PIN;
1751                 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
1752                                 PHM_PlatformCaps_RegulatorHot);
1753         }
1754
1755         if (atomctrl_get_pp_assign_pin(hwmgr, PP_AC_DC_SWITCH_GPIO_PINID,
1756                         &gpio_pin)) {
1757                 table->AcDcGpio = gpio_pin.uc_gpio_pin_bit_shift;
1758                 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1759                                 PHM_PlatformCaps_AutomaticDCTransition);
1760         } else {
1761                 table->AcDcGpio = SMU7_UNUSED_GPIO_PIN;
1762                 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
1763                                 PHM_PlatformCaps_AutomaticDCTransition);
1764         }
1765
1766         /* Thermal Output GPIO */
1767         if (atomctrl_get_pp_assign_pin(hwmgr, THERMAL_INT_OUTPUT_GPIO_PINID,
1768                         &gpio_pin)) {
1769                 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1770                                 PHM_PlatformCaps_ThermalOutGPIO);
1771
1772                 table->ThermOutGpio = gpio_pin.uc_gpio_pin_bit_shift;
1773
1774                 /* For porlarity read GPIOPAD_A with assigned Gpio pin
1775                  * since VBIOS will program this register to set 'inactive state',
1776                  * driver can then determine 'active state' from this and
1777                  * program SMU with correct polarity
1778                  */
1779                 table->ThermOutPolarity = (0 == (cgs_read_register(hwmgr->device, mmGPIOPAD_A)
1780                                         & (1 << gpio_pin.uc_gpio_pin_bit_shift))) ? 1:0;
1781                 table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_ONLY;
1782
1783                 /* if required, combine VRHot/PCC with thermal out GPIO */
1784                 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_RegulatorHot)
1785                 && phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_CombinePCCWithThermalSignal))
1786                         table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_VRHOT;
1787         } else {
1788                 table->ThermOutGpio = 17;
1789                 table->ThermOutPolarity = 1;
1790                 table->ThermOutMode = SMU7_THERM_OUT_MODE_DISABLE;
1791         }
1792
1793         /* Populate BIF_SCLK levels into SMC DPM table */
1794         for (i = 0; i <= hw_data->dpm_table.pcie_speed_table.count; i++) {
1795                 result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, smu_data->bif_sclk_table[i], &dividers);
1796                 PP_ASSERT_WITH_CODE((result == 0), "Can not find DFS divide id for Sclk", return result);
1797
1798                 if (i == 0)
1799                         table->Ulv.BifSclkDfs = PP_HOST_TO_SMC_US((USHORT)(dividers.pll_post_divider));
1800                 else
1801                         table->LinkLevel[i-1].BifSclkDfs = PP_HOST_TO_SMC_US((USHORT)(dividers.pll_post_divider));
1802         }
1803
1804         for (i = 0; i < SMU74_MAX_ENTRIES_SMIO; i++)
1805                 table->Smio[i] = PP_HOST_TO_SMC_UL(table->Smio[i]);
1806
1807         CONVERT_FROM_HOST_TO_SMC_UL(table->SystemFlags);
1808         CONVERT_FROM_HOST_TO_SMC_UL(table->VRConfig);
1809         CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask1);
1810         CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask2);
1811         CONVERT_FROM_HOST_TO_SMC_UL(table->SclkStepSize);
1812         CONVERT_FROM_HOST_TO_SMC_UL(table->CurrSclkPllRange);
1813         CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitHigh);
1814         CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitLow);
1815         CONVERT_FROM_HOST_TO_SMC_US(table->VoltageResponseTime);
1816         CONVERT_FROM_HOST_TO_SMC_US(table->PhaseResponseTime);
1817
1818         /* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */
1819         result = smu7_copy_bytes_to_smc(hwmgr->smumgr,
1820                         smu_data->smu7_data.dpm_table_start +
1821                         offsetof(SMU74_Discrete_DpmTable, SystemFlags),
1822                         (uint8_t *)&(table->SystemFlags),
1823                         sizeof(SMU74_Discrete_DpmTable) - 3 * sizeof(SMU74_PIDController),
1824                         SMC_RAM_END);
1825         PP_ASSERT_WITH_CODE(0 == result,
1826                         "Failed to upload dpm data to SMC memory!", return result);
1827
1828         result = polaris10_init_arb_table_index(hwmgr->smumgr);
1829         PP_ASSERT_WITH_CODE(0 == result,
1830                         "Failed to upload arb data to SMC memory!", return result);
1831
1832         result = polaris10_populate_pm_fuses(hwmgr);
1833         PP_ASSERT_WITH_CODE(0 == result,
1834                         "Failed to  populate PM fuses to SMC memory!", return result);
1835         return 0;
1836 }
1837
1838 static int polaris10_program_mem_timing_parameters(struct pp_hwmgr *hwmgr)
1839 {
1840         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1841
1842         if (data->need_update_smu7_dpm_table &
1843                 (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_OD_UPDATE_MCLK))
1844                 return polaris10_program_memory_timing_parameters(hwmgr);
1845
1846         return 0;
1847 }
1848
1849 int polaris10_thermal_avfs_enable(struct pp_hwmgr *hwmgr)
1850 {
1851         int ret;
1852         struct pp_smumgr *smumgr = (struct pp_smumgr *)(hwmgr->smumgr);
1853         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend);
1854         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1855
1856         if (smu_data->avfs.avfs_btc_status == AVFS_BTC_NOTSUPPORTED)
1857                 return 0;
1858
1859         ret = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
1860                         PPSMC_MSG_SetGBDroopSettings, data->avfs_vdroop_override_setting);
1861
1862         ret = (smum_send_msg_to_smc(smumgr, PPSMC_MSG_EnableAvfs) == 0) ?
1863                         0 : -1;
1864
1865         if (!ret)
1866                 /* If this param is not changed, this function could fire unnecessarily */
1867                 smu_data->avfs.avfs_btc_status = AVFS_BTC_COMPLETED_PREVIOUSLY;
1868
1869         return ret;
1870 }
1871
1872 /**
1873 * Set up the fan table to control the fan using the SMC.
1874 * @param    hwmgr  the address of the powerplay hardware manager.
1875 * @param    pInput the pointer to input data
1876 * @param    pOutput the pointer to output data
1877 * @param    pStorage the pointer to temporary storage
1878 * @param    Result the last failure code
1879 * @return   result from set temperature range routine
1880 */
1881 int polaris10_thermal_setup_fan_table(struct pp_hwmgr *hwmgr)
1882 {
1883         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend);
1884         SMU74_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE };
1885         uint32_t duty100;
1886         uint32_t t_diff1, t_diff2, pwm_diff1, pwm_diff2;
1887         uint16_t fdo_min, slope1, slope2;
1888         uint32_t reference_clock;
1889         int res;
1890         uint64_t tmp64;
1891
1892         if (hwmgr->thermal_controller.fanInfo.bNoFan) {
1893                 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
1894                         PHM_PlatformCaps_MicrocodeFanControl);
1895                 return 0;
1896         }
1897
1898         if (smu_data->smu7_data.fan_table_start == 0) {
1899                 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
1900                                 PHM_PlatformCaps_MicrocodeFanControl);
1901                 return 0;
1902         }
1903
1904         duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
1905                         CG_FDO_CTRL1, FMAX_DUTY100);
1906
1907         if (duty100 == 0) {
1908                 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
1909                                 PHM_PlatformCaps_MicrocodeFanControl);
1910                 return 0;
1911         }
1912
1913         tmp64 = hwmgr->thermal_controller.advanceFanControlParameters.
1914                         usPWMMin * duty100;
1915         do_div(tmp64, 10000);
1916         fdo_min = (uint16_t)tmp64;
1917
1918         t_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usTMed -
1919                         hwmgr->thermal_controller.advanceFanControlParameters.usTMin;
1920         t_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usTHigh -
1921                         hwmgr->thermal_controller.advanceFanControlParameters.usTMed;
1922
1923         pwm_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed -
1924                         hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin;
1925         pwm_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh -
1926                         hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed;
1927
1928         slope1 = (uint16_t)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100);
1929         slope2 = (uint16_t)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100);
1930
1931         fan_table.TempMin = cpu_to_be16((50 + hwmgr->
1932                         thermal_controller.advanceFanControlParameters.usTMin) / 100);
1933         fan_table.TempMed = cpu_to_be16((50 + hwmgr->
1934                         thermal_controller.advanceFanControlParameters.usTMed) / 100);
1935         fan_table.TempMax = cpu_to_be16((50 + hwmgr->
1936                         thermal_controller.advanceFanControlParameters.usTMax) / 100);
1937
1938         fan_table.Slope1 = cpu_to_be16(slope1);
1939         fan_table.Slope2 = cpu_to_be16(slope2);
1940
1941         fan_table.FdoMin = cpu_to_be16(fdo_min);
1942
1943         fan_table.HystDown = cpu_to_be16(hwmgr->
1944                         thermal_controller.advanceFanControlParameters.ucTHyst);
1945
1946         fan_table.HystUp = cpu_to_be16(1);
1947
1948         fan_table.HystSlope = cpu_to_be16(1);
1949
1950         fan_table.TempRespLim = cpu_to_be16(5);
1951
1952         reference_clock = smu7_get_xclk(hwmgr);
1953
1954         fan_table.RefreshPeriod = cpu_to_be32((hwmgr->
1955                         thermal_controller.advanceFanControlParameters.ulCycleDelay *
1956                         reference_clock) / 1600);
1957
1958         fan_table.FdoMax = cpu_to_be16((uint16_t)duty100);
1959
1960         fan_table.TempSrc = (uint8_t)PHM_READ_VFPF_INDIRECT_FIELD(
1961                         hwmgr->device, CGS_IND_REG__SMC,
1962                         CG_MULT_THERMAL_CTRL, TEMP_SEL);
1963
1964         res = smu7_copy_bytes_to_smc(hwmgr->smumgr, smu_data->smu7_data.fan_table_start,
1965                         (uint8_t *)&fan_table, (uint32_t)sizeof(fan_table),
1966                         SMC_RAM_END);
1967
1968         if (!res && hwmgr->thermal_controller.
1969                         advanceFanControlParameters.ucMinimumPWMLimit)
1970                 res = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
1971                                 PPSMC_MSG_SetFanMinPwm,
1972                                 hwmgr->thermal_controller.
1973                                 advanceFanControlParameters.ucMinimumPWMLimit);
1974
1975         if (!res && hwmgr->thermal_controller.
1976                         advanceFanControlParameters.ulMinFanSCLKAcousticLimit)
1977                 res = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
1978                                 PPSMC_MSG_SetFanSclkTarget,
1979                                 hwmgr->thermal_controller.
1980                                 advanceFanControlParameters.ulMinFanSCLKAcousticLimit);
1981
1982         if (res)
1983                 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
1984                                 PHM_PlatformCaps_MicrocodeFanControl);
1985
1986         return 0;
1987 }
1988
1989 static int polaris10_update_uvd_smc_table(struct pp_hwmgr *hwmgr)
1990 {
1991         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend);
1992         uint32_t mm_boot_level_offset, mm_boot_level_value;
1993         struct phm_ppt_v1_information *table_info =
1994                         (struct phm_ppt_v1_information *)(hwmgr->pptable);
1995
1996         smu_data->smc_state_table.UvdBootLevel = 0;
1997         if (table_info->mm_dep_table->count > 0)
1998                 smu_data->smc_state_table.UvdBootLevel =
1999                                 (uint8_t) (table_info->mm_dep_table->count - 1);
2000         mm_boot_level_offset = smu_data->smu7_data.dpm_table_start + offsetof(SMU74_Discrete_DpmTable,
2001                                                 UvdBootLevel);
2002         mm_boot_level_offset /= 4;
2003         mm_boot_level_offset *= 4;
2004         mm_boot_level_value = cgs_read_ind_register(hwmgr->device,
2005                         CGS_IND_REG__SMC, mm_boot_level_offset);
2006         mm_boot_level_value &= 0x00FFFFFF;
2007         mm_boot_level_value |= smu_data->smc_state_table.UvdBootLevel << 24;
2008         cgs_write_ind_register(hwmgr->device,
2009                         CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value);
2010
2011         if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2012                         PHM_PlatformCaps_UVDDPM) ||
2013                 phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2014                         PHM_PlatformCaps_StablePState))
2015                 smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
2016                                 PPSMC_MSG_UVDDPM_SetEnabledMask,
2017                                 (uint32_t)(1 << smu_data->smc_state_table.UvdBootLevel));
2018         return 0;
2019 }
2020
2021 static int polaris10_update_vce_smc_table(struct pp_hwmgr *hwmgr)
2022 {
2023         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend);
2024         uint32_t mm_boot_level_offset, mm_boot_level_value;
2025         struct phm_ppt_v1_information *table_info =
2026                         (struct phm_ppt_v1_information *)(hwmgr->pptable);
2027
2028         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2029                                         PHM_PlatformCaps_StablePState))
2030                 smu_data->smc_state_table.VceBootLevel =
2031                         (uint8_t) (table_info->mm_dep_table->count - 1);
2032         else
2033                 smu_data->smc_state_table.VceBootLevel = 0;
2034
2035         mm_boot_level_offset = smu_data->smu7_data.dpm_table_start +
2036                                         offsetof(SMU74_Discrete_DpmTable, VceBootLevel);
2037         mm_boot_level_offset /= 4;
2038         mm_boot_level_offset *= 4;
2039         mm_boot_level_value = cgs_read_ind_register(hwmgr->device,
2040                         CGS_IND_REG__SMC, mm_boot_level_offset);
2041         mm_boot_level_value &= 0xFF00FFFF;
2042         mm_boot_level_value |= smu_data->smc_state_table.VceBootLevel << 16;
2043         cgs_write_ind_register(hwmgr->device,
2044                         CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value);
2045
2046         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState))
2047                 smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
2048                                 PPSMC_MSG_VCEDPM_SetEnabledMask,
2049                                 (uint32_t)1 << smu_data->smc_state_table.VceBootLevel);
2050         return 0;
2051 }
2052
2053 static int polaris10_update_samu_smc_table(struct pp_hwmgr *hwmgr)
2054 {
2055         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend);
2056         uint32_t mm_boot_level_offset, mm_boot_level_value;
2057
2058
2059         smu_data->smc_state_table.SamuBootLevel = 0;
2060         mm_boot_level_offset = smu_data->smu7_data.dpm_table_start +
2061                                 offsetof(SMU74_Discrete_DpmTable, SamuBootLevel);
2062
2063         mm_boot_level_offset /= 4;
2064         mm_boot_level_offset *= 4;
2065         mm_boot_level_value = cgs_read_ind_register(hwmgr->device,
2066                         CGS_IND_REG__SMC, mm_boot_level_offset);
2067         mm_boot_level_value &= 0xFFFFFF00;
2068         mm_boot_level_value |= smu_data->smc_state_table.SamuBootLevel << 0;
2069         cgs_write_ind_register(hwmgr->device,
2070                         CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value);
2071
2072         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2073                         PHM_PlatformCaps_StablePState))
2074                 smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
2075                                 PPSMC_MSG_SAMUDPM_SetEnabledMask,
2076                                 (uint32_t)(1 << smu_data->smc_state_table.SamuBootLevel));
2077         return 0;
2078 }
2079
2080
2081 static int polaris10_update_bif_smc_table(struct pp_hwmgr *hwmgr)
2082 {
2083         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend);
2084         struct phm_ppt_v1_information *table_info =
2085                         (struct phm_ppt_v1_information *)(hwmgr->pptable);
2086         struct phm_ppt_v1_pcie_table *pcie_table = table_info->pcie_table;
2087         int max_entry, i;
2088
2089         max_entry = (SMU74_MAX_LEVELS_LINK < pcie_table->count) ?
2090                                                 SMU74_MAX_LEVELS_LINK :
2091                                                 pcie_table->count;
2092         /* Setup BIF_SCLK levels */
2093         for (i = 0; i < max_entry; i++)
2094                 smu_data->bif_sclk_table[i] = pcie_table->entries[i].pcie_sclk;
2095         return 0;
2096 }
2097
2098 int polaris10_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type)
2099 {
2100         switch (type) {
2101         case SMU_UVD_TABLE:
2102                 polaris10_update_uvd_smc_table(hwmgr);
2103                 break;
2104         case SMU_VCE_TABLE:
2105                 polaris10_update_vce_smc_table(hwmgr);
2106                 break;
2107         case SMU_SAMU_TABLE:
2108                 polaris10_update_samu_smc_table(hwmgr);
2109                 break;
2110         case SMU_BIF_TABLE:
2111                 polaris10_update_bif_smc_table(hwmgr);
2112         default:
2113                 break;
2114         }
2115         return 0;
2116 }
2117
2118 int polaris10_update_sclk_threshold(struct pp_hwmgr *hwmgr)
2119 {
2120         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2121         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend);
2122
2123         int result = 0;
2124         uint32_t low_sclk_interrupt_threshold = 0;
2125
2126         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2127                         PHM_PlatformCaps_SclkThrottleLowNotification)
2128                 && (hwmgr->gfx_arbiter.sclk_threshold !=
2129                                 data->low_sclk_interrupt_threshold)) {
2130                 data->low_sclk_interrupt_threshold =
2131                                 hwmgr->gfx_arbiter.sclk_threshold;
2132                 low_sclk_interrupt_threshold =
2133                                 data->low_sclk_interrupt_threshold;
2134
2135                 CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold);
2136
2137                 result = smu7_copy_bytes_to_smc(
2138                                 hwmgr->smumgr,
2139                                 smu_data->smu7_data.dpm_table_start +
2140                                 offsetof(SMU74_Discrete_DpmTable,
2141                                         LowSclkInterruptThreshold),
2142                                 (uint8_t *)&low_sclk_interrupt_threshold,
2143                                 sizeof(uint32_t),
2144                                 SMC_RAM_END);
2145         }
2146         PP_ASSERT_WITH_CODE((result == 0),
2147                         "Failed to update SCLK threshold!", return result);
2148
2149         result = polaris10_program_mem_timing_parameters(hwmgr);
2150         PP_ASSERT_WITH_CODE((result == 0),
2151                         "Failed to program memory timing parameters!",
2152                         );
2153
2154         return result;
2155 }
2156
2157 uint32_t polaris10_get_offsetof(uint32_t type, uint32_t member)
2158 {
2159         switch (type) {
2160         case SMU_SoftRegisters:
2161                 switch (member) {
2162                 case HandshakeDisables:
2163                         return offsetof(SMU74_SoftRegisters, HandshakeDisables);
2164                 case VoltageChangeTimeout:
2165                         return offsetof(SMU74_SoftRegisters, VoltageChangeTimeout);
2166                 case AverageGraphicsActivity:
2167                         return offsetof(SMU74_SoftRegisters, AverageGraphicsActivity);
2168                 case PreVBlankGap:
2169                         return offsetof(SMU74_SoftRegisters, PreVBlankGap);
2170                 case VBlankTimeout:
2171                         return offsetof(SMU74_SoftRegisters, VBlankTimeout);
2172                 case UcodeLoadStatus:
2173                         return offsetof(SMU74_SoftRegisters, UcodeLoadStatus);
2174                 }
2175         case SMU_Discrete_DpmTable:
2176                 switch (member) {
2177                 case UvdBootLevel:
2178                         return offsetof(SMU74_Discrete_DpmTable, UvdBootLevel);
2179                 case VceBootLevel:
2180                         return offsetof(SMU74_Discrete_DpmTable, VceBootLevel);
2181                 case SamuBootLevel:
2182                         return offsetof(SMU74_Discrete_DpmTable, SamuBootLevel);
2183                 case LowSclkInterruptThreshold:
2184                         return offsetof(SMU74_Discrete_DpmTable, LowSclkInterruptThreshold);
2185                 }
2186         }
2187         pr_warning("can't get the offset of type %x member %x\n", type, member);
2188         return 0;
2189 }
2190
2191 uint32_t polaris10_get_mac_definition(uint32_t value)
2192 {
2193         switch (value) {
2194         case SMU_MAX_LEVELS_GRAPHICS:
2195                 return SMU74_MAX_LEVELS_GRAPHICS;
2196         case SMU_MAX_LEVELS_MEMORY:
2197                 return SMU74_MAX_LEVELS_MEMORY;
2198         case SMU_MAX_LEVELS_LINK:
2199                 return SMU74_MAX_LEVELS_LINK;
2200         case SMU_MAX_ENTRIES_SMIO:
2201                 return SMU74_MAX_ENTRIES_SMIO;
2202         case SMU_MAX_LEVELS_VDDC:
2203                 return SMU74_MAX_LEVELS_VDDC;
2204         case SMU_MAX_LEVELS_VDDGFX:
2205                 return SMU74_MAX_LEVELS_VDDGFX;
2206         case SMU_MAX_LEVELS_VDDCI:
2207                 return SMU74_MAX_LEVELS_VDDCI;
2208         case SMU_MAX_LEVELS_MVDD:
2209                 return SMU74_MAX_LEVELS_MVDD;
2210         case SMU_UVD_MCLK_HANDSHAKE_DISABLE:
2211                 return SMU7_UVD_MCLK_HANDSHAKE_DISABLE;
2212         }
2213
2214         pr_warning("can't get the mac of %x\n", value);
2215         return 0;
2216 }
2217
2218 /**
2219 * Get the location of various tables inside the FW image.
2220 *
2221 * @param    hwmgr  the address of the powerplay hardware manager.
2222 * @return   always  0
2223 */
2224 int polaris10_process_firmware_header(struct pp_hwmgr *hwmgr)
2225 {
2226         struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend);
2227         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2228         uint32_t tmp;
2229         int result;
2230         bool error = false;
2231
2232         result = smu7_read_smc_sram_dword(hwmgr->smumgr,
2233                         SMU7_FIRMWARE_HEADER_LOCATION +
2234                         offsetof(SMU74_Firmware_Header, DpmTable),
2235                         &tmp, SMC_RAM_END);
2236
2237         if (0 == result)
2238                 smu_data->smu7_data.dpm_table_start = tmp;
2239
2240         error |= (0 != result);
2241
2242         result = smu7_read_smc_sram_dword(hwmgr->smumgr,
2243                         SMU7_FIRMWARE_HEADER_LOCATION +
2244                         offsetof(SMU74_Firmware_Header, SoftRegisters),
2245                         &tmp, SMC_RAM_END);
2246
2247         if (!result) {
2248                 data->soft_regs_start = tmp;
2249                 smu_data->smu7_data.soft_regs_start = tmp;
2250         }
2251
2252         error |= (0 != result);
2253
2254         result = smu7_read_smc_sram_dword(hwmgr->smumgr,
2255                         SMU7_FIRMWARE_HEADER_LOCATION +
2256                         offsetof(SMU74_Firmware_Header, mcRegisterTable),
2257                         &tmp, SMC_RAM_END);
2258
2259         if (!result)
2260                 smu_data->smu7_data.mc_reg_table_start = tmp;
2261
2262         result = smu7_read_smc_sram_dword(hwmgr->smumgr,
2263                         SMU7_FIRMWARE_HEADER_LOCATION +
2264                         offsetof(SMU74_Firmware_Header, FanTable),
2265                         &tmp, SMC_RAM_END);
2266
2267         if (!result)
2268                 smu_data->smu7_data.fan_table_start = tmp;
2269
2270         error |= (0 != result);
2271
2272         result = smu7_read_smc_sram_dword(hwmgr->smumgr,
2273                         SMU7_FIRMWARE_HEADER_LOCATION +
2274                         offsetof(SMU74_Firmware_Header, mcArbDramTimingTable),
2275                         &tmp, SMC_RAM_END);
2276
2277         if (!result)
2278                 smu_data->smu7_data.arb_table_start = tmp;
2279
2280         error |= (0 != result);
2281
2282         result = smu7_read_smc_sram_dword(hwmgr->smumgr,
2283                         SMU7_FIRMWARE_HEADER_LOCATION +
2284                         offsetof(SMU74_Firmware_Header, Version),
2285                         &tmp, SMC_RAM_END);
2286
2287         if (!result)
2288                 hwmgr->microcode_version_info.SMC = tmp;
2289
2290         error |= (0 != result);
2291
2292         return error ? -1 : 0;
2293 }
2294
2295 bool polaris10_is_dpm_running(struct pp_hwmgr *hwmgr)
2296 {
2297         return (1 == PHM_READ_INDIRECT_FIELD(hwmgr->device,
2298                         CGS_IND_REG__SMC, FEATURE_STATUS, VOLTAGE_CONTROLLER_ON))
2299                         ? true : false;
2300 }