diff --git a/drivers/gpu/drm/amd/include/atombios.h b/drivers/gpu/drm/amd/include/atombios.h index 8ba21747b40a..e6548bb6cad2 100644 --- a/drivers/gpu/drm/amd/include/atombios.h +++ b/drivers/gpu/drm/amd/include/atombios.h @@ -5655,6 +5655,22 @@ typedef struct _ATOM_GFX_INFO_V2_1 UCHAR max_texture_channel_caches; }ATOM_GFX_INFO_V2_1; +typedef struct _ATOM_GFX_INFO_V2_3 +{ + ATOM_COMMON_TABLE_HEADER asHeader; + UCHAR GfxIpMinVer; + UCHAR GfxIpMajVer; + UCHAR max_shader_engines; + UCHAR max_tile_pipes; + UCHAR max_cu_per_sh; + UCHAR max_sh_per_se; + UCHAR max_backends_per_se; + UCHAR max_texture_channel_caches; + USHORT usHiLoLeakageThreshold; + USHORT usEdcDidtLoDpm7TableOffset; //offset of DPM7 low leakage table _ATOM_EDC_DIDT_TABLE_V1 + USHORT usEdcDidtHiDpm7TableOffset; //offset of DPM7 high leakage table _ATOM_EDC_DIDT_TABLE_V1 + USHORT usReserverd[3]; +}ATOM_GFX_INFO_V2_3; typedef struct _ATOM_POWER_SOURCE_OBJECT { diff --git a/drivers/gpu/drm/amd/pm/inc/smu7_ppsmc.h b/drivers/gpu/drm/amd/pm/inc/smu7_ppsmc.h index 0454ec990a5e..97302aae4b27 100644 --- a/drivers/gpu/drm/amd/pm/inc/smu7_ppsmc.h +++ b/drivers/gpu/drm/amd/pm/inc/smu7_ppsmc.h @@ -404,6 +404,9 @@ typedef uint16_t PPSMC_Result; #define PPSMC_MSG_EnableDpmDidt ((uint16_t) 0x309) #define PPSMC_MSG_DisableDpmDidt ((uint16_t) 0x30A) +#define PPSMC_MSG_EnableEDCController ((uint16_t) 0x316) +#define PPSMC_MSG_DisableEDCController ((uint16_t) 0x317) + #define PPSMC_MSG_SecureSRBMWrite ((uint16_t) 0x600) #define PPSMC_MSG_SecureSRBMRead ((uint16_t) 0x601) #define PPSMC_MSG_SetAddress ((uint16_t) 0x800) diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomctrl.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomctrl.c index 1bde79dd30c9..3aaf2d64cd98 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomctrl.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomctrl.c @@ -1566,3 +1566,56 @@ void atomctrl_get_voltage_range(struct pp_hwmgr *hwmgr, uint32_t *max_vddc, *max_vddc = 0; *min_vddc = 0; } + +int atomctrl_get_edc_hilo_leakage_offset_table(struct pp_hwmgr *hwmgr, + AtomCtrl_HiLoLeakageOffsetTable *table) +{ + ATOM_GFX_INFO_V2_3 *gfxinfo = smu_atom_get_data_table(hwmgr->adev, + GetIndexIntoMasterTable(DATA, GFX_Info), + NULL, NULL, NULL); + if (!gfxinfo) + return -ENOENT; + + table->usHiLoLeakageThreshold = gfxinfo->usHiLoLeakageThreshold; + table->usEdcDidtLoDpm7TableOffset = gfxinfo->usEdcDidtLoDpm7TableOffset; + table->usEdcDidtHiDpm7TableOffset = gfxinfo->usEdcDidtHiDpm7TableOffset; + + return 0; +} + +static AtomCtrl_EDCLeakgeTable *get_edc_leakage_table(struct pp_hwmgr *hwmgr, + uint16_t offset) +{ + void *table_address; + char *temp; + + table_address = smu_atom_get_data_table(hwmgr->adev, + GetIndexIntoMasterTable(DATA, GFX_Info), + NULL, NULL, NULL); + if (!table_address) + return NULL; + + temp = (char *)table_address; + table_address += offset; + + return (AtomCtrl_EDCLeakgeTable *)temp; +} + +int atomctrl_get_edc_leakage_table(struct pp_hwmgr *hwmgr, + AtomCtrl_EDCLeakgeTable *table, + uint16_t offset) +{ + uint32_t length, i; + AtomCtrl_EDCLeakgeTable *leakage_table = + get_edc_leakage_table(hwmgr, offset); + + if (!leakage_table) + return -ENOENT; + + length = sizeof(leakage_table->DIDT_REG) / + sizeof(leakage_table->DIDT_REG[0]); + for (i = 0; i < length; i++) + table->DIDT_REG[i] = leakage_table->DIDT_REG[i]; + + return 0; +} diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomctrl.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomctrl.h index ee14635dfadf..c6276ab073b7 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomctrl.h +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomctrl.h @@ -278,6 +278,20 @@ struct pp_atom_ctrl__avfs_parameters { uint8_t ucReserved; }; +struct _AtomCtrl_HiLoLeakageOffsetTable +{ + USHORT usHiLoLeakageThreshold; + USHORT usEdcDidtLoDpm7TableOffset; + USHORT usEdcDidtHiDpm7TableOffset; +}; +typedef struct _AtomCtrl_HiLoLeakageOffsetTable AtomCtrl_HiLoLeakageOffsetTable; + +struct _AtomCtrl_EDCLeakgeTable +{ + ULONG DIDT_REG[24]; +}; +typedef struct _AtomCtrl_EDCLeakgeTable AtomCtrl_EDCLeakgeTable; + extern bool atomctrl_get_pp_assign_pin(struct pp_hwmgr *hwmgr, const uint32_t pinId, pp_atomctrl_gpio_pin_assignment *gpio_pin_assignment); extern int atomctrl_get_voltage_evv_on_sclk(struct pp_hwmgr *hwmgr, uint8_t voltage_type, uint32_t sclk, uint16_t virtual_voltage_Id, uint16_t *voltage); extern int atomctrl_get_voltage_evv(struct pp_hwmgr *hwmgr, uint16_t virtual_voltage_id, uint16_t *voltage); @@ -324,5 +338,13 @@ extern int atomctrl_get_leakage_id_from_efuse(struct pp_hwmgr *hwmgr, uint16_t * extern void atomctrl_get_voltage_range(struct pp_hwmgr *hwmgr, uint32_t *max_vddc, uint32_t *min_vddc); + +extern int atomctrl_get_edc_hilo_leakage_offset_table(struct pp_hwmgr *hwmgr, + AtomCtrl_HiLoLeakageOffsetTable *table); + +extern int atomctrl_get_edc_leakage_table(struct pp_hwmgr *hwmgr, + AtomCtrl_EDCLeakgeTable *table, + uint16_t offset); + #endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c index b32dc0d6e880..27ca0e6b724f 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c @@ -109,6 +109,62 @@ enum DPM_EVENT_SRC { DPM_EVENT_SRC_DIGITAL_OR_EXTERNAL = 4 }; +#define ixDIDT_SQ_EDC_CTRL 0x0013 +#define ixDIDT_SQ_EDC_THRESHOLD 0x0014 +#define ixDIDT_SQ_EDC_STALL_PATTERN_1_2 0x0015 +#define ixDIDT_SQ_EDC_STALL_PATTERN_3_4 0x0016 +#define ixDIDT_SQ_EDC_STALL_PATTERN_5_6 0x0017 +#define ixDIDT_SQ_EDC_STALL_PATTERN_7 0x0018 + +#define ixDIDT_TD_EDC_CTRL 0x0053 +#define ixDIDT_TD_EDC_THRESHOLD 0x0054 +#define ixDIDT_TD_EDC_STALL_PATTERN_1_2 0x0055 +#define ixDIDT_TD_EDC_STALL_PATTERN_3_4 0x0056 +#define ixDIDT_TD_EDC_STALL_PATTERN_5_6 0x0057 +#define ixDIDT_TD_EDC_STALL_PATTERN_7 0x0058 + +#define ixDIDT_TCP_EDC_CTRL 0x0073 +#define ixDIDT_TCP_EDC_THRESHOLD 0x0074 +#define ixDIDT_TCP_EDC_STALL_PATTERN_1_2 0x0075 +#define ixDIDT_TCP_EDC_STALL_PATTERN_3_4 0x0076 +#define ixDIDT_TCP_EDC_STALL_PATTERN_5_6 0x0077 +#define ixDIDT_TCP_EDC_STALL_PATTERN_7 0x0078 + +#define ixDIDT_DB_EDC_CTRL 0x0033 +#define ixDIDT_DB_EDC_THRESHOLD 0x0034 +#define ixDIDT_DB_EDC_STALL_PATTERN_1_2 0x0035 +#define ixDIDT_DB_EDC_STALL_PATTERN_3_4 0x0036 +#define ixDIDT_DB_EDC_STALL_PATTERN_5_6 0x0037 +#define ixDIDT_DB_EDC_STALL_PATTERN_7 0x0038 + +uint32_t DIDTEDCConfig_P12[] = { + ixDIDT_SQ_EDC_STALL_PATTERN_1_2, + ixDIDT_SQ_EDC_STALL_PATTERN_3_4, + ixDIDT_SQ_EDC_STALL_PATTERN_5_6, + ixDIDT_SQ_EDC_STALL_PATTERN_7, + ixDIDT_SQ_EDC_THRESHOLD, + ixDIDT_SQ_EDC_CTRL, + ixDIDT_TD_EDC_STALL_PATTERN_1_2, + ixDIDT_TD_EDC_STALL_PATTERN_3_4, + ixDIDT_TD_EDC_STALL_PATTERN_5_6, + ixDIDT_TD_EDC_STALL_PATTERN_7, + ixDIDT_TD_EDC_THRESHOLD, + ixDIDT_TD_EDC_CTRL, + ixDIDT_TCP_EDC_STALL_PATTERN_1_2, + ixDIDT_TCP_EDC_STALL_PATTERN_3_4, + ixDIDT_TCP_EDC_STALL_PATTERN_5_6, + ixDIDT_TCP_EDC_STALL_PATTERN_7, + ixDIDT_TCP_EDC_THRESHOLD, + ixDIDT_TCP_EDC_CTRL, + ixDIDT_DB_EDC_STALL_PATTERN_1_2, + ixDIDT_DB_EDC_STALL_PATTERN_3_4, + ixDIDT_DB_EDC_STALL_PATTERN_5_6, + ixDIDT_DB_EDC_STALL_PATTERN_7, + ixDIDT_DB_EDC_THRESHOLD, + ixDIDT_DB_EDC_CTRL, + 0xFFFFFFFF // End of list +}; + static const unsigned long PhwVIslands_Magic = (unsigned long)(PHM_VIslands_Magic); static int smu7_force_clock_level(struct pp_hwmgr *hwmgr, enum pp_clock_type type, uint32_t mask); @@ -1334,6 +1390,50 @@ static int smu7_pcie_performance_request(struct pp_hwmgr *hwmgr) return 0; } +static int smu7_program_edc_didt_registers(struct pp_hwmgr *hwmgr, + uint32_t *cac_config_regs, + AtomCtrl_EDCLeakgeTable *edc_leakage_table) +{ + uint32_t data, i = 0; + + while (cac_config_regs[i] != 0xFFFFFFFF) { + data = edc_leakage_table->DIDT_REG[i]; + cgs_write_ind_register(hwmgr->device, + CGS_IND_REG__DIDT, + cac_config_regs[i], + data); + i++; + } + + return 0; +} + +static int smu7_populate_edc_leakage_registers(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + int ret = 0; + + if (!data->disable_edc_leakage_controller && + data->edc_hilo_leakage_offset_from_vbios.usEdcDidtLoDpm7TableOffset && + data->edc_hilo_leakage_offset_from_vbios.usEdcDidtHiDpm7TableOffset) { + ret = smu7_program_edc_didt_registers(hwmgr, + DIDTEDCConfig_P12, + &data->edc_leakage_table); + if (ret) + return ret; + + ret = smum_send_msg_to_smc(hwmgr, + (PPSMC_Msg)PPSMC_MSG_EnableEDCController, + NULL); + } else { + ret = smum_send_msg_to_smc(hwmgr, + (PPSMC_Msg)PPSMC_MSG_DisableEDCController, + NULL); + } + + return ret; +} + static int smu7_enable_dpm_tasks(struct pp_hwmgr *hwmgr) { int tmp_result = 0; @@ -1400,6 +1500,13 @@ static int smu7_enable_dpm_tasks(struct pp_hwmgr *hwmgr) smum_send_msg_to_smc(hwmgr, (PPSMC_Msg)PPSMC_NoDisplay, NULL); + if (hwmgr->chip_id >= CHIP_POLARIS10 && + hwmgr->chip_id <= CHIP_VEGAM) { + tmp_result = smu7_populate_edc_leakage_registers(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to populate edc leakage registers!", result = tmp_result); + } + tmp_result = smu7_enable_sclk_control(hwmgr); PP_ASSERT_WITH_CODE((0 == tmp_result), "Failed to enable SCLK control!", result = tmp_result); @@ -1697,6 +1804,13 @@ static void smu7_init_dpm_defaults(struct pp_hwmgr *hwmgr) if (adev->pg_flags & AMD_PG_SUPPORT_VCE) phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_VCEPowerGating); + + data->disable_edc_leakage_controller = true; + if (((adev->asic_type == CHIP_POLARIS10) && hwmgr->is_kicker) || + ((adev->asic_type == CHIP_POLARIS11) && hwmgr->is_kicker) || + (adev->asic_type == CHIP_POLARIS12) || + (adev->asic_type == CHIP_VEGAM)) + data->disable_edc_leakage_controller = false; } static int smu7_calculate_ro_range(struct pp_hwmgr *hwmgr) @@ -2611,6 +2725,42 @@ static int smu7_get_elb_voltages(struct pp_hwmgr *hwmgr) return 0; } +#define LEAKAGE_ID_MSB 463 +#define LEAKAGE_ID_LSB 454 + +static int smu7_update_edc_leakage_table(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t efuse; + uint16_t offset; + int ret = 0; + + if (data->disable_edc_leakage_controller) + return 0; + + ret = atomctrl_get_edc_hilo_leakage_offset_table(hwmgr, + &data->edc_hilo_leakage_offset_from_vbios); + if (ret) + return ret; + + if (data->edc_hilo_leakage_offset_from_vbios.usEdcDidtLoDpm7TableOffset && + data->edc_hilo_leakage_offset_from_vbios.usEdcDidtHiDpm7TableOffset) { + atomctrl_read_efuse(hwmgr, LEAKAGE_ID_LSB, LEAKAGE_ID_MSB, &efuse); + if (efuse < data->edc_hilo_leakage_offset_from_vbios.usHiLoLeakageThreshold) + offset = data->edc_hilo_leakage_offset_from_vbios.usEdcDidtLoDpm7TableOffset; + else + offset = data->edc_hilo_leakage_offset_from_vbios.usEdcDidtHiDpm7TableOffset; + + ret = atomctrl_get_edc_leakage_table(hwmgr, + &data->edc_leakage_table, + offset); + if (ret) + return ret; + } + + return ret; +} + static int smu7_hwmgr_backend_init(struct pp_hwmgr *hwmgr) { struct smu7_hwmgr *data; @@ -2672,6 +2822,10 @@ static int smu7_hwmgr_backend_init(struct pp_hwmgr *hwmgr) smu7_hwmgr_backend_fini(hwmgr); } + result = smu7_update_edc_leakage_table(hwmgr); + if (result) + return result; + return 0; } diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.h index b10e5bbffdf5..c1ed6fe587f3 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.h +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.h @@ -331,6 +331,10 @@ struct smu7_hwmgr { uint32_t ro_range_minimum; uint32_t ro_range_maximum; + + bool disable_edc_leakage_controller; + AtomCtrl_HiLoLeakageOffsetTable edc_hilo_leakage_offset_from_vbios; + AtomCtrl_EDCLeakgeTable edc_leakage_table; }; /* To convert to Q8.8 format for firmware */