aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/ellesmere_hwmgr.c51
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/ellesmere_hwmgr.h1
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr_ppt.h2
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/tonga_pptable.h14
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.c101
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/ellesmere_smumgr.c28
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/ellesmere_smumgr.h2
7 files changed, 162 insertions, 37 deletions
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/ellesmere_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/ellesmere_hwmgr.c
index 62f0f36cd673..043aefa44c0b 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/ellesmere_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/ellesmere_hwmgr.c
@@ -222,6 +222,22 @@ void phm_apply_dal_min_voltage_request(struct pp_hwmgr *hwmgr)
222 " found a available voltage in VDDC DPM Table \n"); 222 " found a available voltage in VDDC DPM Table \n");
223} 223}
224 224
225/**
226* Enable voltage control
227*
228* @param pHwMgr the address of the powerplay hardware manager.
229* @return always PP_Result_OK
230*/
231int ellesmere_enable_smc_voltage_controller(struct pp_hwmgr *hwmgr)
232{
233 PP_ASSERT_WITH_CODE(
234 (hwmgr->smumgr->smumgr_funcs->send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_Voltage_Cntl_Enable) == 0),
235 "Failed to enable voltage DPM during DPM Start Function!",
236 return 1;
237 );
238
239 return 0;
240}
225 241
226/** 242/**
227* Checks if we want to support voltage control 243* Checks if we want to support voltage control
@@ -586,6 +602,10 @@ static int ellesmere_setup_default_pcie_table(struct pp_hwmgr *hwmgr)
586 pcie_table->entries[i].lane_width)); 602 pcie_table->entries[i].lane_width));
587 } 603 }
588 data->dpm_table.pcie_speed_table.count = max_entry - 1; 604 data->dpm_table.pcie_speed_table.count = max_entry - 1;
605
606 /* Setup BIF_SCLK levels */
607 for (i = 0; i < max_entry; i++)
608 data->bif_sclk_table[i] = pcie_table->entries[i].pcie_sclk;
589 } else { 609 } else {
590 /* Hardcode Pcie Table */ 610 /* Hardcode Pcie Table */
591 phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 0, 611 phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 0,
@@ -938,9 +958,13 @@ static int ellesmere_calculate_sclk_params(struct pp_hwmgr *hwmgr,
938 sclk_setting->Fcw_frac = dividers.usSclk_fcw_frac; 958 sclk_setting->Fcw_frac = dividers.usSclk_fcw_frac;
939 sclk_setting->Pcc_fcw_int = dividers.usPcc_fcw_int; 959 sclk_setting->Pcc_fcw_int = dividers.usPcc_fcw_int;
940 sclk_setting->PllRange = dividers.ucSclkPllRange; 960 sclk_setting->PllRange = dividers.ucSclkPllRange;
961 sclk_setting->Sclk_slew_rate = 0x400;
962 sclk_setting->Pcc_up_slew_rate = dividers.usPcc_fcw_slew_frac;
963 sclk_setting->Pcc_down_slew_rate = 0xffff;
941 sclk_setting->SSc_En = dividers.ucSscEnable; 964 sclk_setting->SSc_En = dividers.ucSscEnable;
942 sclk_setting->Fcw1_int = dividers.usSsc_fcw1_int; 965 sclk_setting->Fcw1_int = dividers.usSsc_fcw1_int;
943 sclk_setting->Fcw1_frac = dividers.usSsc_fcw1_frac; 966 sclk_setting->Fcw1_frac = dividers.usSsc_fcw1_frac;
967 sclk_setting->Sclk_ss_slew_rate = dividers.usSsc_fcw_slew_frac;
944 return result; 968 return result;
945 } 969 }
946 970
@@ -1174,8 +1198,12 @@ static int ellesmere_populate_single_graphic_level(struct pp_hwmgr *hwmgr,
1174 CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Fcw_int); 1198 CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Fcw_int);
1175 CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Fcw_frac); 1199 CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Fcw_frac);
1176 CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Pcc_fcw_int); 1200 CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Pcc_fcw_int);
1201 CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Sclk_slew_rate);
1202 CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Pcc_up_slew_rate);
1203 CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Pcc_down_slew_rate);
1177 CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Fcw1_int); 1204 CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Fcw1_int);
1178 CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Fcw1_frac); 1205 CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Fcw1_frac);
1206 CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Sclk_ss_slew_rate);
1179 return 0; 1207 return 0;
1180} 1208}
1181 1209
@@ -1458,8 +1486,12 @@ static int ellesmere_populate_smc_acpi_level(struct pp_hwmgr *hwmgr,
1458 CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Fcw_int); 1486 CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Fcw_int);
1459 CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Fcw_frac); 1487 CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Fcw_frac);
1460 CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Pcc_fcw_int); 1488 CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Pcc_fcw_int);
1489 CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Sclk_slew_rate);
1490 CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Pcc_up_slew_rate);
1491 CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Pcc_down_slew_rate);
1461 CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Fcw1_int); 1492 CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Fcw1_int);
1462 CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Fcw1_frac); 1493 CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Fcw1_frac);
1494 CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Sclk_ss_slew_rate);
1463 1495
1464 if (!data->mclk_dpm_key_disabled) { 1496 if (!data->mclk_dpm_key_disabled) {
1465 /* Get MinVoltage and Frequency from DPM0, already converted to SMC_UL */ 1497 /* Get MinVoltage and Frequency from DPM0, already converted to SMC_UL */
@@ -1966,6 +1998,7 @@ static int ellesmere_init_smc_table(struct pp_hwmgr *hwmgr)
1966 const struct ellesmere_ulv_parm *ulv = &(data->ulv); 1998 const struct ellesmere_ulv_parm *ulv = &(data->ulv);
1967 uint8_t i; 1999 uint8_t i;
1968 struct pp_atomctrl_gpio_pin_assignment gpio_pin; 2000 struct pp_atomctrl_gpio_pin_assignment gpio_pin;
2001 pp_atomctrl_clock_dividers_vi dividers;
1969 2002
1970 result = ellesmere_setup_default_dpm_tables(hwmgr); 2003 result = ellesmere_setup_default_dpm_tables(hwmgr);
1971 PP_ASSERT_WITH_CODE(0 == result, 2004 PP_ASSERT_WITH_CODE(0 == result,
@@ -2121,6 +2154,17 @@ static int ellesmere_init_smc_table(struct pp_hwmgr *hwmgr)
2121 table->ThermOutMode = SMU7_THERM_OUT_MODE_DISABLE; 2154 table->ThermOutMode = SMU7_THERM_OUT_MODE_DISABLE;
2122 } 2155 }
2123 2156
2157 /* Populate BIF_SCLK levels into SMC DPM table */
2158 for (i = 0; i <= data->dpm_table.pcie_speed_table.count; i++) {
2159 result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, data->bif_sclk_table[i], &dividers);
2160 PP_ASSERT_WITH_CODE((result == 0), "Can not find DFS divide id for Sclk", return result);
2161
2162 if (i == 0)
2163 table->Ulv.BifSclkDfs = PP_HOST_TO_SMC_US((USHORT)(dividers.pll_post_divider));
2164 else
2165 table->LinkLevel[i-1].BifSclkDfs = PP_HOST_TO_SMC_US((USHORT)(dividers.pll_post_divider));
2166 }
2167
2124 for (i = 0; i < SMU74_MAX_ENTRIES_SMIO; i++) 2168 for (i = 0; i < SMU74_MAX_ENTRIES_SMIO; i++)
2125 table->Smio[i] = PP_HOST_TO_SMC_UL(table->Smio[i]); 2169 table->Smio[i] = PP_HOST_TO_SMC_UL(table->Smio[i]);
2126 2170
@@ -2284,12 +2328,13 @@ static int ellesmere_start_dpm(struct pp_hwmgr *hwmgr)
2284 VoltageChangeTimeout), 0x1000); 2328 VoltageChangeTimeout), 0x1000);
2285 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__PCIE, 2329 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__PCIE,
2286 SWRST_COMMAND_1, RESETLC, 0x0); 2330 SWRST_COMMAND_1, RESETLC, 0x0);
2287 2331/*
2288 PP_ASSERT_WITH_CODE( 2332 PP_ASSERT_WITH_CODE(
2289 (0 == smum_send_msg_to_smc(hwmgr->smumgr, 2333 (0 == smum_send_msg_to_smc(hwmgr->smumgr,
2290 PPSMC_MSG_Voltage_Cntl_Enable)), 2334 PPSMC_MSG_Voltage_Cntl_Enable)),
2291 "Failed to enable voltage DPM during DPM Start Function!", 2335 "Failed to enable voltage DPM during DPM Start Function!",
2292 return -1); 2336 return -1);
2337*/
2293 2338
2294 if (ellesmere_enable_sclk_mclk_dpm(hwmgr)) { 2339 if (ellesmere_enable_sclk_mclk_dpm(hwmgr)) {
2295 printk(KERN_ERR "Failed to enable Sclk DPM and Mclk DPM!"); 2340 printk(KERN_ERR "Failed to enable Sclk DPM and Mclk DPM!");
@@ -2450,6 +2495,10 @@ int ellesmere_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
2450 PP_ASSERT_WITH_CODE((0 == tmp_result), 2495 PP_ASSERT_WITH_CODE((0 == tmp_result),
2451 "Failed to enable SCLK control!", result = tmp_result); 2496 "Failed to enable SCLK control!", result = tmp_result);
2452 2497
2498 tmp_result = ellesmere_enable_smc_voltage_controller(hwmgr);
2499 PP_ASSERT_WITH_CODE((0 == tmp_result),
2500 "Failed to enable voltage control!", result = tmp_result);
2501
2453 tmp_result = ellesmere_enable_ulv(hwmgr); 2502 tmp_result = ellesmere_enable_ulv(hwmgr);
2454 PP_ASSERT_WITH_CODE((0 == tmp_result), 2503 PP_ASSERT_WITH_CODE((0 == tmp_result),
2455 "Failed to enable ULV!", result = tmp_result); 2504 "Failed to enable ULV!", result = tmp_result);
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/ellesmere_hwmgr.h b/drivers/gpu/drm/amd/powerplay/hwmgr/ellesmere_hwmgr.h
index 7f9025256d08..dd6c60bb7513 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/ellesmere_hwmgr.h
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/ellesmere_hwmgr.h
@@ -274,6 +274,7 @@ struct ellesmere_hwmgr {
274 274
275 /* ---- DI/DT ---- */ 275 /* ---- DI/DT ---- */
276 struct ellesmere_display_timing display_timing; 276 struct ellesmere_display_timing display_timing;
277 uint32_t bif_sclk_table[SMU74_MAX_LEVELS_LINK];
277 278
278 /* ---- Thermal Temperature Setting ---- */ 279 /* ---- Thermal Temperature Setting ---- */
279 struct ellesmere_dpmlevel_enable_mask dpm_level_enable_mask; 280 struct ellesmere_dpmlevel_enable_mask dpm_level_enable_mask;
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr_ppt.h b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr_ppt.h
index c9e6c2d80ea6..347fef127ce9 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr_ppt.h
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr_ppt.h
@@ -92,6 +92,8 @@ typedef struct phm_ppt_v1_voltage_lookup_table phm_ppt_v1_voltage_lookup_table;
92struct phm_ppt_v1_pcie_record { 92struct phm_ppt_v1_pcie_record {
93 uint8_t gen_speed; 93 uint8_t gen_speed;
94 uint8_t lane_width; 94 uint8_t lane_width;
95 uint16_t usreserved;
96 uint32_t pcie_sclk;
95}; 97};
96typedef struct phm_ppt_v1_pcie_record phm_ppt_v1_pcie_record; 98typedef struct phm_ppt_v1_pcie_record phm_ppt_v1_pcie_record;
97 99
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_pptable.h b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_pptable.h
index 9a4456e6521b..a2c87ae20fb0 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_pptable.h
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_pptable.h
@@ -209,6 +209,20 @@ typedef struct _ATOM_Tonga_PCIE_Table {
209 ATOM_Tonga_PCIE_Record entries[1]; /* Dynamically allocate entries. */ 209 ATOM_Tonga_PCIE_Record entries[1]; /* Dynamically allocate entries. */
210} ATOM_Tonga_PCIE_Table; 210} ATOM_Tonga_PCIE_Table;
211 211
212typedef struct _ATOM_Ellesmere_PCIE_Record {
213 UCHAR ucPCIEGenSpeed;
214 UCHAR usPCIELaneWidth;
215 UCHAR ucReserved[2];
216 ULONG ulPCIE_Sclk;
217} ATOM_Ellesmere_PCIE_Record;
218
219typedef struct _ATOM_Ellesmere_PCIE_Table {
220 UCHAR ucRevId;
221 UCHAR ucNumEntries; /* Number of entries. */
222 ATOM_Ellesmere_PCIE_Record entries[1]; /* Dynamically allocate entries. */
223} ATOM_Ellesmere_PCIE_Table;
224
225
212typedef struct _ATOM_Tonga_MM_Dependency_Record { 226typedef struct _ATOM_Tonga_MM_Dependency_Record {
213 UCHAR ucVddcInd; /* VDDC voltage */ 227 UCHAR ucVddcInd; /* VDDC voltage */
214 USHORT usVddgfxOffset; /* Offset relative to VDDC voltage */ 228 USHORT usVddgfxOffset; /* Offset relative to VDDC voltage */
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.c b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.c
index b156481b50e8..ecbc43f170bf 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.c
@@ -448,47 +448,90 @@ static int get_sclk_voltage_dependency_table(
448static int get_pcie_table( 448static int get_pcie_table(
449 struct pp_hwmgr *hwmgr, 449 struct pp_hwmgr *hwmgr,
450 phm_ppt_v1_pcie_table **pp_tonga_pcie_table, 450 phm_ppt_v1_pcie_table **pp_tonga_pcie_table,
451 const ATOM_Tonga_PCIE_Table * atom_pcie_table 451 const PPTable_Generic_SubTable_Header * pTable
452 ) 452 )
453{ 453{
454 uint32_t table_size, i, pcie_count; 454 uint32_t table_size, i, pcie_count;
455 phm_ppt_v1_pcie_table *pcie_table; 455 phm_ppt_v1_pcie_table *pcie_table;
456 struct phm_ppt_v1_information *pp_table_information = 456 struct phm_ppt_v1_information *pp_table_information =
457 (struct phm_ppt_v1_information *)(hwmgr->pptable); 457 (struct phm_ppt_v1_information *)(hwmgr->pptable);
458 PP_ASSERT_WITH_CODE((0 != atom_pcie_table->ucNumEntries),
459 "Invalid PowerPlay Table!", return -1);
460 458
461 table_size = sizeof(uint32_t) + 459 if (pTable->ucRevId < 1) {
462 sizeof(phm_ppt_v1_pcie_record) * atom_pcie_table->ucNumEntries; 460 const ATOM_Tonga_PCIE_Table *atom_pcie_table = (ATOM_Tonga_PCIE_Table *)pTable;
461 PP_ASSERT_WITH_CODE((atom_pcie_table->ucNumEntries != 0),
462 "Invalid PowerPlay Table!", return -1);
463 463
464 pcie_table = (phm_ppt_v1_pcie_table *)kzalloc(table_size, GFP_KERNEL); 464 table_size = sizeof(uint32_t) +
465 sizeof(phm_ppt_v1_pcie_record) * atom_pcie_table->ucNumEntries;
465 466
466 if (NULL == pcie_table) 467 pcie_table = (phm_ppt_v1_pcie_table *)kzalloc(table_size, GFP_KERNEL);
467 return -ENOMEM;
468 468
469 memset(pcie_table, 0x00, table_size); 469 if (pcie_table == NULL)
470 return -ENOMEM;
470 471
471 /* 472 memset(pcie_table, 0x00, table_size);
472 * Make sure the number of pcie entries are less than or equal to sclk dpm levels.
473 * Since first PCIE entry is for ULV, #pcie has to be <= SclkLevel + 1.
474 */
475 pcie_count = (pp_table_information->vdd_dep_on_sclk->count) + 1;
476 if ((uint32_t)atom_pcie_table->ucNumEntries <= pcie_count)
477 pcie_count = (uint32_t)atom_pcie_table->ucNumEntries;
478 else
479 printk(KERN_ERR "[ powerplay ] Number of Pcie Entries exceed the number of SCLK Dpm Levels! \
480 Disregarding the excess entries... \n");
481 473
482 pcie_table->count = pcie_count; 474 /*
475 * Make sure the number of pcie entries are less than or equal to sclk dpm levels.
476 * Since first PCIE entry is for ULV, #pcie has to be <= SclkLevel + 1.
477 */
478 pcie_count = (pp_table_information->vdd_dep_on_sclk->count) + 1;
479 if ((uint32_t)atom_pcie_table->ucNumEntries <= pcie_count)
480 pcie_count = (uint32_t)atom_pcie_table->ucNumEntries;
481 else
482 printk(KERN_ERR "[ powerplay ] Number of Pcie Entries exceed the number of SCLK Dpm Levels! \
483 Disregarding the excess entries... \n");
483 484
484 for (i = 0; i < pcie_count; i++) { 485 pcie_table->count = pcie_count;
485 pcie_table->entries[i].gen_speed = 486
486 atom_pcie_table->entries[i].ucPCIEGenSpeed; 487 for (i = 0; i < pcie_count; i++) {
487 pcie_table->entries[i].lane_width = 488 pcie_table->entries[i].gen_speed =
488 atom_pcie_table->entries[i].usPCIELaneWidth; 489 atom_pcie_table->entries[i].ucPCIEGenSpeed;
489 } 490 pcie_table->entries[i].lane_width =
491 atom_pcie_table->entries[i].usPCIELaneWidth;
492 }
493
494 *pp_tonga_pcie_table = pcie_table;
495 } else {
496 /* Ellesmere/Baffin and newer. */
497 const ATOM_Ellesmere_PCIE_Table *atom_pcie_table = (ATOM_Ellesmere_PCIE_Table *)pTable;
498 PP_ASSERT_WITH_CODE((atom_pcie_table->ucNumEntries != 0),
499 "Invalid PowerPlay Table!", return -1);
500
501 table_size = sizeof(uint32_t) +
502 sizeof(phm_ppt_v1_pcie_record) * atom_pcie_table->ucNumEntries;
503
504 pcie_table = (phm_ppt_v1_pcie_table *)kzalloc(table_size, GFP_KERNEL);
505
506 if (pcie_table == NULL)
507 return -ENOMEM;
508
509 memset(pcie_table, 0x00, table_size);
510
511 /*
512 * Make sure the number of pcie entries are less than or equal to sclk dpm levels.
513 * Since first PCIE entry is for ULV, #pcie has to be <= SclkLevel + 1.
514 */
515 pcie_count = (pp_table_information->vdd_dep_on_sclk->count) + 1;
516 if ((uint32_t)atom_pcie_table->ucNumEntries <= pcie_count)
517 pcie_count = (uint32_t)atom_pcie_table->ucNumEntries;
518 else
519 printk(KERN_ERR "[ powerplay ] Number of Pcie Entries exceed the number of SCLK Dpm Levels! \
520 Disregarding the excess entries... \n");
521
522 pcie_table->count = pcie_count;
523
524 for (i = 0; i < pcie_count; i++) {
525 pcie_table->entries[i].gen_speed =
526 atom_pcie_table->entries[i].ucPCIEGenSpeed;
527 pcie_table->entries[i].lane_width =
528 atom_pcie_table->entries[i].usPCIELaneWidth;
529 pcie_table->entries[i].pcie_sclk =
530 atom_pcie_table->entries[i].ulPCIE_Sclk;
531 }
490 532
491 *pp_tonga_pcie_table = pcie_table; 533 *pp_tonga_pcie_table = pcie_table;
534 }
492 535
493 return 0; 536 return 0;
494} 537}
@@ -668,8 +711,8 @@ static int init_clock_voltage_dependency(
668 const ATOM_Tonga_Hard_Limit_Table *pHardLimits = 711 const ATOM_Tonga_Hard_Limit_Table *pHardLimits =
669 (const ATOM_Tonga_Hard_Limit_Table *)(((unsigned long) powerplay_table) + 712 (const ATOM_Tonga_Hard_Limit_Table *)(((unsigned long) powerplay_table) +
670 le16_to_cpu(powerplay_table->usHardLimitTableOffset)); 713 le16_to_cpu(powerplay_table->usHardLimitTableOffset));
671 const ATOM_Tonga_PCIE_Table *pcie_table = 714 const PPTable_Generic_SubTable_Header *pcie_table =
672 (const ATOM_Tonga_PCIE_Table *)(((unsigned long) powerplay_table) + 715 (const PPTable_Generic_SubTable_Header *)(((unsigned long) powerplay_table) +
673 le16_to_cpu(powerplay_table->usPCIETableOffset)); 716 le16_to_cpu(powerplay_table->usPCIETableOffset));
674 717
675 pp_table_information->vdd_dep_on_sclk = NULL; 718 pp_table_information->vdd_dep_on_sclk = NULL;
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/ellesmere_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/ellesmere_smumgr.c
index f57ba123cadb..6395065a6e19 100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/ellesmere_smumgr.c
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/ellesmere_smumgr.c
@@ -345,7 +345,6 @@ static int ellesmere_upload_smc_firmware_data(struct pp_smumgr *smumgr, uint32_t
345 cgs_write_register(smumgr->device, mmSMC_IND_INDEX_11, 0x20000); 345 cgs_write_register(smumgr->device, mmSMC_IND_INDEX_11, 0x20000);
346 SMUM_WRITE_FIELD(smumgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_11, 1); 346 SMUM_WRITE_FIELD(smumgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_11, 1);
347 347
348
349 for (; byte_count >= 4; byte_count -= 4) 348 for (; byte_count >= 4; byte_count -= 4)
350 cgs_write_register(smumgr->device, mmSMC_IND_DATA_11, *src++); 349 cgs_write_register(smumgr->device, mmSMC_IND_DATA_11, *src++);
351 350
@@ -364,6 +363,9 @@ static enum cgs_ucode_id ellesmere_convert_fw_type_to_cgs(uint32_t fw_type)
364 case UCODE_ID_SMU: 363 case UCODE_ID_SMU:
365 result = CGS_UCODE_ID_SMU; 364 result = CGS_UCODE_ID_SMU;
366 break; 365 break;
366 case UCODE_ID_SMU_SK:
367 result = CGS_UCODE_ID_SMU_SK;
368 break;
367 case UCODE_ID_SDMA0: 369 case UCODE_ID_SDMA0:
368 result = CGS_UCODE_ID_SDMA0; 370 result = CGS_UCODE_ID_SDMA0;
369 break; 371 break;
@@ -401,14 +403,18 @@ static enum cgs_ucode_id ellesmere_convert_fw_type_to_cgs(uint32_t fw_type)
401static int ellesmere_upload_smu_firmware_image(struct pp_smumgr *smumgr) 403static int ellesmere_upload_smu_firmware_image(struct pp_smumgr *smumgr)
402{ 404{
403 int result = 0; 405 int result = 0;
406 struct ellesmere_smumgr *smu_data = (struct ellesmere_smumgr *)(smumgr->backend);
404 407
405 struct cgs_firmware_info info = {0}; 408 struct cgs_firmware_info info = {0};
406 409
407 cgs_get_firmware_info(smumgr->device, 410 if (smu_data->security_hard_key == 1)
411 cgs_get_firmware_info(smumgr->device,
408 ellesmere_convert_fw_type_to_cgs(UCODE_ID_SMU), &info); 412 ellesmere_convert_fw_type_to_cgs(UCODE_ID_SMU), &info);
413 else
414 cgs_get_firmware_info(smumgr->device,
415 ellesmere_convert_fw_type_to_cgs(UCODE_ID_SMU_SK), &info);
409 416
410 /* TO DO cgs_init_samu_load_smu(smumgr->device, (uint32_t *)info.kptr, info.image_size, smu_data->post_initial_boot);*/ 417 /* TO DO cgs_init_samu_load_smu(smumgr->device, (uint32_t *)info.kptr, info.image_size, smu_data->post_initial_boot);*/
411
412 result = ellesmere_upload_smc_firmware_data(smumgr, info.image_size, (uint32_t *)info.kptr, ELLESMERE_SMC_SIZE); 418 result = ellesmere_upload_smc_firmware_data(smumgr, info.image_size, (uint32_t *)info.kptr, ELLESMERE_SMC_SIZE);
413 419
414 return result; 420 return result;
@@ -798,13 +804,11 @@ static int ellesmere_start_smu_in_protection_mode(struct pp_smumgr *smumgr)
798 SMU_STATUS, SMU_PASS)) 804 SMU_STATUS, SMU_PASS))
799 PP_ASSERT_WITH_CODE(false, "SMU Firmware start failed!", return -1); 805 PP_ASSERT_WITH_CODE(false, "SMU Firmware start failed!", return -1);
800 806
801
802 cgs_write_ind_register(smumgr->device, CGS_IND_REG__SMC, ixFIRMWARE_FLAGS, 0); 807 cgs_write_ind_register(smumgr->device, CGS_IND_REG__SMC, ixFIRMWARE_FLAGS, 0);
803 808
804 SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, 809 SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC,
805 SMC_SYSCON_RESET_CNTL, rst_reg, 1); 810 SMC_SYSCON_RESET_CNTL, rst_reg, 1);
806 811
807
808 SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, 812 SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC,
809 SMC_SYSCON_RESET_CNTL, rst_reg, 0); 813 SMC_SYSCON_RESET_CNTL, rst_reg, 0);
810 814
@@ -860,12 +864,22 @@ static int ellesmere_start_smu(struct pp_smumgr *smumgr)
860 /* Only start SMC if SMC RAM is not running */ 864 /* Only start SMC if SMC RAM is not running */
861 if (!ellesmere_is_smc_ram_running(smumgr)) { 865 if (!ellesmere_is_smc_ram_running(smumgr)) {
862 SMU_VFT_INTACT = false; 866 SMU_VFT_INTACT = false;
867 smu_data->protected_mode = (uint8_t) (SMUM_READ_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, SMU_FIRMWARE, SMU_MODE));
868 smu_data->security_hard_key = (uint8_t) (SMUM_READ_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, SMU_FIRMWARE, SMU_SEL));
869
863 /* Check if SMU is running in protected mode */ 870 /* Check if SMU is running in protected mode */
864 if (0 == SMUM_READ_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, SMU_FIRMWARE, SMU_MODE)) 871 if (smu_data->protected_mode == 0) {
865 result = ellesmere_start_smu_in_non_protection_mode(smumgr); 872 result = ellesmere_start_smu_in_non_protection_mode(smumgr);
866 else 873 } else {
867 result = ellesmere_start_smu_in_protection_mode(smumgr); 874 result = ellesmere_start_smu_in_protection_mode(smumgr);
868 875
876 /* If failed, try with different security Key. */
877 if (result != 0) {
878 smu_data->security_hard_key ^= 1;
879 result = ellesmere_start_smu_in_protection_mode(smumgr);
880 }
881 }
882
869 if (result != 0) 883 if (result != 0)
870 PP_ASSERT_WITH_CODE(0, "Failed to load SMU ucode.", return result); 884 PP_ASSERT_WITH_CODE(0, "Failed to load SMU ucode.", return result);
871 885
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/ellesmere_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/ellesmere_smumgr.h
index 3712b3278b68..05d636a8e5c9 100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/ellesmere_smumgr.h
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/ellesmere_smumgr.h
@@ -51,6 +51,8 @@ struct ellesmere_smumgr {
51 uint32_t read_drm_straps_mc_address_low; 51 uint32_t read_drm_straps_mc_address_low;
52 uint32_t acpi_optimization; 52 uint32_t acpi_optimization;
53 bool post_initial_boot; 53 bool post_initial_boot;
54 uint8_t protected_mode;
55 uint8_t security_hard_key;
54 struct ellesmere_avfs avfs; 56 struct ellesmere_avfs avfs;
55}; 57};
56 58