diff options
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 | */ | ||
231 | int 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], ÷rs); | ||
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; | |||
92 | struct phm_ppt_v1_pcie_record { | 92 | struct 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 | }; |
96 | typedef struct phm_ppt_v1_pcie_record phm_ppt_v1_pcie_record; | 98 | typedef 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 | ||
212 | typedef 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 | |||
219 | typedef 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 | |||
212 | typedef struct _ATOM_Tonga_MM_Dependency_Record { | 226 | typedef 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( | |||
448 | static int get_pcie_table( | 448 | static 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) | |||
401 | static int ellesmere_upload_smu_firmware_image(struct pp_smumgr *smumgr) | 403 | static 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 | ||