Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[cascardo/linux.git] / drivers / gpu / drm / amd / powerplay / smumgr / iceland_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 SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
8  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
9  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
10  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
11  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
12  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
13  * OTHER DEALINGS IN THE SOFTWARE.
14  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15  * and/or sell copies of the Software, and to permit persons to whom the
16  * Software is furnished to do so, subject to the following conditions:
17  *
18  * The above copyright notice and this permission notice shall be included in
19  * all copies or substantial portions of the Software.
20  *
21  *
22  */
23
24 #include "iceland_smc.h"
25 #include "smu7_dyn_defaults.h"
26
27 #include "smu7_hwmgr.h"
28 #include "hardwaremanager.h"
29 #include "ppatomctrl.h"
30 #include "pp_debug.h"
31 #include "cgs_common.h"
32 #include "atombios.h"
33 #include "pppcielanes.h"
34 #include "pp_endian.h"
35 #include "smu7_ppsmc.h"
36
37 #include "smu71_discrete.h"
38
39 #include "smu/smu_7_1_1_d.h"
40 #include "smu/smu_7_1_1_sh_mask.h"
41
42 #include "gmc/gmc_8_1_d.h"
43 #include "gmc/gmc_8_1_sh_mask.h"
44
45 #include "bif/bif_5_0_d.h"
46 #include "bif/bif_5_0_sh_mask.h"
47
48 #include "dce/dce_10_0_d.h"
49 #include "dce/dce_10_0_sh_mask.h"
50 #include "processpptables.h"
51
52 #include "iceland_smumgr.h"
53
54 #define VOLTAGE_SCALE 4
55 #define POWERTUNE_DEFAULT_SET_MAX    1
56 #define VOLTAGE_VID_OFFSET_SCALE1   625
57 #define VOLTAGE_VID_OFFSET_SCALE2   100
58 #define MC_CG_ARB_FREQ_F1           0x0b
59 #define VDDC_VDDCI_DELTA            200
60
61 #define DEVICE_ID_VI_ICELAND_M_6900     0x6900
62 #define DEVICE_ID_VI_ICELAND_M_6901     0x6901
63 #define DEVICE_ID_VI_ICELAND_M_6902     0x6902
64 #define DEVICE_ID_VI_ICELAND_M_6903     0x6903
65
66 static const struct iceland_pt_defaults defaults_iceland = {
67         /*
68          * sviLoadLIneEn, SviLoadLineVddC, TDC_VDDC_ThrottleReleaseLimitPerc,
69          * TDC_MAWt, TdcWaterfallCtl, DTEAmbientTempBase, DisplayCac, BAPM_TEMP_GRADIENT
70          */
71         1, 0xF, 0xFD, 0x19, 5, 45, 0, 0xB0000,
72         { 0x79,  0x253, 0x25D, 0xAE,  0x72,  0x80,  0x83,  0x86,  0x6F,  0xC8,  0xC9,  0xC9,  0x2F,  0x4D,  0x61  },
73         { 0x17C, 0x172, 0x180, 0x1BC, 0x1B3, 0x1BD, 0x206, 0x200, 0x203, 0x25D, 0x25A, 0x255, 0x2C3, 0x2C5, 0x2B4 }
74 };
75
76 /* 35W - XT, XTL */
77 static const struct iceland_pt_defaults defaults_icelandxt = {
78         /*
79          * sviLoadLIneEn, SviLoadLineVddC,
80          * TDC_VDDC_ThrottleReleaseLimitPerc, TDC_MAWt,
81          * TdcWaterfallCtl, DTEAmbientTempBase, DisplayCac,
82          * BAPM_TEMP_GRADIENT
83          */
84         1, 0xF, 0xFD, 0x19, 5, 45, 0, 0x0,
85         { 0xA7,  0x0, 0x0, 0xB5,  0x0, 0x0, 0x9F,  0x0, 0x0, 0xD6,  0x0, 0x0, 0xD7,  0x0, 0x0},
86         { 0x1EA, 0x0, 0x0, 0x224, 0x0, 0x0, 0x25E, 0x0, 0x0, 0x28E, 0x0, 0x0, 0x2AB, 0x0, 0x0}
87 };
88
89 /* 25W - PRO, LE */
90 static const struct iceland_pt_defaults defaults_icelandpro = {
91         /*
92          * sviLoadLIneEn, SviLoadLineVddC,
93          * TDC_VDDC_ThrottleReleaseLimitPerc, TDC_MAWt,
94          * TdcWaterfallCtl, DTEAmbientTempBase, DisplayCac,
95          * BAPM_TEMP_GRADIENT
96          */
97         1, 0xF, 0xFD, 0x19, 5, 45, 0, 0x0,
98         { 0xB7,  0x0, 0x0, 0xC3,  0x0, 0x0, 0xB5,  0x0, 0x0, 0xEA,  0x0, 0x0, 0xE6,  0x0, 0x0},
99         { 0x1EA, 0x0, 0x0, 0x224, 0x0, 0x0, 0x25E, 0x0, 0x0, 0x28E, 0x0, 0x0, 0x2AB, 0x0, 0x0}
100 };
101
102 static void iceland_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr)
103 {
104         struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smumgr->backend);
105         struct cgs_system_info sys_info = {0};
106         uint32_t dev_id;
107
108         sys_info.size = sizeof(struct cgs_system_info);
109         sys_info.info_id = CGS_SYSTEM_INFO_PCIE_DEV;
110         cgs_query_system_info(hwmgr->device, &sys_info);
111         dev_id = (uint32_t)sys_info.value;
112
113         switch (dev_id) {
114         case DEVICE_ID_VI_ICELAND_M_6900:
115         case DEVICE_ID_VI_ICELAND_M_6903:
116                 smu_data->power_tune_defaults = &defaults_icelandxt;
117                 break;
118
119         case DEVICE_ID_VI_ICELAND_M_6901:
120         case DEVICE_ID_VI_ICELAND_M_6902:
121                 smu_data->power_tune_defaults = &defaults_icelandpro;
122                 break;
123         default:
124                 smu_data->power_tune_defaults = &defaults_iceland;
125                 pr_warning("Unknown V.I. Device ID.\n");
126                 break;
127         }
128         return;
129 }
130
131 static int iceland_populate_svi_load_line(struct pp_hwmgr *hwmgr)
132 {
133         struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smumgr->backend);
134         const struct iceland_pt_defaults *defaults = smu_data->power_tune_defaults;
135
136         smu_data->power_tune_table.SviLoadLineEn = defaults->svi_load_line_en;
137         smu_data->power_tune_table.SviLoadLineVddC = defaults->svi_load_line_vddc;
138         smu_data->power_tune_table.SviLoadLineTrimVddC = 3;
139         smu_data->power_tune_table.SviLoadLineOffsetVddC = 0;
140
141         return 0;
142 }
143
144 static int iceland_populate_tdc_limit(struct pp_hwmgr *hwmgr)
145 {
146         uint16_t tdc_limit;
147         struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smumgr->backend);
148         const struct iceland_pt_defaults *defaults = smu_data->power_tune_defaults;
149
150         tdc_limit = (uint16_t)(hwmgr->dyn_state.cac_dtp_table->usTDC * 256);
151         smu_data->power_tune_table.TDC_VDDC_PkgLimit =
152                         CONVERT_FROM_HOST_TO_SMC_US(tdc_limit);
153         smu_data->power_tune_table.TDC_VDDC_ThrottleReleaseLimitPerc =
154                         defaults->tdc_vddc_throttle_release_limit_perc;
155         smu_data->power_tune_table.TDC_MAWt = defaults->tdc_mawt;
156
157         return 0;
158 }
159
160 static int iceland_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset)
161 {
162         struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smumgr->backend);
163         const struct iceland_pt_defaults *defaults = smu_data->power_tune_defaults;
164         uint32_t temp;
165
166         if (smu7_read_smc_sram_dword(hwmgr->smumgr,
167                         fuse_table_offset +
168                         offsetof(SMU71_Discrete_PmFuses, TdcWaterfallCtl),
169                         (uint32_t *)&temp, SMC_RAM_END))
170                 PP_ASSERT_WITH_CODE(false,
171                                 "Attempt to read PmFuses.DW6 (SviLoadLineEn) from SMC Failed!",
172                                 return -EINVAL);
173         else
174                 smu_data->power_tune_table.TdcWaterfallCtl = defaults->tdc_waterfall_ctl;
175
176         return 0;
177 }
178
179 static int iceland_populate_temperature_scaler(struct pp_hwmgr *hwmgr)
180 {
181         return 0;
182 }
183
184 static int iceland_populate_gnb_lpml(struct pp_hwmgr *hwmgr)
185 {
186         int i;
187         struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smumgr->backend);
188
189         /* Currently not used. Set all to zero. */
190         for (i = 0; i < 8; i++)
191                 smu_data->power_tune_table.GnbLPML[i] = 0;
192
193         return 0;
194 }
195
196 static int iceland_min_max_vgnb_lpml_id_from_bapm_vddc(struct pp_hwmgr *hwmgr)
197 {
198         return 0;
199 }
200
201 static int iceland_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr)
202 {
203         struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smumgr->backend);
204         uint16_t HiSidd = smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd;
205         uint16_t LoSidd = smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd;
206         struct phm_cac_tdp_table *cac_table = hwmgr->dyn_state.cac_dtp_table;
207
208         HiSidd = (uint16_t)(cac_table->usHighCACLeakage / 100 * 256);
209         LoSidd = (uint16_t)(cac_table->usLowCACLeakage / 100 * 256);
210
211         smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd =
212                         CONVERT_FROM_HOST_TO_SMC_US(HiSidd);
213         smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd =
214                         CONVERT_FROM_HOST_TO_SMC_US(LoSidd);
215
216         return 0;
217 }
218
219 static int iceland_populate_bapm_vddc_vid_sidd(struct pp_hwmgr *hwmgr)
220 {
221         int i;
222         struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smumgr->backend);
223         uint8_t *hi_vid = smu_data->power_tune_table.BapmVddCVidHiSidd;
224         uint8_t *lo_vid = smu_data->power_tune_table.BapmVddCVidLoSidd;
225
226         PP_ASSERT_WITH_CODE(NULL != hwmgr->dyn_state.cac_leakage_table,
227                             "The CAC Leakage table does not exist!", return -EINVAL);
228         PP_ASSERT_WITH_CODE(hwmgr->dyn_state.cac_leakage_table->count <= 8,
229                             "There should never be more than 8 entries for BapmVddcVid!!!", return -EINVAL);
230         PP_ASSERT_WITH_CODE(hwmgr->dyn_state.cac_leakage_table->count == hwmgr->dyn_state.vddc_dependency_on_sclk->count,
231                             "CACLeakageTable->count and VddcDependencyOnSCLk->count not equal", return -EINVAL);
232
233         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_EVV)) {
234                 for (i = 0; (uint32_t) i < hwmgr->dyn_state.cac_leakage_table->count; i++) {
235                         lo_vid[i] = convert_to_vid(hwmgr->dyn_state.cac_leakage_table->entries[i].Vddc1);
236                         hi_vid[i] = convert_to_vid(hwmgr->dyn_state.cac_leakage_table->entries[i].Vddc2);
237                 }
238         } else {
239                 PP_ASSERT_WITH_CODE(false, "Iceland should always support EVV", return -EINVAL);
240         }
241
242         return 0;
243 }
244
245 static int iceland_populate_vddc_vid(struct pp_hwmgr *hwmgr)
246 {
247         int i;
248         struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smumgr->backend);
249         uint8_t *vid = smu_data->power_tune_table.VddCVid;
250         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
251
252         PP_ASSERT_WITH_CODE(data->vddc_voltage_table.count <= 8,
253                 "There should never be more than 8 entries for VddcVid!!!",
254                 return -EINVAL);
255
256         for (i = 0; i < (int)data->vddc_voltage_table.count; i++) {
257                 vid[i] = convert_to_vid(data->vddc_voltage_table.entries[i].value);
258         }
259
260         return 0;
261 }
262
263
264
265 static int iceland_populate_pm_fuses(struct pp_hwmgr *hwmgr)
266 {
267         struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smumgr->backend);
268         uint32_t pm_fuse_table_offset;
269
270         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
271                         PHM_PlatformCaps_PowerContainment)) {
272                 if (smu7_read_smc_sram_dword(hwmgr->smumgr,
273                                 SMU71_FIRMWARE_HEADER_LOCATION +
274                                 offsetof(SMU71_Firmware_Header, PmFuseTable),
275                                 &pm_fuse_table_offset, SMC_RAM_END))
276                         PP_ASSERT_WITH_CODE(false,
277                                         "Attempt to get pm_fuse_table_offset Failed!",
278                                         return -EINVAL);
279
280                 /* DW0 - DW3 */
281                 if (iceland_populate_bapm_vddc_vid_sidd(hwmgr))
282                         PP_ASSERT_WITH_CODE(false,
283                                         "Attempt to populate bapm vddc vid Failed!",
284                                         return -EINVAL);
285
286                 /* DW4 - DW5 */
287                 if (iceland_populate_vddc_vid(hwmgr))
288                         PP_ASSERT_WITH_CODE(false,
289                                         "Attempt to populate vddc vid Failed!",
290                                         return -EINVAL);
291
292                 /* DW6 */
293                 if (iceland_populate_svi_load_line(hwmgr))
294                         PP_ASSERT_WITH_CODE(false,
295                                         "Attempt to populate SviLoadLine Failed!",
296                                         return -EINVAL);
297                 /* DW7 */
298                 if (iceland_populate_tdc_limit(hwmgr))
299                         PP_ASSERT_WITH_CODE(false,
300                                         "Attempt to populate TDCLimit Failed!", return -EINVAL);
301                 /* DW8 */
302                 if (iceland_populate_dw8(hwmgr, pm_fuse_table_offset))
303                         PP_ASSERT_WITH_CODE(false,
304                                         "Attempt to populate TdcWaterfallCtl, "
305                                         "LPMLTemperature Min and Max Failed!",
306                                         return -EINVAL);
307
308                 /* DW9-DW12 */
309                 if (0 != iceland_populate_temperature_scaler(hwmgr))
310                         PP_ASSERT_WITH_CODE(false,
311                                         "Attempt to populate LPMLTemperatureScaler Failed!",
312                                         return -EINVAL);
313
314                 /* DW13-DW16 */
315                 if (iceland_populate_gnb_lpml(hwmgr))
316                         PP_ASSERT_WITH_CODE(false,
317                                         "Attempt to populate GnbLPML Failed!",
318                                         return -EINVAL);
319
320                 /* DW17 */
321                 if (iceland_min_max_vgnb_lpml_id_from_bapm_vddc(hwmgr))
322                         PP_ASSERT_WITH_CODE(false,
323                                         "Attempt to populate GnbLPML Min and Max Vid Failed!",
324                                         return -EINVAL);
325
326                 /* DW18 */
327                 if (iceland_populate_bapm_vddc_base_leakage_sidd(hwmgr))
328                         PP_ASSERT_WITH_CODE(false,
329                                         "Attempt to populate BapmVddCBaseLeakage Hi and Lo Sidd Failed!",
330                                         return -EINVAL);
331
332                 if (smu7_copy_bytes_to_smc(hwmgr->smumgr, pm_fuse_table_offset,
333                                 (uint8_t *)&smu_data->power_tune_table,
334                                 sizeof(struct SMU71_Discrete_PmFuses), SMC_RAM_END))
335                         PP_ASSERT_WITH_CODE(false,
336                                         "Attempt to download PmFuseTable Failed!",
337                                         return -EINVAL);
338         }
339         return 0;
340 }
341
342 static int iceland_get_dependecy_volt_by_clk(struct pp_hwmgr *hwmgr,
343         struct phm_clock_voltage_dependency_table *allowed_clock_voltage_table,
344         uint32_t clock, uint32_t *vol)
345 {
346         uint32_t i = 0;
347
348         /* clock - voltage dependency table is empty table */
349         if (allowed_clock_voltage_table->count == 0)
350                 return -EINVAL;
351
352         for (i = 0; i < allowed_clock_voltage_table->count; i++) {
353                 /* find first sclk bigger than request */
354                 if (allowed_clock_voltage_table->entries[i].clk >= clock) {
355                         *vol = allowed_clock_voltage_table->entries[i].v;
356                         return 0;
357                 }
358         }
359
360         /* sclk is bigger than max sclk in the dependence table */
361         *vol = allowed_clock_voltage_table->entries[i - 1].v;
362
363         return 0;
364 }
365
366 static int iceland_get_std_voltage_value_sidd(struct pp_hwmgr *hwmgr,
367                 pp_atomctrl_voltage_table_entry *tab, uint16_t *hi,
368                 uint16_t *lo)
369 {
370         uint16_t v_index;
371         bool vol_found = false;
372         *hi = tab->value * VOLTAGE_SCALE;
373         *lo = tab->value * VOLTAGE_SCALE;
374
375         /* SCLK/VDDC Dependency Table has to exist. */
376         PP_ASSERT_WITH_CODE(NULL != hwmgr->dyn_state.vddc_dependency_on_sclk,
377                         "The SCLK/VDDC Dependency Table does not exist.\n",
378                         return -EINVAL);
379
380         if (NULL == hwmgr->dyn_state.cac_leakage_table) {
381                 pr_warning("CAC Leakage Table does not exist, using vddc.\n");
382                 return 0;
383         }
384
385         /*
386          * Since voltage in the sclk/vddc dependency table is not
387          * necessarily in ascending order because of ELB voltage
388          * patching, loop through entire list to find exact voltage.
389          */
390         for (v_index = 0; (uint32_t)v_index < hwmgr->dyn_state.vddc_dependency_on_sclk->count; v_index++) {
391                 if (tab->value == hwmgr->dyn_state.vddc_dependency_on_sclk->entries[v_index].v) {
392                         vol_found = true;
393                         if ((uint32_t)v_index < hwmgr->dyn_state.cac_leakage_table->count) {
394                                 *lo = hwmgr->dyn_state.cac_leakage_table->entries[v_index].Vddc * VOLTAGE_SCALE;
395                                 *hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[v_index].Leakage * VOLTAGE_SCALE);
396                         } else {
397                                 pr_warning("Index from SCLK/VDDC Dependency Table exceeds the CAC Leakage Table index, using maximum index from CAC table.\n");
398                                 *lo = hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Vddc * VOLTAGE_SCALE;
399                                 *hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Leakage * VOLTAGE_SCALE);
400                         }
401                         break;
402                 }
403         }
404
405         /*
406          * If voltage is not found in the first pass, loop again to
407          * find the best match, equal or higher value.
408          */
409         if (!vol_found) {
410                 for (v_index = 0; (uint32_t)v_index < hwmgr->dyn_state.vddc_dependency_on_sclk->count; v_index++) {
411                         if (tab->value <= hwmgr->dyn_state.vddc_dependency_on_sclk->entries[v_index].v) {
412                                 vol_found = true;
413                                 if ((uint32_t)v_index < hwmgr->dyn_state.cac_leakage_table->count) {
414                                         *lo = hwmgr->dyn_state.cac_leakage_table->entries[v_index].Vddc * VOLTAGE_SCALE;
415                                         *hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[v_index].Leakage) * VOLTAGE_SCALE;
416                                 } else {
417                                         pr_warning("Index from SCLK/VDDC Dependency Table exceeds the CAC Leakage Table index in second look up, using maximum index from CAC table.");
418                                         *lo = hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Vddc * VOLTAGE_SCALE;
419                                         *hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Leakage * VOLTAGE_SCALE);
420                                 }
421                                 break;
422                         }
423                 }
424
425                 if (!vol_found)
426                         pr_warning("Unable to get std_vddc from SCLK/VDDC Dependency Table, using vddc.\n");
427         }
428
429         return 0;
430 }
431
432 static int iceland_populate_smc_voltage_table(struct pp_hwmgr *hwmgr,
433                 pp_atomctrl_voltage_table_entry *tab,
434                 SMU71_Discrete_VoltageLevel *smc_voltage_tab)
435 {
436         int result;
437
438         result = iceland_get_std_voltage_value_sidd(hwmgr, tab,
439                         &smc_voltage_tab->StdVoltageHiSidd,
440                         &smc_voltage_tab->StdVoltageLoSidd);
441         if (0 != result) {
442                 smc_voltage_tab->StdVoltageHiSidd = tab->value * VOLTAGE_SCALE;
443                 smc_voltage_tab->StdVoltageLoSidd = tab->value * VOLTAGE_SCALE;
444         }
445
446         smc_voltage_tab->Voltage = PP_HOST_TO_SMC_US(tab->value * VOLTAGE_SCALE);
447         CONVERT_FROM_HOST_TO_SMC_US(smc_voltage_tab->StdVoltageHiSidd);
448         CONVERT_FROM_HOST_TO_SMC_US(smc_voltage_tab->StdVoltageHiSidd);
449
450         return 0;
451 }
452
453 static int iceland_populate_smc_vddc_table(struct pp_hwmgr *hwmgr,
454                         SMU71_Discrete_DpmTable *table)
455 {
456         unsigned int count;
457         int result;
458         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
459
460         table->VddcLevelCount = data->vddc_voltage_table.count;
461         for (count = 0; count < table->VddcLevelCount; count++) {
462                 result = iceland_populate_smc_voltage_table(hwmgr,
463                                 &(data->vddc_voltage_table.entries[count]),
464                                 &(table->VddcLevel[count]));
465                 PP_ASSERT_WITH_CODE(0 == result, "do not populate SMC VDDC voltage table", return -EINVAL);
466
467                 /* GPIO voltage control */
468                 if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->voltage_control)
469                         table->VddcLevel[count].Smio |= data->vddc_voltage_table.entries[count].smio_low;
470                 else if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control)
471                         table->VddcLevel[count].Smio = 0;
472         }
473
474         CONVERT_FROM_HOST_TO_SMC_UL(table->VddcLevelCount);
475
476         return 0;
477 }
478
479 static int iceland_populate_smc_vdd_ci_table(struct pp_hwmgr *hwmgr,
480                         SMU71_Discrete_DpmTable *table)
481 {
482         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
483         uint32_t count;
484         int result;
485
486         table->VddciLevelCount = data->vddci_voltage_table.count;
487
488         for (count = 0; count < table->VddciLevelCount; count++) {
489                 result = iceland_populate_smc_voltage_table(hwmgr,
490                                 &(data->vddci_voltage_table.entries[count]),
491                                 &(table->VddciLevel[count]));
492                 PP_ASSERT_WITH_CODE(result == 0, "do not populate SMC VDDCI voltage table", return -EINVAL);
493                 if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control)
494                         table->VddciLevel[count].Smio |= data->vddci_voltage_table.entries[count].smio_low;
495                 else
496                         table->VddciLevel[count].Smio |= 0;
497         }
498
499         CONVERT_FROM_HOST_TO_SMC_UL(table->VddciLevelCount);
500
501         return 0;
502 }
503
504 static int iceland_populate_smc_mvdd_table(struct pp_hwmgr *hwmgr,
505                         SMU71_Discrete_DpmTable *table)
506 {
507         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
508         uint32_t count;
509         int result;
510
511         table->MvddLevelCount = data->mvdd_voltage_table.count;
512
513         for (count = 0; count < table->VddciLevelCount; count++) {
514                 result = iceland_populate_smc_voltage_table(hwmgr,
515                                 &(data->mvdd_voltage_table.entries[count]),
516                                 &table->MvddLevel[count]);
517                 PP_ASSERT_WITH_CODE(result == 0, "do not populate SMC mvdd voltage table", return -EINVAL);
518                 if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control)
519                         table->MvddLevel[count].Smio |= data->mvdd_voltage_table.entries[count].smio_low;
520                 else
521                         table->MvddLevel[count].Smio |= 0;
522         }
523
524         CONVERT_FROM_HOST_TO_SMC_UL(table->MvddLevelCount);
525
526         return 0;
527 }
528
529
530 static int iceland_populate_smc_voltage_tables(struct pp_hwmgr *hwmgr,
531         SMU71_Discrete_DpmTable *table)
532 {
533         int result;
534
535         result = iceland_populate_smc_vddc_table(hwmgr, table);
536         PP_ASSERT_WITH_CODE(0 == result,
537                         "can not populate VDDC voltage table to SMC", return -EINVAL);
538
539         result = iceland_populate_smc_vdd_ci_table(hwmgr, table);
540         PP_ASSERT_WITH_CODE(0 == result,
541                         "can not populate VDDCI voltage table to SMC", return -EINVAL);
542
543         result = iceland_populate_smc_mvdd_table(hwmgr, table);
544         PP_ASSERT_WITH_CODE(0 == result,
545                         "can not populate MVDD voltage table to SMC", return -EINVAL);
546
547         return 0;
548 }
549
550 static int iceland_populate_ulv_level(struct pp_hwmgr *hwmgr,
551                 struct SMU71_Discrete_Ulv *state)
552 {
553         uint32_t voltage_response_time, ulv_voltage;
554         int result;
555         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
556
557         state->CcPwrDynRm = 0;
558         state->CcPwrDynRm1 = 0;
559
560         result = pp_tables_get_response_times(hwmgr, &voltage_response_time, &ulv_voltage);
561         PP_ASSERT_WITH_CODE((0 == result), "can not get ULV voltage value", return result;);
562
563         if (ulv_voltage == 0) {
564                 data->ulv_supported = false;
565                 return 0;
566         }
567
568         if (data->voltage_control != SMU7_VOLTAGE_CONTROL_BY_SVID2) {
569                 /* use minimum voltage if ulv voltage in pptable is bigger than minimum voltage */
570                 if (ulv_voltage > hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v)
571                         state->VddcOffset = 0;
572                 else
573                         /* used in SMIO Mode. not implemented for now. this is backup only for CI. */
574                         state->VddcOffset = (uint16_t)(hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v - ulv_voltage);
575         } else {
576                 /* use minimum voltage if ulv voltage in pptable is bigger than minimum voltage */
577                 if (ulv_voltage > hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v)
578                         state->VddcOffsetVid = 0;
579                 else  /* used in SVI2 Mode */
580                         state->VddcOffsetVid = (uint8_t)(
581                                         (hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v - ulv_voltage)
582                                                 * VOLTAGE_VID_OFFSET_SCALE2
583                                                 / VOLTAGE_VID_OFFSET_SCALE1);
584         }
585         state->VddcPhase = 1;
586
587         CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm);
588         CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm1);
589         CONVERT_FROM_HOST_TO_SMC_US(state->VddcOffset);
590
591         return 0;
592 }
593
594 static int iceland_populate_ulv_state(struct pp_hwmgr *hwmgr,
595                  SMU71_Discrete_Ulv *ulv_level)
596 {
597         return iceland_populate_ulv_level(hwmgr, ulv_level);
598 }
599
600 static int iceland_populate_smc_link_level(struct pp_hwmgr *hwmgr, SMU71_Discrete_DpmTable *table)
601 {
602         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
603         struct smu7_dpm_table *dpm_table = &data->dpm_table;
604         struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smumgr->backend);
605         uint32_t i;
606
607         /* Index (dpm_table->pcie_speed_table.count) is reserved for PCIE boot level. */
608         for (i = 0; i <= dpm_table->pcie_speed_table.count; i++) {
609                 table->LinkLevel[i].PcieGenSpeed  =
610                         (uint8_t)dpm_table->pcie_speed_table.dpm_levels[i].value;
611                 table->LinkLevel[i].PcieLaneCount =
612                         (uint8_t)encode_pcie_lane_width(dpm_table->pcie_speed_table.dpm_levels[i].param1);
613                 table->LinkLevel[i].EnabledForActivity =
614                         1;
615                 table->LinkLevel[i].SPC =
616                         (uint8_t)(data->pcie_spc_cap & 0xff);
617                 table->LinkLevel[i].DownThreshold =
618                         PP_HOST_TO_SMC_UL(5);
619                 table->LinkLevel[i].UpThreshold =
620                         PP_HOST_TO_SMC_UL(30);
621         }
622
623         smu_data->smc_state_table.LinkLevelCount =
624                 (uint8_t)dpm_table->pcie_speed_table.count;
625         data->dpm_level_enable_mask.pcie_dpm_enable_mask =
626                 phm_get_dpm_level_enable_mask_value(&dpm_table->pcie_speed_table);
627
628         return 0;
629 }
630
631 /**
632  * Calculates the SCLK dividers using the provided engine clock
633  *
634  * @param    hwmgr      the address of the hardware manager
635  * @param    engine_clock the engine clock to use to populate the structure
636  * @param    sclk        the SMC SCLK structure to be populated
637  */
638 static int iceland_calculate_sclk_params(struct pp_hwmgr *hwmgr,
639                 uint32_t engine_clock, SMU71_Discrete_GraphicsLevel *sclk)
640 {
641         const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
642         pp_atomctrl_clock_dividers_vi dividers;
643         uint32_t spll_func_cntl            = data->clock_registers.vCG_SPLL_FUNC_CNTL;
644         uint32_t spll_func_cntl_3          = data->clock_registers.vCG_SPLL_FUNC_CNTL_3;
645         uint32_t spll_func_cntl_4          = data->clock_registers.vCG_SPLL_FUNC_CNTL_4;
646         uint32_t cg_spll_spread_spectrum   = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM;
647         uint32_t cg_spll_spread_spectrum_2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2;
648         uint32_t    reference_clock;
649         uint32_t reference_divider;
650         uint32_t fbdiv;
651         int result;
652
653         /* get the engine clock dividers for this clock value*/
654         result = atomctrl_get_engine_pll_dividers_vi(hwmgr, engine_clock,  &dividers);
655
656         PP_ASSERT_WITH_CODE(result == 0,
657                 "Error retrieving Engine Clock dividers from VBIOS.", return result);
658
659         /* To get FBDIV we need to multiply this by 16384 and divide it by Fref.*/
660         reference_clock = atomctrl_get_reference_clock(hwmgr);
661
662         reference_divider = 1 + dividers.uc_pll_ref_div;
663
664         /* low 14 bits is fraction and high 12 bits is divider*/
665         fbdiv = dividers.ul_fb_div.ul_fb_divider & 0x3FFFFFF;
666
667         /* SPLL_FUNC_CNTL setup*/
668         spll_func_cntl = PHM_SET_FIELD(spll_func_cntl,
669                 CG_SPLL_FUNC_CNTL, SPLL_REF_DIV, dividers.uc_pll_ref_div);
670         spll_func_cntl = PHM_SET_FIELD(spll_func_cntl,
671                 CG_SPLL_FUNC_CNTL, SPLL_PDIV_A,  dividers.uc_pll_post_div);
672
673         /* SPLL_FUNC_CNTL_3 setup*/
674         spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3,
675                 CG_SPLL_FUNC_CNTL_3, SPLL_FB_DIV, fbdiv);
676
677         /* set to use fractional accumulation*/
678         spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3,
679                 CG_SPLL_FUNC_CNTL_3, SPLL_DITHEN, 1);
680
681         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
682                         PHM_PlatformCaps_EngineSpreadSpectrumSupport)) {
683                 pp_atomctrl_internal_ss_info ss_info;
684
685                 uint32_t vcoFreq = engine_clock * dividers.uc_pll_post_div;
686                 if (0 == atomctrl_get_engine_clock_spread_spectrum(hwmgr, vcoFreq, &ss_info)) {
687                         /*
688                         * ss_info.speed_spectrum_percentage -- in unit of 0.01%
689                         * ss_info.speed_spectrum_rate -- in unit of khz
690                         */
691                         /* clks = reference_clock * 10 / (REFDIV + 1) / speed_spectrum_rate / 2 */
692                         uint32_t clkS = reference_clock * 5 / (reference_divider * ss_info.speed_spectrum_rate);
693
694                         /* clkv = 2 * D * fbdiv / NS */
695                         uint32_t clkV = 4 * ss_info.speed_spectrum_percentage * fbdiv / (clkS * 10000);
696
697                         cg_spll_spread_spectrum =
698                                 PHM_SET_FIELD(cg_spll_spread_spectrum, CG_SPLL_SPREAD_SPECTRUM, CLKS, clkS);
699                         cg_spll_spread_spectrum =
700                                 PHM_SET_FIELD(cg_spll_spread_spectrum, CG_SPLL_SPREAD_SPECTRUM, SSEN, 1);
701                         cg_spll_spread_spectrum_2 =
702                                 PHM_SET_FIELD(cg_spll_spread_spectrum_2, CG_SPLL_SPREAD_SPECTRUM_2, CLKV, clkV);
703                 }
704         }
705
706         sclk->SclkFrequency        = engine_clock;
707         sclk->CgSpllFuncCntl3      = spll_func_cntl_3;
708         sclk->CgSpllFuncCntl4      = spll_func_cntl_4;
709         sclk->SpllSpreadSpectrum   = cg_spll_spread_spectrum;
710         sclk->SpllSpreadSpectrum2  = cg_spll_spread_spectrum_2;
711         sclk->SclkDid              = (uint8_t)dividers.pll_post_divider;
712
713         return 0;
714 }
715
716 static int iceland_populate_phase_value_based_on_sclk(struct pp_hwmgr *hwmgr,
717                                 const struct phm_phase_shedding_limits_table *pl,
718                                         uint32_t sclk, uint32_t *p_shed)
719 {
720         unsigned int i;
721
722         /* use the minimum phase shedding */
723         *p_shed = 1;
724
725         for (i = 0; i < pl->count; i++) {
726                 if (sclk < pl->entries[i].Sclk) {
727                         *p_shed = i;
728                         break;
729                 }
730         }
731         return 0;
732 }
733
734 /**
735  * Populates single SMC SCLK structure using the provided engine clock
736  *
737  * @param    hwmgr      the address of the hardware manager
738  * @param    engine_clock the engine clock to use to populate the structure
739  * @param    sclk        the SMC SCLK structure to be populated
740  */
741 static int iceland_populate_single_graphic_level(struct pp_hwmgr *hwmgr,
742                                                 uint32_t engine_clock,
743                                 uint16_t sclk_activity_level_threshold,
744                                 SMU71_Discrete_GraphicsLevel *graphic_level)
745 {
746         int result;
747         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
748
749         result = iceland_calculate_sclk_params(hwmgr, engine_clock, graphic_level);
750
751         /* populate graphics levels*/
752         result = iceland_get_dependecy_volt_by_clk(hwmgr,
753                 hwmgr->dyn_state.vddc_dependency_on_sclk, engine_clock,
754                 &graphic_level->MinVddc);
755         PP_ASSERT_WITH_CODE((0 == result),
756                 "can not find VDDC voltage value for VDDC       \
757                 engine clock dependency table", return result);
758
759         /* SCLK frequency in units of 10KHz*/
760         graphic_level->SclkFrequency = engine_clock;
761         graphic_level->MinVddcPhases = 1;
762
763         if (data->vddc_phase_shed_control)
764                 iceland_populate_phase_value_based_on_sclk(hwmgr,
765                                 hwmgr->dyn_state.vddc_phase_shed_limits_table,
766                                 engine_clock,
767                                 &graphic_level->MinVddcPhases);
768
769         /* Indicates maximum activity level for this performance level. 50% for now*/
770         graphic_level->ActivityLevel = sclk_activity_level_threshold;
771
772         graphic_level->CcPwrDynRm = 0;
773         graphic_level->CcPwrDynRm1 = 0;
774         /* this level can be used if activity is high enough.*/
775         graphic_level->EnabledForActivity = 0;
776         /* this level can be used for throttling.*/
777         graphic_level->EnabledForThrottle = 1;
778         graphic_level->UpHyst = 0;
779         graphic_level->DownHyst = 100;
780         graphic_level->VoltageDownHyst = 0;
781         graphic_level->PowerThrottle = 0;
782
783         data->display_timing.min_clock_in_sr =
784                         hwmgr->display_config.min_core_set_clock_in_sr;
785
786         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
787                         PHM_PlatformCaps_SclkDeepSleep))
788                 graphic_level->DeepSleepDivId =
789                                 smu7_get_sleep_divider_id_from_clock(engine_clock,
790                                                 data->display_timing.min_clock_in_sr);
791
792         /* Default to slow, highest DPM level will be set to PPSMC_DISPLAY_WATERMARK_LOW later.*/
793         graphic_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW;
794
795         if (0 == result) {
796                 graphic_level->MinVddc = PP_HOST_TO_SMC_UL(graphic_level->MinVddc * VOLTAGE_SCALE);
797                 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->MinVddcPhases);
798                 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SclkFrequency);
799                 CONVERT_FROM_HOST_TO_SMC_US(graphic_level->ActivityLevel);
800                 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CgSpllFuncCntl3);
801                 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CgSpllFuncCntl4);
802                 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SpllSpreadSpectrum);
803                 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SpllSpreadSpectrum2);
804                 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CcPwrDynRm);
805                 CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CcPwrDynRm1);
806         }
807
808         return result;
809 }
810
811 /**
812  * Populates all SMC SCLK levels' structure based on the trimmed allowed dpm engine clock states
813  *
814  * @param    hwmgr      the address of the hardware manager
815  */
816 int iceland_populate_all_graphic_levels(struct pp_hwmgr *hwmgr)
817 {
818         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
819         struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smumgr->backend);
820         struct smu7_dpm_table *dpm_table = &data->dpm_table;
821         uint32_t level_array_adress = smu_data->smu7_data.dpm_table_start +
822                                 offsetof(SMU71_Discrete_DpmTable, GraphicsLevel);
823
824         uint32_t level_array_size = sizeof(SMU71_Discrete_GraphicsLevel) *
825                                                 SMU71_MAX_LEVELS_GRAPHICS;
826
827         SMU71_Discrete_GraphicsLevel *levels = smu_data->smc_state_table.GraphicsLevel;
828
829         uint32_t i;
830         uint8_t highest_pcie_level_enabled = 0;
831         uint8_t lowest_pcie_level_enabled = 0, mid_pcie_level_enabled = 0;
832         uint8_t count = 0;
833         int result = 0;
834
835         memset(levels, 0x00, level_array_size);
836
837         for (i = 0; i < dpm_table->sclk_table.count; i++) {
838                 result = iceland_populate_single_graphic_level(hwmgr,
839                                         dpm_table->sclk_table.dpm_levels[i].value,
840                                         (uint16_t)smu_data->activity_target[i],
841                                         &(smu_data->smc_state_table.GraphicsLevel[i]));
842                 if (result != 0)
843                         return result;
844
845                 /* Making sure only DPM level 0-1 have Deep Sleep Div ID populated. */
846                 if (i > 1)
847                         smu_data->smc_state_table.GraphicsLevel[i].DeepSleepDivId = 0;
848         }
849
850         /* Only enable level 0 for now. */
851         smu_data->smc_state_table.GraphicsLevel[0].EnabledForActivity = 1;
852
853         /* set highest level watermark to high */
854         if (dpm_table->sclk_table.count > 1)
855                 smu_data->smc_state_table.GraphicsLevel[dpm_table->sclk_table.count-1].DisplayWatermark =
856                         PPSMC_DISPLAY_WATERMARK_HIGH;
857
858         smu_data->smc_state_table.GraphicsDpmLevelCount =
859                 (uint8_t)dpm_table->sclk_table.count;
860         data->dpm_level_enable_mask.sclk_dpm_enable_mask =
861                 phm_get_dpm_level_enable_mask_value(&dpm_table->sclk_table);
862
863         while ((data->dpm_level_enable_mask.pcie_dpm_enable_mask &
864                                 (1 << (highest_pcie_level_enabled + 1))) != 0) {
865                 highest_pcie_level_enabled++;
866         }
867
868         while ((data->dpm_level_enable_mask.pcie_dpm_enable_mask &
869                 (1 << lowest_pcie_level_enabled)) == 0) {
870                 lowest_pcie_level_enabled++;
871         }
872
873         while ((count < highest_pcie_level_enabled) &&
874                         ((data->dpm_level_enable_mask.pcie_dpm_enable_mask &
875                                 (1 << (lowest_pcie_level_enabled + 1 + count))) == 0)) {
876                 count++;
877         }
878
879         mid_pcie_level_enabled = (lowest_pcie_level_enabled+1+count) < highest_pcie_level_enabled ?
880                 (lowest_pcie_level_enabled+1+count) : highest_pcie_level_enabled;
881
882
883         /* set pcieDpmLevel to highest_pcie_level_enabled*/
884         for (i = 2; i < dpm_table->sclk_table.count; i++) {
885                 smu_data->smc_state_table.GraphicsLevel[i].pcieDpmLevel = highest_pcie_level_enabled;
886         }
887
888         /* set pcieDpmLevel to lowest_pcie_level_enabled*/
889         smu_data->smc_state_table.GraphicsLevel[0].pcieDpmLevel = lowest_pcie_level_enabled;
890
891         /* set pcieDpmLevel to mid_pcie_level_enabled*/
892         smu_data->smc_state_table.GraphicsLevel[1].pcieDpmLevel = mid_pcie_level_enabled;
893
894         /* level count will send to smc once at init smc table and never change*/
895         result = smu7_copy_bytes_to_smc(hwmgr->smumgr, level_array_adress,
896                                 (uint8_t *)levels, (uint32_t)level_array_size,
897                                                                 SMC_RAM_END);
898
899         return result;
900 }
901
902 /**
903  * Populates the SMC MCLK structure using the provided memory clock
904  *
905  * @param    hwmgr      the address of the hardware manager
906  * @param    memory_clock the memory clock to use to populate the structure
907  * @param    sclk        the SMC SCLK structure to be populated
908  */
909 static int iceland_calculate_mclk_params(
910                 struct pp_hwmgr *hwmgr,
911                 uint32_t memory_clock,
912                 SMU71_Discrete_MemoryLevel *mclk,
913                 bool strobe_mode,
914                 bool dllStateOn
915                 )
916 {
917         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
918
919         uint32_t  dll_cntl = data->clock_registers.vDLL_CNTL;
920         uint32_t  mclk_pwrmgt_cntl = data->clock_registers.vMCLK_PWRMGT_CNTL;
921         uint32_t  mpll_ad_func_cntl = data->clock_registers.vMPLL_AD_FUNC_CNTL;
922         uint32_t  mpll_dq_func_cntl = data->clock_registers.vMPLL_DQ_FUNC_CNTL;
923         uint32_t  mpll_func_cntl = data->clock_registers.vMPLL_FUNC_CNTL;
924         uint32_t  mpll_func_cntl_1 = data->clock_registers.vMPLL_FUNC_CNTL_1;
925         uint32_t  mpll_func_cntl_2 = data->clock_registers.vMPLL_FUNC_CNTL_2;
926         uint32_t  mpll_ss1 = data->clock_registers.vMPLL_SS1;
927         uint32_t  mpll_ss2 = data->clock_registers.vMPLL_SS2;
928
929         pp_atomctrl_memory_clock_param mpll_param;
930         int result;
931
932         result = atomctrl_get_memory_pll_dividers_si(hwmgr,
933                                 memory_clock, &mpll_param, strobe_mode);
934         PP_ASSERT_WITH_CODE(0 == result,
935                 "Error retrieving Memory Clock Parameters from VBIOS.", return result);
936
937         /* MPLL_FUNC_CNTL setup*/
938         mpll_func_cntl = PHM_SET_FIELD(mpll_func_cntl, MPLL_FUNC_CNTL, BWCTRL, mpll_param.bw_ctrl);
939
940         /* MPLL_FUNC_CNTL_1 setup*/
941         mpll_func_cntl_1  = PHM_SET_FIELD(mpll_func_cntl_1,
942                                                         MPLL_FUNC_CNTL_1, CLKF, mpll_param.mpll_fb_divider.cl_kf);
943         mpll_func_cntl_1  = PHM_SET_FIELD(mpll_func_cntl_1,
944                                                         MPLL_FUNC_CNTL_1, CLKFRAC, mpll_param.mpll_fb_divider.clk_frac);
945         mpll_func_cntl_1  = PHM_SET_FIELD(mpll_func_cntl_1,
946                                                         MPLL_FUNC_CNTL_1, VCO_MODE, mpll_param.vco_mode);
947
948         /* MPLL_AD_FUNC_CNTL setup*/
949         mpll_ad_func_cntl = PHM_SET_FIELD(mpll_ad_func_cntl,
950                                                         MPLL_AD_FUNC_CNTL, YCLK_POST_DIV, mpll_param.mpll_post_divider);
951
952         if (data->is_memory_gddr5) {
953                 /* MPLL_DQ_FUNC_CNTL setup*/
954                 mpll_dq_func_cntl  = PHM_SET_FIELD(mpll_dq_func_cntl,
955                                                                 MPLL_DQ_FUNC_CNTL, YCLK_SEL, mpll_param.yclk_sel);
956                 mpll_dq_func_cntl  = PHM_SET_FIELD(mpll_dq_func_cntl,
957                                                                 MPLL_DQ_FUNC_CNTL, YCLK_POST_DIV, mpll_param.mpll_post_divider);
958         }
959
960         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
961                         PHM_PlatformCaps_MemorySpreadSpectrumSupport)) {
962                 /*
963                  ************************************
964                  Fref = Reference Frequency
965                  NF = Feedback divider ratio
966                  NR = Reference divider ratio
967                  Fnom = Nominal VCO output frequency = Fref * NF / NR
968                  Fs = Spreading Rate
969                  D = Percentage down-spread / 2
970                  Fint = Reference input frequency to PFD = Fref / NR
971                  NS = Spreading rate divider ratio = int(Fint / (2 * Fs))
972                  CLKS = NS - 1 = ISS_STEP_NUM[11:0]
973                  NV = D * Fs / Fnom * 4 * ((Fnom/Fref * NR) ^ 2)
974                  CLKV = 65536 * NV = ISS_STEP_SIZE[25:0]
975                  *************************************
976                  */
977                 pp_atomctrl_internal_ss_info ss_info;
978                 uint32_t freq_nom;
979                 uint32_t tmp;
980                 uint32_t reference_clock = atomctrl_get_mpll_reference_clock(hwmgr);
981
982                 /* for GDDR5 for all modes and DDR3 */
983                 if (1 == mpll_param.qdr)
984                         freq_nom = memory_clock * 4 * (1 << mpll_param.mpll_post_divider);
985                 else
986                         freq_nom = memory_clock * 2 * (1 << mpll_param.mpll_post_divider);
987
988                 /* tmp = (freq_nom / reference_clock * reference_divider) ^ 2  Note: S.I. reference_divider = 1*/
989                 tmp = (freq_nom / reference_clock);
990                 tmp = tmp * tmp;
991
992                 if (0 == atomctrl_get_memory_clock_spread_spectrum(hwmgr, freq_nom, &ss_info)) {
993                         /* ss_info.speed_spectrum_percentage -- in unit of 0.01% */
994                         /* ss.Info.speed_spectrum_rate -- in unit of khz */
995                         /* CLKS = reference_clock / (2 * speed_spectrum_rate * reference_divider) * 10 */
996                         /*     = reference_clock * 5 / speed_spectrum_rate */
997                         uint32_t clks = reference_clock * 5 / ss_info.speed_spectrum_rate;
998
999                         /* CLKV = 65536 * speed_spectrum_percentage / 2 * spreadSpecrumRate / freq_nom * 4 / 100000 * ((freq_nom / reference_clock) ^ 2) */
1000                         /*     = 131 * speed_spectrum_percentage * speed_spectrum_rate / 100 * ((freq_nom / reference_clock) ^ 2) / freq_nom */
1001                         uint32_t clkv =
1002                                 (uint32_t)((((131 * ss_info.speed_spectrum_percentage *
1003                                                         ss_info.speed_spectrum_rate) / 100) * tmp) / freq_nom);
1004
1005                         mpll_ss1 = PHM_SET_FIELD(mpll_ss1, MPLL_SS1, CLKV, clkv);
1006                         mpll_ss2 = PHM_SET_FIELD(mpll_ss2, MPLL_SS2, CLKS, clks);
1007                 }
1008         }
1009
1010         /* MCLK_PWRMGT_CNTL setup */
1011         mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl,
1012                 MCLK_PWRMGT_CNTL, DLL_SPEED, mpll_param.dll_speed);
1013         mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl,
1014                 MCLK_PWRMGT_CNTL, MRDCK0_PDNB, dllStateOn);
1015         mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl,
1016                 MCLK_PWRMGT_CNTL, MRDCK1_PDNB, dllStateOn);
1017
1018
1019         /* Save the result data to outpupt memory level structure */
1020         mclk->MclkFrequency   = memory_clock;
1021         mclk->MpllFuncCntl    = mpll_func_cntl;
1022         mclk->MpllFuncCntl_1  = mpll_func_cntl_1;
1023         mclk->MpllFuncCntl_2  = mpll_func_cntl_2;
1024         mclk->MpllAdFuncCntl  = mpll_ad_func_cntl;
1025         mclk->MpllDqFuncCntl  = mpll_dq_func_cntl;
1026         mclk->MclkPwrmgtCntl  = mclk_pwrmgt_cntl;
1027         mclk->DllCntl         = dll_cntl;
1028         mclk->MpllSs1         = mpll_ss1;
1029         mclk->MpllSs2         = mpll_ss2;
1030
1031         return 0;
1032 }
1033
1034 static uint8_t iceland_get_mclk_frequency_ratio(uint32_t memory_clock,
1035                 bool strobe_mode)
1036 {
1037         uint8_t mc_para_index;
1038
1039         if (strobe_mode) {
1040                 if (memory_clock < 12500) {
1041                         mc_para_index = 0x00;
1042                 } else if (memory_clock > 47500) {
1043                         mc_para_index = 0x0f;
1044                 } else {
1045                         mc_para_index = (uint8_t)((memory_clock - 10000) / 2500);
1046                 }
1047         } else {
1048                 if (memory_clock < 65000) {
1049                         mc_para_index = 0x00;
1050                 } else if (memory_clock > 135000) {
1051                         mc_para_index = 0x0f;
1052                 } else {
1053                         mc_para_index = (uint8_t)((memory_clock - 60000) / 5000);
1054                 }
1055         }
1056
1057         return mc_para_index;
1058 }
1059
1060 static uint8_t iceland_get_ddr3_mclk_frequency_ratio(uint32_t memory_clock)
1061 {
1062         uint8_t mc_para_index;
1063
1064         if (memory_clock < 10000) {
1065                 mc_para_index = 0;
1066         } else if (memory_clock >= 80000) {
1067                 mc_para_index = 0x0f;
1068         } else {
1069                 mc_para_index = (uint8_t)((memory_clock - 10000) / 5000 + 1);
1070         }
1071
1072         return mc_para_index;
1073 }
1074
1075 static int iceland_populate_phase_value_based_on_mclk(struct pp_hwmgr *hwmgr, const struct phm_phase_shedding_limits_table *pl,
1076                                         uint32_t memory_clock, uint32_t *p_shed)
1077 {
1078         unsigned int i;
1079
1080         *p_shed = 1;
1081
1082         for (i = 0; i < pl->count; i++) {
1083                 if (memory_clock < pl->entries[i].Mclk) {
1084                         *p_shed = i;
1085                         break;
1086                 }
1087         }
1088
1089         return 0;
1090 }
1091
1092 static int iceland_populate_single_memory_level(
1093                 struct pp_hwmgr *hwmgr,
1094                 uint32_t memory_clock,
1095                 SMU71_Discrete_MemoryLevel *memory_level
1096                 )
1097 {
1098         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1099         int result = 0;
1100         bool dll_state_on;
1101         struct cgs_display_info info = {0};
1102         uint32_t mclk_edc_wr_enable_threshold = 40000;
1103         uint32_t mclk_edc_enable_threshold = 40000;
1104         uint32_t mclk_strobe_mode_threshold = 40000;
1105
1106         if (hwmgr->dyn_state.vddc_dependency_on_mclk != NULL) {
1107                 result = iceland_get_dependecy_volt_by_clk(hwmgr,
1108                         hwmgr->dyn_state.vddc_dependency_on_mclk, memory_clock, &memory_level->MinVddc);
1109                 PP_ASSERT_WITH_CODE((0 == result),
1110                         "can not find MinVddc voltage value from memory VDDC voltage dependency table", return result);
1111         }
1112
1113         if (data->vddci_control == SMU7_VOLTAGE_CONTROL_NONE) {
1114                 memory_level->MinVddci = memory_level->MinVddc;
1115         } else if (NULL != hwmgr->dyn_state.vddci_dependency_on_mclk) {
1116                 result = iceland_get_dependecy_volt_by_clk(hwmgr,
1117                                 hwmgr->dyn_state.vddci_dependency_on_mclk,
1118                                 memory_clock,
1119                                 &memory_level->MinVddci);
1120                 PP_ASSERT_WITH_CODE((0 == result),
1121                         "can not find MinVddci voltage value from memory VDDCI voltage dependency table", return result);
1122         }
1123
1124         memory_level->MinVddcPhases = 1;
1125
1126         if (data->vddc_phase_shed_control) {
1127                 iceland_populate_phase_value_based_on_mclk(hwmgr, hwmgr->dyn_state.vddc_phase_shed_limits_table,
1128                                 memory_clock, &memory_level->MinVddcPhases);
1129         }
1130
1131         memory_level->EnabledForThrottle = 1;
1132         memory_level->EnabledForActivity = 0;
1133         memory_level->UpHyst = 0;
1134         memory_level->DownHyst = 100;
1135         memory_level->VoltageDownHyst = 0;
1136
1137         /* Indicates maximum activity level for this performance level.*/
1138         memory_level->ActivityLevel = (uint16_t)data->mclk_activity_target;
1139         memory_level->StutterEnable = 0;
1140         memory_level->StrobeEnable = 0;
1141         memory_level->EdcReadEnable = 0;
1142         memory_level->EdcWriteEnable = 0;
1143         memory_level->RttEnable = 0;
1144
1145         /* default set to low watermark. Highest level will be set to high later.*/
1146         memory_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW;
1147
1148         cgs_get_active_displays_info(hwmgr->device, &info);
1149         data->display_timing.num_existing_displays = info.display_count;
1150
1151         /* stutter mode not support on iceland */
1152
1153         /* decide strobe mode*/
1154         memory_level->StrobeEnable = (mclk_strobe_mode_threshold != 0) &&
1155                 (memory_clock <= mclk_strobe_mode_threshold);
1156
1157         /* decide EDC mode and memory clock ratio*/
1158         if (data->is_memory_gddr5) {
1159                 memory_level->StrobeRatio = iceland_get_mclk_frequency_ratio(memory_clock,
1160                                         memory_level->StrobeEnable);
1161
1162                 if ((mclk_edc_enable_threshold != 0) &&
1163                                 (memory_clock > mclk_edc_enable_threshold)) {
1164                         memory_level->EdcReadEnable = 1;
1165                 }
1166
1167                 if ((mclk_edc_wr_enable_threshold != 0) &&
1168                                 (memory_clock > mclk_edc_wr_enable_threshold)) {
1169                         memory_level->EdcWriteEnable = 1;
1170                 }
1171
1172                 if (memory_level->StrobeEnable) {
1173                         if (iceland_get_mclk_frequency_ratio(memory_clock, 1) >=
1174                                         ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC7) >> 16) & 0xf))
1175                                 dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC5) >> 1) & 0x1) ? 1 : 0;
1176                         else
1177                                 dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC6) >> 1) & 0x1) ? 1 : 0;
1178                 } else
1179                         dll_state_on = data->dll_default_on;
1180         } else {
1181                 memory_level->StrobeRatio =
1182                         iceland_get_ddr3_mclk_frequency_ratio(memory_clock);
1183                 dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC5) >> 1) & 0x1) ? 1 : 0;
1184         }
1185
1186         result = iceland_calculate_mclk_params(hwmgr,
1187                 memory_clock, memory_level, memory_level->StrobeEnable, dll_state_on);
1188
1189         if (0 == result) {
1190                 memory_level->MinVddc = PP_HOST_TO_SMC_UL(memory_level->MinVddc * VOLTAGE_SCALE);
1191                 CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MinVddcPhases);
1192                 memory_level->MinVddci = PP_HOST_TO_SMC_UL(memory_level->MinVddci * VOLTAGE_SCALE);
1193                 memory_level->MinMvdd = PP_HOST_TO_SMC_UL(memory_level->MinMvdd * VOLTAGE_SCALE);
1194                 /* MCLK frequency in units of 10KHz*/
1195                 CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MclkFrequency);
1196                 /* Indicates maximum activity level for this performance level.*/
1197                 CONVERT_FROM_HOST_TO_SMC_US(memory_level->ActivityLevel);
1198                 CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl);
1199                 CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl_1);
1200                 CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl_2);
1201                 CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllAdFuncCntl);
1202                 CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllDqFuncCntl);
1203                 CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MclkPwrmgtCntl);
1204                 CONVERT_FROM_HOST_TO_SMC_UL(memory_level->DllCntl);
1205                 CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllSs1);
1206                 CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllSs2);
1207         }
1208
1209         return result;
1210 }
1211
1212 /**
1213  * Populates all SMC MCLK levels' structure based on the trimmed allowed dpm memory clock states
1214  *
1215  * @param    hwmgr      the address of the hardware manager
1216  */
1217
1218 int iceland_populate_all_memory_levels(struct pp_hwmgr *hwmgr)
1219 {
1220         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1221         struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smumgr->backend);
1222         struct smu7_dpm_table *dpm_table = &data->dpm_table;
1223         int result;
1224
1225         /* populate MCLK dpm table to SMU7 */
1226         uint32_t level_array_adress = smu_data->smu7_data.dpm_table_start + offsetof(SMU71_Discrete_DpmTable, MemoryLevel);
1227         uint32_t level_array_size = sizeof(SMU71_Discrete_MemoryLevel) * SMU71_MAX_LEVELS_MEMORY;
1228         SMU71_Discrete_MemoryLevel *levels = smu_data->smc_state_table.MemoryLevel;
1229         uint32_t i;
1230
1231         memset(levels, 0x00, level_array_size);
1232
1233         for (i = 0; i < dpm_table->mclk_table.count; i++) {
1234                 PP_ASSERT_WITH_CODE((0 != dpm_table->mclk_table.dpm_levels[i].value),
1235                         "can not populate memory level as memory clock is zero", return -EINVAL);
1236                 result = iceland_populate_single_memory_level(hwmgr, dpm_table->mclk_table.dpm_levels[i].value,
1237                         &(smu_data->smc_state_table.MemoryLevel[i]));
1238                 if (0 != result) {
1239                         return result;
1240                 }
1241         }
1242
1243         /* Only enable level 0 for now.*/
1244         smu_data->smc_state_table.MemoryLevel[0].EnabledForActivity = 1;
1245
1246         /*
1247         * in order to prevent MC activity from stutter mode to push DPM up.
1248         * the UVD change complements this by putting the MCLK in a higher state
1249         * by default such that we are not effected by up threshold or and MCLK DPM latency.
1250         */
1251         smu_data->smc_state_table.MemoryLevel[0].ActivityLevel = 0x1F;
1252         CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.MemoryLevel[0].ActivityLevel);
1253
1254         smu_data->smc_state_table.MemoryDpmLevelCount = (uint8_t)dpm_table->mclk_table.count;
1255         data->dpm_level_enable_mask.mclk_dpm_enable_mask = phm_get_dpm_level_enable_mask_value(&dpm_table->mclk_table);
1256         /* set highest level watermark to high*/
1257         smu_data->smc_state_table.MemoryLevel[dpm_table->mclk_table.count-1].DisplayWatermark = PPSMC_DISPLAY_WATERMARK_HIGH;
1258
1259         /* level count will send to smc once at init smc table and never change*/
1260         result = smu7_copy_bytes_to_smc(hwmgr->smumgr,
1261                 level_array_adress, (uint8_t *)levels, (uint32_t)level_array_size,
1262                 SMC_RAM_END);
1263
1264         return result;
1265 }
1266
1267 static int iceland_populate_mvdd_value(struct pp_hwmgr *hwmgr, uint32_t mclk,
1268                                         SMU71_Discrete_VoltageLevel *voltage)
1269 {
1270         const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1271
1272         uint32_t i = 0;
1273
1274         if (SMU7_VOLTAGE_CONTROL_NONE != data->mvdd_control) {
1275                 /* find mvdd value which clock is more than request */
1276                 for (i = 0; i < hwmgr->dyn_state.mvdd_dependency_on_mclk->count; i++) {
1277                         if (mclk <= hwmgr->dyn_state.mvdd_dependency_on_mclk->entries[i].clk) {
1278                                 /* Always round to higher voltage. */
1279                                 voltage->Voltage = data->mvdd_voltage_table.entries[i].value;
1280                                 break;
1281                         }
1282                 }
1283
1284                 PP_ASSERT_WITH_CODE(i < hwmgr->dyn_state.mvdd_dependency_on_mclk->count,
1285                         "MVDD Voltage is outside the supported range.", return -EINVAL);
1286
1287         } else {
1288                 return -EINVAL;
1289         }
1290
1291         return 0;
1292 }
1293
1294 static int iceland_populate_smc_acpi_level(struct pp_hwmgr *hwmgr,
1295         SMU71_Discrete_DpmTable *table)
1296 {
1297         int result = 0;
1298         const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1299         struct pp_atomctrl_clock_dividers_vi dividers;
1300         uint32_t vddc_phase_shed_control = 0;
1301
1302         SMU71_Discrete_VoltageLevel voltage_level;
1303         uint32_t spll_func_cntl    = data->clock_registers.vCG_SPLL_FUNC_CNTL;
1304         uint32_t spll_func_cntl_2  = data->clock_registers.vCG_SPLL_FUNC_CNTL_2;
1305         uint32_t dll_cntl          = data->clock_registers.vDLL_CNTL;
1306         uint32_t mclk_pwrmgt_cntl  = data->clock_registers.vMCLK_PWRMGT_CNTL;
1307
1308
1309         /* The ACPI state should not do DPM on DC (or ever).*/
1310         table->ACPILevel.Flags &= ~PPSMC_SWSTATE_FLAG_DC;
1311
1312         if (data->acpi_vddc)
1313                 table->ACPILevel.MinVddc = PP_HOST_TO_SMC_UL(data->acpi_vddc * VOLTAGE_SCALE);
1314         else
1315                 table->ACPILevel.MinVddc = PP_HOST_TO_SMC_UL(data->min_vddc_in_pptable * VOLTAGE_SCALE);
1316
1317         table->ACPILevel.MinVddcPhases = vddc_phase_shed_control ? 0 : 1;
1318         /* assign zero for now*/
1319         table->ACPILevel.SclkFrequency = atomctrl_get_reference_clock(hwmgr);
1320
1321         /* get the engine clock dividers for this clock value*/
1322         result = atomctrl_get_engine_pll_dividers_vi(hwmgr,
1323                 table->ACPILevel.SclkFrequency,  &dividers);
1324
1325         PP_ASSERT_WITH_CODE(result == 0,
1326                 "Error retrieving Engine Clock dividers from VBIOS.", return result);
1327
1328         /* divider ID for required SCLK*/
1329         table->ACPILevel.SclkDid = (uint8_t)dividers.pll_post_divider;
1330         table->ACPILevel.DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW;
1331         table->ACPILevel.DeepSleepDivId = 0;
1332
1333         spll_func_cntl      = PHM_SET_FIELD(spll_func_cntl,
1334                                                         CG_SPLL_FUNC_CNTL,   SPLL_PWRON,     0);
1335         spll_func_cntl      = PHM_SET_FIELD(spll_func_cntl,
1336                                                         CG_SPLL_FUNC_CNTL,   SPLL_RESET,     1);
1337         spll_func_cntl_2    = PHM_SET_FIELD(spll_func_cntl_2,
1338                                                         CG_SPLL_FUNC_CNTL_2, SCLK_MUX_SEL,   4);
1339
1340         table->ACPILevel.CgSpllFuncCntl = spll_func_cntl;
1341         table->ACPILevel.CgSpllFuncCntl2 = spll_func_cntl_2;
1342         table->ACPILevel.CgSpllFuncCntl3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3;
1343         table->ACPILevel.CgSpllFuncCntl4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4;
1344         table->ACPILevel.SpllSpreadSpectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM;
1345         table->ACPILevel.SpllSpreadSpectrum2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2;
1346         table->ACPILevel.CcPwrDynRm = 0;
1347         table->ACPILevel.CcPwrDynRm1 = 0;
1348
1349
1350         /* For various features to be enabled/disabled while this level is active.*/
1351         CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.Flags);
1352         /* SCLK frequency in units of 10KHz*/
1353         CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SclkFrequency);
1354         CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl);
1355         CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl2);
1356         CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl3);
1357         CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl4);
1358         CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum);
1359         CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum2);
1360         CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm);
1361         CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm1);
1362
1363         /* table->MemoryACPILevel.MinVddcPhases = table->ACPILevel.MinVddcPhases;*/
1364         table->MemoryACPILevel.MinVddc = table->ACPILevel.MinVddc;
1365         table->MemoryACPILevel.MinVddcPhases = table->ACPILevel.MinVddcPhases;
1366
1367         if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control)
1368                 table->MemoryACPILevel.MinVddci = table->MemoryACPILevel.MinVddc;
1369         else {
1370                 if (data->acpi_vddci != 0)
1371                         table->MemoryACPILevel.MinVddci = PP_HOST_TO_SMC_UL(data->acpi_vddci * VOLTAGE_SCALE);
1372                 else
1373                         table->MemoryACPILevel.MinVddci = PP_HOST_TO_SMC_UL(data->min_vddci_in_pptable * VOLTAGE_SCALE);
1374         }
1375
1376         if (0 == iceland_populate_mvdd_value(hwmgr, 0, &voltage_level))
1377                 table->MemoryACPILevel.MinMvdd =
1378                         PP_HOST_TO_SMC_UL(voltage_level.Voltage * VOLTAGE_SCALE);
1379         else
1380                 table->MemoryACPILevel.MinMvdd = 0;
1381
1382         /* Force reset on DLL*/
1383         mclk_pwrmgt_cntl    = PHM_SET_FIELD(mclk_pwrmgt_cntl,
1384                 MCLK_PWRMGT_CNTL, MRDCK0_RESET, 0x1);
1385         mclk_pwrmgt_cntl    = PHM_SET_FIELD(mclk_pwrmgt_cntl,
1386                 MCLK_PWRMGT_CNTL, MRDCK1_RESET, 0x1);
1387
1388         /* Disable DLL in ACPIState*/
1389         mclk_pwrmgt_cntl    = PHM_SET_FIELD(mclk_pwrmgt_cntl,
1390                 MCLK_PWRMGT_CNTL, MRDCK0_PDNB, 0);
1391         mclk_pwrmgt_cntl    = PHM_SET_FIELD(mclk_pwrmgt_cntl,
1392                 MCLK_PWRMGT_CNTL, MRDCK1_PDNB, 0);
1393
1394         /* Enable DLL bypass signal*/
1395         dll_cntl            = PHM_SET_FIELD(dll_cntl,
1396                 DLL_CNTL, MRDCK0_BYPASS, 0);
1397         dll_cntl            = PHM_SET_FIELD(dll_cntl,
1398                 DLL_CNTL, MRDCK1_BYPASS, 0);
1399
1400         table->MemoryACPILevel.DllCntl            =
1401                 PP_HOST_TO_SMC_UL(dll_cntl);
1402         table->MemoryACPILevel.MclkPwrmgtCntl     =
1403                 PP_HOST_TO_SMC_UL(mclk_pwrmgt_cntl);
1404         table->MemoryACPILevel.MpllAdFuncCntl     =
1405                 PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_AD_FUNC_CNTL);
1406         table->MemoryACPILevel.MpllDqFuncCntl     =
1407                 PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_DQ_FUNC_CNTL);
1408         table->MemoryACPILevel.MpllFuncCntl       =
1409                 PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL);
1410         table->MemoryACPILevel.MpllFuncCntl_1     =
1411                 PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL_1);
1412         table->MemoryACPILevel.MpllFuncCntl_2     =
1413                 PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL_2);
1414         table->MemoryACPILevel.MpllSs1            =
1415                 PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_SS1);
1416         table->MemoryACPILevel.MpllSs2            =
1417                 PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_SS2);
1418
1419         table->MemoryACPILevel.EnabledForThrottle = 0;
1420         table->MemoryACPILevel.EnabledForActivity = 0;
1421         table->MemoryACPILevel.UpHyst = 0;
1422         table->MemoryACPILevel.DownHyst = 100;
1423         table->MemoryACPILevel.VoltageDownHyst = 0;
1424         /* Indicates maximum activity level for this performance level.*/
1425         table->MemoryACPILevel.ActivityLevel = PP_HOST_TO_SMC_US((uint16_t)data->mclk_activity_target);
1426
1427         table->MemoryACPILevel.StutterEnable = 0;
1428         table->MemoryACPILevel.StrobeEnable = 0;
1429         table->MemoryACPILevel.EdcReadEnable = 0;
1430         table->MemoryACPILevel.EdcWriteEnable = 0;
1431         table->MemoryACPILevel.RttEnable = 0;
1432
1433         return result;
1434 }
1435
1436 static int iceland_populate_smc_uvd_level(struct pp_hwmgr *hwmgr,
1437                                         SMU71_Discrete_DpmTable *table)
1438 {
1439         return 0;
1440 }
1441
1442 static int iceland_populate_smc_vce_level(struct pp_hwmgr *hwmgr,
1443                 SMU71_Discrete_DpmTable *table)
1444 {
1445         return 0;
1446 }
1447
1448 static int iceland_populate_smc_acp_level(struct pp_hwmgr *hwmgr,
1449                 SMU71_Discrete_DpmTable *table)
1450 {
1451         return 0;
1452 }
1453
1454 static int iceland_populate_smc_samu_level(struct pp_hwmgr *hwmgr,
1455         SMU71_Discrete_DpmTable *table)
1456 {
1457         return 0;
1458 }
1459
1460 static int iceland_populate_memory_timing_parameters(
1461                 struct pp_hwmgr *hwmgr,
1462                 uint32_t engine_clock,
1463                 uint32_t memory_clock,
1464                 struct SMU71_Discrete_MCArbDramTimingTableEntry *arb_regs
1465                 )
1466 {
1467         uint32_t dramTiming;
1468         uint32_t dramTiming2;
1469         uint32_t burstTime;
1470         int result;
1471
1472         result = atomctrl_set_engine_dram_timings_rv770(hwmgr,
1473                                 engine_clock, memory_clock);
1474
1475         PP_ASSERT_WITH_CODE(result == 0,
1476                 "Error calling VBIOS to set DRAM_TIMING.", return result);
1477
1478         dramTiming  = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING);
1479         dramTiming2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2);
1480         burstTime = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0);
1481
1482         arb_regs->McArbDramTiming  = PP_HOST_TO_SMC_UL(dramTiming);
1483         arb_regs->McArbDramTiming2 = PP_HOST_TO_SMC_UL(dramTiming2);
1484         arb_regs->McArbBurstTime = (uint8_t)burstTime;
1485
1486         return 0;
1487 }
1488
1489 /**
1490  * Setup parameters for the MC ARB.
1491  *
1492  * @param    hwmgr  the address of the powerplay hardware manager.
1493  * @return   always 0
1494  * This function is to be called from the SetPowerState table.
1495  */
1496 static int iceland_program_memory_timing_parameters(struct pp_hwmgr *hwmgr)
1497 {
1498         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1499         struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smumgr->backend);
1500         int result = 0;
1501         SMU71_Discrete_MCArbDramTimingTable  arb_regs;
1502         uint32_t i, j;
1503
1504         memset(&arb_regs, 0x00, sizeof(SMU71_Discrete_MCArbDramTimingTable));
1505
1506         for (i = 0; i < data->dpm_table.sclk_table.count; i++) {
1507                 for (j = 0; j < data->dpm_table.mclk_table.count; j++) {
1508                         result = iceland_populate_memory_timing_parameters
1509                                 (hwmgr, data->dpm_table.sclk_table.dpm_levels[i].value,
1510                                  data->dpm_table.mclk_table.dpm_levels[j].value,
1511                                  &arb_regs.entries[i][j]);
1512
1513                         if (0 != result) {
1514                                 break;
1515                         }
1516                 }
1517         }
1518
1519         if (0 == result) {
1520                 result = smu7_copy_bytes_to_smc(
1521                                 hwmgr->smumgr,
1522                                 smu_data->smu7_data.arb_table_start,
1523                                 (uint8_t *)&arb_regs,
1524                                 sizeof(SMU71_Discrete_MCArbDramTimingTable),
1525                                 SMC_RAM_END
1526                                 );
1527         }
1528
1529         return result;
1530 }
1531
1532 static int iceland_populate_smc_boot_level(struct pp_hwmgr *hwmgr,
1533                         SMU71_Discrete_DpmTable *table)
1534 {
1535         int result = 0;
1536         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1537         struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smumgr->backend);
1538         table->GraphicsBootLevel = 0;
1539         table->MemoryBootLevel = 0;
1540
1541         /* find boot level from dpm table*/
1542         result = phm_find_boot_level(&(data->dpm_table.sclk_table),
1543                         data->vbios_boot_state.sclk_bootup_value,
1544                         (uint32_t *)&(smu_data->smc_state_table.GraphicsBootLevel));
1545
1546         if (0 != result) {
1547                 smu_data->smc_state_table.GraphicsBootLevel = 0;
1548                 printk(KERN_ERR "[ powerplay ] VBIOS did not find boot engine clock value \
1549                         in dependency table. Using Graphics DPM level 0!");
1550                 result = 0;
1551         }
1552
1553         result = phm_find_boot_level(&(data->dpm_table.mclk_table),
1554                 data->vbios_boot_state.mclk_bootup_value,
1555                 (uint32_t *)&(smu_data->smc_state_table.MemoryBootLevel));
1556
1557         if (0 != result) {
1558                 smu_data->smc_state_table.MemoryBootLevel = 0;
1559                 printk(KERN_ERR "[ powerplay ] VBIOS did not find boot engine clock value \
1560                         in dependency table. Using Memory DPM level 0!");
1561                 result = 0;
1562         }
1563
1564         table->BootVddc = data->vbios_boot_state.vddc_bootup_value;
1565         if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control)
1566                 table->BootVddci = table->BootVddc;
1567         else
1568                 table->BootVddci = data->vbios_boot_state.vddci_bootup_value;
1569
1570         table->BootMVdd = data->vbios_boot_state.mvdd_bootup_value;
1571
1572         return result;
1573 }
1574
1575 static int iceland_populate_mc_reg_address(struct pp_smumgr *smumgr,
1576                                  SMU71_Discrete_MCRegisters *mc_reg_table)
1577 {
1578         const struct iceland_smumgr *smu_data = (struct iceland_smumgr *)smumgr->backend;
1579
1580         uint32_t i, j;
1581
1582         for (i = 0, j = 0; j < smu_data->mc_reg_table.last; j++) {
1583                 if (smu_data->mc_reg_table.validflag & 1<<j) {
1584                         PP_ASSERT_WITH_CODE(i < SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE,
1585                                 "Index of mc_reg_table->address[] array out of boundary", return -EINVAL);
1586                         mc_reg_table->address[i].s0 =
1587                                 PP_HOST_TO_SMC_US(smu_data->mc_reg_table.mc_reg_address[j].s0);
1588                         mc_reg_table->address[i].s1 =
1589                                 PP_HOST_TO_SMC_US(smu_data->mc_reg_table.mc_reg_address[j].s1);
1590                         i++;
1591                 }
1592         }
1593
1594         mc_reg_table->last = (uint8_t)i;
1595
1596         return 0;
1597 }
1598
1599 /*convert register values from driver to SMC format */
1600 static void iceland_convert_mc_registers(
1601         const struct iceland_mc_reg_entry *entry,
1602         SMU71_Discrete_MCRegisterSet *data,
1603         uint32_t num_entries, uint32_t valid_flag)
1604 {
1605         uint32_t i, j;
1606
1607         for (i = 0, j = 0; j < num_entries; j++) {
1608                 if (valid_flag & 1<<j) {
1609                         data->value[i] = PP_HOST_TO_SMC_UL(entry->mc_data[j]);
1610                         i++;
1611                 }
1612         }
1613 }
1614
1615 static int iceland_convert_mc_reg_table_entry_to_smc(
1616                 struct pp_smumgr *smumgr,
1617                 const uint32_t memory_clock,
1618                 SMU71_Discrete_MCRegisterSet *mc_reg_table_data
1619                 )
1620 {
1621         struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(smumgr->backend);
1622         uint32_t i = 0;
1623
1624         for (i = 0; i < smu_data->mc_reg_table.num_entries; i++) {
1625                 if (memory_clock <=
1626                         smu_data->mc_reg_table.mc_reg_table_entry[i].mclk_max) {
1627                         break;
1628                 }
1629         }
1630
1631         if ((i == smu_data->mc_reg_table.num_entries) && (i > 0))
1632                 --i;
1633
1634         iceland_convert_mc_registers(&smu_data->mc_reg_table.mc_reg_table_entry[i],
1635                                 mc_reg_table_data, smu_data->mc_reg_table.last,
1636                                 smu_data->mc_reg_table.validflag);
1637
1638         return 0;
1639 }
1640
1641 static int iceland_convert_mc_reg_table_to_smc(struct pp_hwmgr *hwmgr,
1642                 SMU71_Discrete_MCRegisters *mc_regs)
1643 {
1644         int result = 0;
1645         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1646         int res;
1647         uint32_t i;
1648
1649         for (i = 0; i < data->dpm_table.mclk_table.count; i++) {
1650                 res = iceland_convert_mc_reg_table_entry_to_smc(
1651                                 hwmgr->smumgr,
1652                                 data->dpm_table.mclk_table.dpm_levels[i].value,
1653                                 &mc_regs->data[i]
1654                                 );
1655
1656                 if (0 != res)
1657                         result = res;
1658         }
1659
1660         return result;
1661 }
1662
1663 static int iceland_update_and_upload_mc_reg_table(struct pp_hwmgr *hwmgr)
1664 {
1665         struct pp_smumgr *smumgr = hwmgr->smumgr;
1666         struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(smumgr->backend);
1667         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1668         uint32_t address;
1669         int32_t result;
1670
1671         if (0 == (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK))
1672                 return 0;
1673
1674
1675         memset(&smu_data->mc_regs, 0, sizeof(SMU71_Discrete_MCRegisters));
1676
1677         result = iceland_convert_mc_reg_table_to_smc(hwmgr, &(smu_data->mc_regs));
1678
1679         if (result != 0)
1680                 return result;
1681
1682
1683         address = smu_data->smu7_data.mc_reg_table_start + (uint32_t)offsetof(SMU71_Discrete_MCRegisters, data[0]);
1684
1685         return  smu7_copy_bytes_to_smc(hwmgr->smumgr, address,
1686                                  (uint8_t *)&smu_data->mc_regs.data[0],
1687                                 sizeof(SMU71_Discrete_MCRegisterSet) * data->dpm_table.mclk_table.count,
1688                                 SMC_RAM_END);
1689 }
1690
1691 static int iceland_populate_initial_mc_reg_table(struct pp_hwmgr *hwmgr)
1692 {
1693         int result;
1694         struct pp_smumgr *smumgr = hwmgr->smumgr;
1695         struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(smumgr->backend);
1696
1697         memset(&smu_data->mc_regs, 0x00, sizeof(SMU71_Discrete_MCRegisters));
1698         result = iceland_populate_mc_reg_address(smumgr, &(smu_data->mc_regs));
1699         PP_ASSERT_WITH_CODE(0 == result,
1700                 "Failed to initialize MCRegTable for the MC register addresses!", return result;);
1701
1702         result = iceland_convert_mc_reg_table_to_smc(hwmgr, &smu_data->mc_regs);
1703         PP_ASSERT_WITH_CODE(0 == result,
1704                 "Failed to initialize MCRegTable for driver state!", return result;);
1705
1706         return smu7_copy_bytes_to_smc(smumgr, smu_data->smu7_data.mc_reg_table_start,
1707                         (uint8_t *)&smu_data->mc_regs, sizeof(SMU71_Discrete_MCRegisters), SMC_RAM_END);
1708 }
1709
1710 static int iceland_populate_smc_initial_state(struct pp_hwmgr *hwmgr)
1711 {
1712         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1713         struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smumgr->backend);
1714         uint8_t count, level;
1715
1716         count = (uint8_t)(hwmgr->dyn_state.vddc_dependency_on_sclk->count);
1717
1718         for (level = 0; level < count; level++) {
1719                 if (hwmgr->dyn_state.vddc_dependency_on_sclk->entries[level].clk
1720                          >= data->vbios_boot_state.sclk_bootup_value) {
1721                         smu_data->smc_state_table.GraphicsBootLevel = level;
1722                         break;
1723                 }
1724         }
1725
1726         count = (uint8_t)(hwmgr->dyn_state.vddc_dependency_on_mclk->count);
1727
1728         for (level = 0; level < count; level++) {
1729                 if (hwmgr->dyn_state.vddc_dependency_on_mclk->entries[level].clk
1730                         >= data->vbios_boot_state.mclk_bootup_value) {
1731                         smu_data->smc_state_table.MemoryBootLevel = level;
1732                         break;
1733                 }
1734         }
1735
1736         return 0;
1737 }
1738
1739 static int iceland_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr)
1740 {
1741         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1742         struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smumgr->backend);
1743         const struct iceland_pt_defaults *defaults = smu_data->power_tune_defaults;
1744         SMU71_Discrete_DpmTable  *dpm_table = &(smu_data->smc_state_table);
1745         struct phm_cac_tdp_table *cac_dtp_table = hwmgr->dyn_state.cac_dtp_table;
1746         struct phm_ppm_table *ppm = hwmgr->dyn_state.ppm_parameter_table;
1747         const uint16_t *def1, *def2;
1748         int i, j, k;
1749
1750
1751         /*
1752          * TDP number of fraction bits are changed from 8 to 7 for Iceland
1753          * as requested by SMC team
1754          */
1755
1756         dpm_table->DefaultTdp = PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table->usTDP * 256));
1757         dpm_table->TargetTdp = PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table->usConfigurableTDP * 256));
1758
1759
1760         dpm_table->DTETjOffset = 0;
1761
1762         dpm_table->GpuTjMax = (uint8_t)(data->thermal_temp_setting.temperature_high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES);
1763         dpm_table->GpuTjHyst = 8;
1764
1765         dpm_table->DTEAmbientTempBase = defaults->dte_ambient_temp_base;
1766
1767         /* The following are for new Iceland Multi-input fan/thermal control */
1768         if (NULL != ppm) {
1769                 dpm_table->PPM_PkgPwrLimit = (uint16_t)ppm->dgpu_tdp * 256 / 1000;
1770                 dpm_table->PPM_TemperatureLimit = (uint16_t)ppm->tj_max * 256;
1771         } else {
1772                 dpm_table->PPM_PkgPwrLimit = 0;
1773                 dpm_table->PPM_TemperatureLimit = 0;
1774         }
1775
1776         CONVERT_FROM_HOST_TO_SMC_US(dpm_table->PPM_PkgPwrLimit);
1777         CONVERT_FROM_HOST_TO_SMC_US(dpm_table->PPM_TemperatureLimit);
1778
1779         dpm_table->BAPM_TEMP_GRADIENT = PP_HOST_TO_SMC_UL(defaults->bamp_temp_gradient);
1780         def1 = defaults->bapmti_r;
1781         def2 = defaults->bapmti_rc;
1782
1783         for (i = 0; i < SMU71_DTE_ITERATIONS; i++) {
1784                 for (j = 0; j < SMU71_DTE_SOURCES; j++) {
1785                         for (k = 0; k < SMU71_DTE_SINKS; k++) {
1786                                 dpm_table->BAPMTI_R[i][j][k] = PP_HOST_TO_SMC_US(*def1);
1787                                 dpm_table->BAPMTI_RC[i][j][k] = PP_HOST_TO_SMC_US(*def2);
1788                                 def1++;
1789                                 def2++;
1790                         }
1791                 }
1792         }
1793
1794         return 0;
1795 }
1796
1797 static int iceland_populate_smc_svi2_config(struct pp_hwmgr *hwmgr,
1798                                             SMU71_Discrete_DpmTable *tab)
1799 {
1800         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1801
1802         if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control)
1803                 tab->SVI2Enable |= VDDC_ON_SVI2;
1804
1805         if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control)
1806                 tab->SVI2Enable |= VDDCI_ON_SVI2;
1807         else
1808                 tab->MergedVddci = 1;
1809
1810         if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->mvdd_control)
1811                 tab->SVI2Enable |= MVDD_ON_SVI2;
1812
1813         PP_ASSERT_WITH_CODE(tab->SVI2Enable != (VDDC_ON_SVI2 | VDDCI_ON_SVI2 | MVDD_ON_SVI2) &&
1814                 (tab->SVI2Enable & VDDC_ON_SVI2), "SVI2 domain configuration is incorrect!", return -EINVAL);
1815
1816         return 0;
1817 }
1818
1819 /**
1820  * Initializes the SMC table and uploads it
1821  *
1822  * @param    hwmgr  the address of the powerplay hardware manager.
1823  * @param    pInput  the pointer to input data (PowerState)
1824  * @return   always 0
1825  */
1826 int iceland_init_smc_table(struct pp_hwmgr *hwmgr)
1827 {
1828         int result;
1829         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1830         struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smumgr->backend);
1831         SMU71_Discrete_DpmTable  *table = &(smu_data->smc_state_table);
1832
1833
1834         iceland_initialize_power_tune_defaults(hwmgr);
1835         memset(&(smu_data->smc_state_table), 0x00, sizeof(smu_data->smc_state_table));
1836
1837         if (SMU7_VOLTAGE_CONTROL_NONE != data->voltage_control) {
1838                 iceland_populate_smc_voltage_tables(hwmgr, table);
1839         }
1840
1841         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1842                         PHM_PlatformCaps_AutomaticDCTransition))
1843                 table->SystemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC;
1844
1845
1846         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1847                         PHM_PlatformCaps_StepVddc))
1848                 table->SystemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC;
1849
1850         if (data->is_memory_gddr5)
1851                 table->SystemFlags |= PPSMC_SYSTEMFLAG_GDDR5;
1852
1853
1854         if (data->ulv_supported) {
1855                 result = iceland_populate_ulv_state(hwmgr, &(smu_data->ulv_setting));
1856                 PP_ASSERT_WITH_CODE(0 == result,
1857                         "Failed to initialize ULV state!", return result;);
1858
1859                 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
1860                         ixCG_ULV_PARAMETER, 0x40035);
1861         }
1862
1863         result = iceland_populate_smc_link_level(hwmgr, table);
1864         PP_ASSERT_WITH_CODE(0 == result,
1865                 "Failed to initialize Link Level!", return result;);
1866
1867         result = iceland_populate_all_graphic_levels(hwmgr);
1868         PP_ASSERT_WITH_CODE(0 == result,
1869                 "Failed to initialize Graphics Level!", return result;);
1870
1871         result = iceland_populate_all_memory_levels(hwmgr);
1872         PP_ASSERT_WITH_CODE(0 == result,
1873                 "Failed to initialize Memory Level!", return result;);
1874
1875         result = iceland_populate_smc_acpi_level(hwmgr, table);
1876         PP_ASSERT_WITH_CODE(0 == result,
1877                 "Failed to initialize ACPI Level!", return result;);
1878
1879         result = iceland_populate_smc_vce_level(hwmgr, table);
1880         PP_ASSERT_WITH_CODE(0 == result,
1881                 "Failed to initialize VCE Level!", return result;);
1882
1883         result = iceland_populate_smc_acp_level(hwmgr, table);
1884         PP_ASSERT_WITH_CODE(0 == result,
1885                 "Failed to initialize ACP Level!", return result;);
1886
1887         result = iceland_populate_smc_samu_level(hwmgr, table);
1888         PP_ASSERT_WITH_CODE(0 == result,
1889                 "Failed to initialize SAMU Level!", return result;);
1890
1891         /* Since only the initial state is completely set up at this point (the other states are just copies of the boot state) we only */
1892         /* need to populate the  ARB settings for the initial state. */
1893         result = iceland_program_memory_timing_parameters(hwmgr);
1894         PP_ASSERT_WITH_CODE(0 == result,
1895                 "Failed to Write ARB settings for the initial state.", return result;);
1896
1897         result = iceland_populate_smc_uvd_level(hwmgr, table);
1898         PP_ASSERT_WITH_CODE(0 == result,
1899                 "Failed to initialize UVD Level!", return result;);
1900
1901         table->GraphicsBootLevel = 0;
1902         table->MemoryBootLevel = 0;
1903
1904         result = iceland_populate_smc_boot_level(hwmgr, table);
1905         PP_ASSERT_WITH_CODE(0 == result,
1906                 "Failed to initialize Boot Level!", return result;);
1907
1908         result = iceland_populate_smc_initial_state(hwmgr);
1909         PP_ASSERT_WITH_CODE(0 == result, "Failed to initialize Boot State!", return result);
1910
1911         result = iceland_populate_bapm_parameters_in_dpm_table(hwmgr);
1912         PP_ASSERT_WITH_CODE(0 == result, "Failed to populate BAPM Parameters!", return result);
1913
1914         table->GraphicsVoltageChangeEnable  = 1;
1915         table->GraphicsThermThrottleEnable  = 1;
1916         table->GraphicsInterval = 1;
1917         table->VoltageInterval  = 1;
1918         table->ThermalInterval  = 1;
1919
1920         table->TemperatureLimitHigh =
1921                 (data->thermal_temp_setting.temperature_high *
1922                  SMU7_Q88_FORMAT_CONVERSION_UNIT) / PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
1923         table->TemperatureLimitLow =
1924                 (data->thermal_temp_setting.temperature_low *
1925                 SMU7_Q88_FORMAT_CONVERSION_UNIT) / PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
1926
1927         table->MemoryVoltageChangeEnable  = 1;
1928         table->MemoryInterval  = 1;
1929         table->VoltageResponseTime  = 0;
1930         table->PhaseResponseTime  = 0;
1931         table->MemoryThermThrottleEnable  = 1;
1932         table->PCIeBootLinkLevel = 0;
1933         table->PCIeGenInterval = 1;
1934
1935         result = iceland_populate_smc_svi2_config(hwmgr, table);
1936         PP_ASSERT_WITH_CODE(0 == result,
1937                 "Failed to populate SVI2 setting!", return result);
1938
1939         table->ThermGpio  = 17;
1940         table->SclkStepSize = 0x4000;
1941
1942         CONVERT_FROM_HOST_TO_SMC_UL(table->SystemFlags);
1943         CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskVddcVid);
1944         CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskVddcPhase);
1945         CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskVddciVid);
1946         CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskMvddVid);
1947         CONVERT_FROM_HOST_TO_SMC_UL(table->SclkStepSize);
1948         CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitHigh);
1949         CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitLow);
1950         CONVERT_FROM_HOST_TO_SMC_US(table->VoltageResponseTime);
1951         CONVERT_FROM_HOST_TO_SMC_US(table->PhaseResponseTime);
1952
1953         table->BootVddc = PP_HOST_TO_SMC_US(table->BootVddc * VOLTAGE_SCALE);
1954         table->BootVddci = PP_HOST_TO_SMC_US(table->BootVddci * VOLTAGE_SCALE);
1955         table->BootMVdd = PP_HOST_TO_SMC_US(table->BootMVdd * VOLTAGE_SCALE);
1956
1957         /* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */
1958         result = smu7_copy_bytes_to_smc(hwmgr->smumgr, smu_data->smu7_data.dpm_table_start +
1959                                                                                 offsetof(SMU71_Discrete_DpmTable, SystemFlags),
1960                                                                                 (uint8_t *)&(table->SystemFlags),
1961                                                                                 sizeof(SMU71_Discrete_DpmTable)-3 * sizeof(SMU71_PIDController),
1962                                                                                 SMC_RAM_END);
1963
1964         PP_ASSERT_WITH_CODE(0 == result,
1965                 "Failed to upload dpm data to SMC memory!", return result;);
1966
1967         /* Upload all ulv setting to SMC memory.(dpm level, dpm level count etc) */
1968         result = smu7_copy_bytes_to_smc(hwmgr->smumgr,
1969                         smu_data->smu7_data.ulv_setting_starts,
1970                         (uint8_t *)&(smu_data->ulv_setting),
1971                         sizeof(SMU71_Discrete_Ulv),
1972                         SMC_RAM_END);
1973
1974
1975         result = iceland_populate_initial_mc_reg_table(hwmgr);
1976         PP_ASSERT_WITH_CODE((0 == result),
1977                 "Failed to populate initialize MC Reg table!", return result);
1978
1979         result = iceland_populate_pm_fuses(hwmgr);
1980         PP_ASSERT_WITH_CODE(0 == result,
1981                         "Failed to  populate PM fuses to SMC memory!", return result);
1982
1983         return 0;
1984 }
1985
1986 /**
1987 * Set up the fan table to control the fan using the SMC.
1988 * @param    hwmgr  the address of the powerplay hardware manager.
1989 * @param    pInput the pointer to input data
1990 * @param    pOutput the pointer to output data
1991 * @param    pStorage the pointer to temporary storage
1992 * @param    Result the last failure code
1993 * @return   result from set temperature range routine
1994 */
1995 int iceland_thermal_setup_fan_table(struct pp_hwmgr *hwmgr)
1996 {
1997         struct smu7_smumgr *smu7_data = (struct smu7_smumgr *)(hwmgr->smumgr->backend);
1998         SMU71_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE };
1999         uint32_t duty100;
2000         uint32_t t_diff1, t_diff2, pwm_diff1, pwm_diff2;
2001         uint16_t fdo_min, slope1, slope2;
2002         uint32_t reference_clock;
2003         int res;
2004         uint64_t tmp64;
2005
2006         if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl))
2007                 return 0;
2008
2009         if (0 == smu7_data->fan_table_start) {
2010                 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl);
2011                 return 0;
2012         }
2013
2014         duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL1, FMAX_DUTY100);
2015
2016         if (0 == duty100) {
2017                 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl);
2018                 return 0;
2019         }
2020
2021         tmp64 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin * duty100;
2022         do_div(tmp64, 10000);
2023         fdo_min = (uint16_t)tmp64;
2024
2025         t_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usTMed - hwmgr->thermal_controller.advanceFanControlParameters.usTMin;
2026         t_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usTHigh - hwmgr->thermal_controller.advanceFanControlParameters.usTMed;
2027
2028         pwm_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin;
2029         pwm_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed;
2030
2031         slope1 = (uint16_t)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100);
2032         slope2 = (uint16_t)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100);
2033
2034         fan_table.TempMin = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMin) / 100);
2035         fan_table.TempMed = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMed) / 100);
2036         fan_table.TempMax = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMax) / 100);
2037
2038         fan_table.Slope1 = cpu_to_be16(slope1);
2039         fan_table.Slope2 = cpu_to_be16(slope2);
2040
2041         fan_table.FdoMin = cpu_to_be16(fdo_min);
2042
2043         fan_table.HystDown = cpu_to_be16(hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst);
2044
2045         fan_table.HystUp = cpu_to_be16(1);
2046
2047         fan_table.HystSlope = cpu_to_be16(1);
2048
2049         fan_table.TempRespLim = cpu_to_be16(5);
2050
2051         reference_clock = smu7_get_xclk(hwmgr);
2052
2053         fan_table.RefreshPeriod = cpu_to_be32((hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay * reference_clock) / 1600);
2054
2055         fan_table.FdoMax = cpu_to_be16((uint16_t)duty100);
2056
2057         fan_table.TempSrc = (uint8_t)PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_MULT_THERMAL_CTRL, TEMP_SEL);
2058
2059         /* fan_table.FanControl_GL_Flag = 1; */
2060
2061         res = smu7_copy_bytes_to_smc(hwmgr->smumgr, smu7_data->fan_table_start, (uint8_t *)&fan_table, (uint32_t)sizeof(fan_table), SMC_RAM_END);
2062
2063         return 0;
2064 }
2065
2066
2067 static int iceland_program_mem_timing_parameters(struct pp_hwmgr *hwmgr)
2068 {
2069         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2070
2071         if (data->need_update_smu7_dpm_table &
2072                 (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_OD_UPDATE_MCLK))
2073                 return iceland_program_memory_timing_parameters(hwmgr);
2074
2075         return 0;
2076 }
2077
2078 int iceland_update_sclk_threshold(struct pp_hwmgr *hwmgr)
2079 {
2080         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2081         struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smumgr->backend);
2082
2083         int result = 0;
2084         uint32_t low_sclk_interrupt_threshold = 0;
2085
2086         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2087                         PHM_PlatformCaps_SclkThrottleLowNotification)
2088                 && (hwmgr->gfx_arbiter.sclk_threshold !=
2089                                 data->low_sclk_interrupt_threshold)) {
2090                 data->low_sclk_interrupt_threshold =
2091                                 hwmgr->gfx_arbiter.sclk_threshold;
2092                 low_sclk_interrupt_threshold =
2093                                 data->low_sclk_interrupt_threshold;
2094
2095                 CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold);
2096
2097                 result = smu7_copy_bytes_to_smc(
2098                                 hwmgr->smumgr,
2099                                 smu_data->smu7_data.dpm_table_start +
2100                                 offsetof(SMU71_Discrete_DpmTable,
2101                                         LowSclkInterruptThreshold),
2102                                 (uint8_t *)&low_sclk_interrupt_threshold,
2103                                 sizeof(uint32_t),
2104                                 SMC_RAM_END);
2105         }
2106
2107         result = iceland_update_and_upload_mc_reg_table(hwmgr);
2108
2109         PP_ASSERT_WITH_CODE((0 == result), "Failed to upload MC reg table!", return result);
2110
2111         result = iceland_program_mem_timing_parameters(hwmgr);
2112         PP_ASSERT_WITH_CODE((result == 0),
2113                         "Failed to program memory timing parameters!",
2114                         );
2115
2116         return result;
2117 }
2118
2119 uint32_t iceland_get_offsetof(uint32_t type, uint32_t member)
2120 {
2121         switch (type) {
2122         case SMU_SoftRegisters:
2123                 switch (member) {
2124                 case HandshakeDisables:
2125                         return offsetof(SMU71_SoftRegisters, HandshakeDisables);
2126                 case VoltageChangeTimeout:
2127                         return offsetof(SMU71_SoftRegisters, VoltageChangeTimeout);
2128                 case AverageGraphicsActivity:
2129                         return offsetof(SMU71_SoftRegisters, AverageGraphicsActivity);
2130                 case PreVBlankGap:
2131                         return offsetof(SMU71_SoftRegisters, PreVBlankGap);
2132                 case VBlankTimeout:
2133                         return offsetof(SMU71_SoftRegisters, VBlankTimeout);
2134                 case UcodeLoadStatus:
2135                         return offsetof(SMU71_SoftRegisters, UcodeLoadStatus);
2136                 }
2137         case SMU_Discrete_DpmTable:
2138                 switch (member) {
2139                 case LowSclkInterruptThreshold:
2140                         return offsetof(SMU71_Discrete_DpmTable, LowSclkInterruptThreshold);
2141                 }
2142         }
2143         printk("cant't get the offset of type %x member %x \n", type, member);
2144         return 0;
2145 }
2146
2147 uint32_t iceland_get_mac_definition(uint32_t value)
2148 {
2149         switch (value) {
2150         case SMU_MAX_LEVELS_GRAPHICS:
2151                 return SMU71_MAX_LEVELS_GRAPHICS;
2152         case SMU_MAX_LEVELS_MEMORY:
2153                 return SMU71_MAX_LEVELS_MEMORY;
2154         case SMU_MAX_LEVELS_LINK:
2155                 return SMU71_MAX_LEVELS_LINK;
2156         case SMU_MAX_ENTRIES_SMIO:
2157                 return SMU71_MAX_ENTRIES_SMIO;
2158         case SMU_MAX_LEVELS_VDDC:
2159                 return SMU71_MAX_LEVELS_VDDC;
2160         case SMU_MAX_LEVELS_VDDCI:
2161                 return SMU71_MAX_LEVELS_VDDCI;
2162         case SMU_MAX_LEVELS_MVDD:
2163                 return SMU71_MAX_LEVELS_MVDD;
2164         }
2165
2166         printk("cant't get the mac of %x \n", value);
2167         return 0;
2168 }
2169
2170 /**
2171  * Get the location of various tables inside the FW image.
2172  *
2173  * @param    hwmgr  the address of the powerplay hardware manager.
2174  * @return   always 0
2175  */
2176 int iceland_process_firmware_header(struct pp_hwmgr *hwmgr)
2177 {
2178         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2179         struct smu7_smumgr *smu7_data = (struct smu7_smumgr *)(hwmgr->smumgr->backend);
2180
2181         uint32_t tmp;
2182         int result;
2183         bool error = false;
2184
2185         result = smu7_read_smc_sram_dword(hwmgr->smumgr,
2186                                 SMU71_FIRMWARE_HEADER_LOCATION +
2187                                 offsetof(SMU71_Firmware_Header, DpmTable),
2188                                 &tmp, SMC_RAM_END);
2189
2190         if (0 == result) {
2191                 smu7_data->dpm_table_start = tmp;
2192         }
2193
2194         error |= (0 != result);
2195
2196         result = smu7_read_smc_sram_dword(hwmgr->smumgr,
2197                                 SMU71_FIRMWARE_HEADER_LOCATION +
2198                                 offsetof(SMU71_Firmware_Header, SoftRegisters),
2199                                 &tmp, SMC_RAM_END);
2200
2201         if (0 == result) {
2202                 data->soft_regs_start = tmp;
2203                 smu7_data->soft_regs_start = tmp;
2204         }
2205
2206         error |= (0 != result);
2207
2208
2209         result = smu7_read_smc_sram_dword(hwmgr->smumgr,
2210                                 SMU71_FIRMWARE_HEADER_LOCATION +
2211                                 offsetof(SMU71_Firmware_Header, mcRegisterTable),
2212                                 &tmp, SMC_RAM_END);
2213
2214         if (0 == result) {
2215                 smu7_data->mc_reg_table_start = tmp;
2216         }
2217
2218         result = smu7_read_smc_sram_dword(hwmgr->smumgr,
2219                                 SMU71_FIRMWARE_HEADER_LOCATION +
2220                                 offsetof(SMU71_Firmware_Header, FanTable),
2221                                 &tmp, SMC_RAM_END);
2222
2223         if (0 == result) {
2224                 smu7_data->fan_table_start = tmp;
2225         }
2226
2227         error |= (0 != result);
2228
2229         result = smu7_read_smc_sram_dword(hwmgr->smumgr,
2230                                 SMU71_FIRMWARE_HEADER_LOCATION +
2231                                 offsetof(SMU71_Firmware_Header, mcArbDramTimingTable),
2232                                 &tmp, SMC_RAM_END);
2233
2234         if (0 == result) {
2235                 smu7_data->arb_table_start = tmp;
2236         }
2237
2238         error |= (0 != result);
2239
2240
2241         result = smu7_read_smc_sram_dword(hwmgr->smumgr,
2242                                 SMU71_FIRMWARE_HEADER_LOCATION +
2243                                 offsetof(SMU71_Firmware_Header, Version),
2244                                 &tmp, SMC_RAM_END);
2245
2246         if (0 == result) {
2247                 hwmgr->microcode_version_info.SMC = tmp;
2248         }
2249
2250         error |= (0 != result);
2251
2252         result = smu7_read_smc_sram_dword(hwmgr->smumgr,
2253                                 SMU71_FIRMWARE_HEADER_LOCATION +
2254                                 offsetof(SMU71_Firmware_Header, UlvSettings),
2255                                 &tmp, SMC_RAM_END);
2256
2257         if (0 == result) {
2258                 smu7_data->ulv_setting_starts = tmp;
2259         }
2260
2261         error |= (0 != result);
2262
2263         return error ? 1 : 0;
2264 }
2265
2266 /*---------------------------MC----------------------------*/
2267
2268 static uint8_t iceland_get_memory_modile_index(struct pp_hwmgr *hwmgr)
2269 {
2270         return (uint8_t) (0xFF & (cgs_read_register(hwmgr->device, mmBIOS_SCRATCH_4) >> 16));
2271 }
2272
2273 static bool iceland_check_s0_mc_reg_index(uint16_t in_reg, uint16_t *out_reg)
2274 {
2275         bool result = true;
2276
2277         switch (in_reg) {
2278         case  mmMC_SEQ_RAS_TIMING:
2279                 *out_reg = mmMC_SEQ_RAS_TIMING_LP;
2280                 break;
2281
2282         case  mmMC_SEQ_DLL_STBY:
2283                 *out_reg = mmMC_SEQ_DLL_STBY_LP;
2284                 break;
2285
2286         case  mmMC_SEQ_G5PDX_CMD0:
2287                 *out_reg = mmMC_SEQ_G5PDX_CMD0_LP;
2288                 break;
2289
2290         case  mmMC_SEQ_G5PDX_CMD1:
2291                 *out_reg = mmMC_SEQ_G5PDX_CMD1_LP;
2292                 break;
2293
2294         case  mmMC_SEQ_G5PDX_CTRL:
2295                 *out_reg = mmMC_SEQ_G5PDX_CTRL_LP;
2296                 break;
2297
2298         case mmMC_SEQ_CAS_TIMING:
2299                 *out_reg = mmMC_SEQ_CAS_TIMING_LP;
2300                 break;
2301
2302         case mmMC_SEQ_MISC_TIMING:
2303                 *out_reg = mmMC_SEQ_MISC_TIMING_LP;
2304                 break;
2305
2306         case mmMC_SEQ_MISC_TIMING2:
2307                 *out_reg = mmMC_SEQ_MISC_TIMING2_LP;
2308                 break;
2309
2310         case mmMC_SEQ_PMG_DVS_CMD:
2311                 *out_reg = mmMC_SEQ_PMG_DVS_CMD_LP;
2312                 break;
2313
2314         case mmMC_SEQ_PMG_DVS_CTL:
2315                 *out_reg = mmMC_SEQ_PMG_DVS_CTL_LP;
2316                 break;
2317
2318         case mmMC_SEQ_RD_CTL_D0:
2319                 *out_reg = mmMC_SEQ_RD_CTL_D0_LP;
2320                 break;
2321
2322         case mmMC_SEQ_RD_CTL_D1:
2323                 *out_reg = mmMC_SEQ_RD_CTL_D1_LP;
2324                 break;
2325
2326         case mmMC_SEQ_WR_CTL_D0:
2327                 *out_reg = mmMC_SEQ_WR_CTL_D0_LP;
2328                 break;
2329
2330         case mmMC_SEQ_WR_CTL_D1:
2331                 *out_reg = mmMC_SEQ_WR_CTL_D1_LP;
2332                 break;
2333
2334         case mmMC_PMG_CMD_EMRS:
2335                 *out_reg = mmMC_SEQ_PMG_CMD_EMRS_LP;
2336                 break;
2337
2338         case mmMC_PMG_CMD_MRS:
2339                 *out_reg = mmMC_SEQ_PMG_CMD_MRS_LP;
2340                 break;
2341
2342         case mmMC_PMG_CMD_MRS1:
2343                 *out_reg = mmMC_SEQ_PMG_CMD_MRS1_LP;
2344                 break;
2345
2346         case mmMC_SEQ_PMG_TIMING:
2347                 *out_reg = mmMC_SEQ_PMG_TIMING_LP;
2348                 break;
2349
2350         case mmMC_PMG_CMD_MRS2:
2351                 *out_reg = mmMC_SEQ_PMG_CMD_MRS2_LP;
2352                 break;
2353
2354         case mmMC_SEQ_WR_CTL_2:
2355                 *out_reg = mmMC_SEQ_WR_CTL_2_LP;
2356                 break;
2357
2358         default:
2359                 result = false;
2360                 break;
2361         }
2362
2363         return result;
2364 }
2365
2366 static int iceland_set_s0_mc_reg_index(struct iceland_mc_reg_table *table)
2367 {
2368         uint32_t i;
2369         uint16_t address;
2370
2371         for (i = 0; i < table->last; i++) {
2372                 table->mc_reg_address[i].s0 =
2373                         iceland_check_s0_mc_reg_index(table->mc_reg_address[i].s1, &address)
2374                         ? address : table->mc_reg_address[i].s1;
2375         }
2376         return 0;
2377 }
2378
2379 static int iceland_copy_vbios_smc_reg_table(const pp_atomctrl_mc_reg_table *table,
2380                                         struct iceland_mc_reg_table *ni_table)
2381 {
2382         uint8_t i, j;
2383
2384         PP_ASSERT_WITH_CODE((table->last <= SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE),
2385                 "Invalid VramInfo table.", return -EINVAL);
2386         PP_ASSERT_WITH_CODE((table->num_entries <= MAX_AC_TIMING_ENTRIES),
2387                 "Invalid VramInfo table.", return -EINVAL);
2388
2389         for (i = 0; i < table->last; i++) {
2390                 ni_table->mc_reg_address[i].s1 = table->mc_reg_address[i].s1;
2391         }
2392         ni_table->last = table->last;
2393
2394         for (i = 0; i < table->num_entries; i++) {
2395                 ni_table->mc_reg_table_entry[i].mclk_max =
2396                         table->mc_reg_table_entry[i].mclk_max;
2397                 for (j = 0; j < table->last; j++) {
2398                         ni_table->mc_reg_table_entry[i].mc_data[j] =
2399                                 table->mc_reg_table_entry[i].mc_data[j];
2400                 }
2401         }
2402
2403         ni_table->num_entries = table->num_entries;
2404
2405         return 0;
2406 }
2407
2408 /**
2409  * VBIOS omits some information to reduce size, we need to recover them here.
2410  * 1.   when we see mmMC_SEQ_MISC1, bit[31:16] EMRS1, need to be write to  mmMC_PMG_CMD_EMRS /_LP[15:0].
2411  *      Bit[15:0] MRS, need to be update mmMC_PMG_CMD_MRS/_LP[15:0]
2412  * 2.   when we see mmMC_SEQ_RESERVE_M, bit[15:0] EMRS2, need to be write to mmMC_PMG_CMD_MRS1/_LP[15:0].
2413  * 3.   need to set these data for each clock range
2414  *
2415  * @param    hwmgr the address of the powerplay hardware manager.
2416  * @param    table the address of MCRegTable
2417  * @return   always 0
2418  */
2419 static int iceland_set_mc_special_registers(struct pp_hwmgr *hwmgr,
2420                                         struct iceland_mc_reg_table *table)
2421 {
2422         uint8_t i, j, k;
2423         uint32_t temp_reg;
2424         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2425
2426         for (i = 0, j = table->last; i < table->last; i++) {
2427                 PP_ASSERT_WITH_CODE((j < SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE),
2428                         "Invalid VramInfo table.", return -EINVAL);
2429
2430                 switch (table->mc_reg_address[i].s1) {
2431
2432                 case mmMC_SEQ_MISC1:
2433                         temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_EMRS);
2434                         table->mc_reg_address[j].s1 = mmMC_PMG_CMD_EMRS;
2435                         table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_EMRS_LP;
2436                         for (k = 0; k < table->num_entries; k++) {
2437                                 table->mc_reg_table_entry[k].mc_data[j] =
2438                                         ((temp_reg & 0xffff0000)) |
2439                                         ((table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16);
2440                         }
2441                         j++;
2442                         PP_ASSERT_WITH_CODE((j < SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE),
2443                                 "Invalid VramInfo table.", return -EINVAL);
2444
2445                         temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS);
2446                         table->mc_reg_address[j].s1 = mmMC_PMG_CMD_MRS;
2447                         table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_MRS_LP;
2448                         for (k = 0; k < table->num_entries; k++) {
2449                                 table->mc_reg_table_entry[k].mc_data[j] =
2450                                         (temp_reg & 0xffff0000) |
2451                                         (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff);
2452
2453                                 if (!data->is_memory_gddr5) {
2454                                         table->mc_reg_table_entry[k].mc_data[j] |= 0x100;
2455                                 }
2456                         }
2457                         j++;
2458                         PP_ASSERT_WITH_CODE((j <= SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE),
2459                                 "Invalid VramInfo table.", return -EINVAL);
2460
2461                         if (!data->is_memory_gddr5 && j < SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE) {
2462                                 table->mc_reg_address[j].s1 = mmMC_PMG_AUTO_CMD;
2463                                 table->mc_reg_address[j].s0 = mmMC_PMG_AUTO_CMD;
2464                                 for (k = 0; k < table->num_entries; k++) {
2465                                         table->mc_reg_table_entry[k].mc_data[j] =
2466                                                 (table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16;
2467                                 }
2468                                 j++;
2469                                 PP_ASSERT_WITH_CODE((j <= SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE),
2470                                         "Invalid VramInfo table.", return -EINVAL);
2471                         }
2472
2473                         break;
2474
2475                 case mmMC_SEQ_RESERVE_M:
2476                         temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS1);
2477                         table->mc_reg_address[j].s1 = mmMC_PMG_CMD_MRS1;
2478                         table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_MRS1_LP;
2479                         for (k = 0; k < table->num_entries; k++) {
2480                                 table->mc_reg_table_entry[k].mc_data[j] =
2481                                         (temp_reg & 0xffff0000) |
2482                                         (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff);
2483                         }
2484                         j++;
2485                         PP_ASSERT_WITH_CODE((j <= SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE),
2486                                 "Invalid VramInfo table.", return -EINVAL);
2487                         break;
2488
2489                 default:
2490                         break;
2491                 }
2492
2493         }
2494
2495         table->last = j;
2496
2497         return 0;
2498 }
2499
2500 static int iceland_set_valid_flag(struct iceland_mc_reg_table *table)
2501 {
2502         uint8_t i, j;
2503         for (i = 0; i < table->last; i++) {
2504                 for (j = 1; j < table->num_entries; j++) {
2505                         if (table->mc_reg_table_entry[j-1].mc_data[i] !=
2506                                 table->mc_reg_table_entry[j].mc_data[i]) {
2507                                 table->validflag |= (1<<i);
2508                                 break;
2509                         }
2510                 }
2511         }
2512
2513         return 0;
2514 }
2515
2516 int iceland_initialize_mc_reg_table(struct pp_hwmgr *hwmgr)
2517 {
2518         int result;
2519         struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smumgr->backend);
2520         pp_atomctrl_mc_reg_table *table;
2521         struct iceland_mc_reg_table *ni_table = &smu_data->mc_reg_table;
2522         uint8_t module_index = iceland_get_memory_modile_index(hwmgr);
2523
2524         table = kzalloc(sizeof(pp_atomctrl_mc_reg_table), GFP_KERNEL);
2525
2526         if (NULL == table)
2527                 return -ENOMEM;
2528
2529         /* Program additional LP registers that are no longer programmed by VBIOS */
2530         cgs_write_register(hwmgr->device, mmMC_SEQ_RAS_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RAS_TIMING));
2531         cgs_write_register(hwmgr->device, mmMC_SEQ_CAS_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_CAS_TIMING));
2532         cgs_write_register(hwmgr->device, mmMC_SEQ_DLL_STBY_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_DLL_STBY));
2533         cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD0));
2534         cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD1));
2535         cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CTRL_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CTRL));
2536         cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CMD_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CMD));
2537         cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CTL_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CTL));
2538         cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING));
2539         cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2));
2540         cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_EMRS_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_EMRS));
2541         cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS));
2542         cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS1_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS1));
2543         cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D0));
2544         cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1));
2545         cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0));
2546         cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1));
2547         cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_TIMING));
2548         cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS2_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS2));
2549         cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_2_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_2));
2550
2551         memset(table, 0x00, sizeof(pp_atomctrl_mc_reg_table));
2552
2553         result = atomctrl_initialize_mc_reg_table(hwmgr, module_index, table);
2554
2555         if (0 == result)
2556                 result = iceland_copy_vbios_smc_reg_table(table, ni_table);
2557
2558         if (0 == result) {
2559                 iceland_set_s0_mc_reg_index(ni_table);
2560                 result = iceland_set_mc_special_registers(hwmgr, ni_table);
2561         }
2562
2563         if (0 == result)
2564                 iceland_set_valid_flag(ni_table);
2565
2566         kfree(table);
2567
2568         return result;
2569 }
2570
2571 bool iceland_is_dpm_running(struct pp_hwmgr *hwmgr)
2572 {
2573         return (1 == PHM_READ_INDIRECT_FIELD(hwmgr->device,
2574                         CGS_IND_REG__SMC, FEATURE_STATUS, VOLTAGE_CONTROLLER_ON))
2575                         ? true : false;
2576 }