Commit 8f0804c6 authored by Evan Quan's avatar Evan Quan Committed by Alex Deucher
Browse files

drm/amd/pm: add edc leakage controller setting



Enable edc controller table setting.

Signed-off-by: default avatarEvan Quan <evan.quan@amd.com>
Acked-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 9610a3bf
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -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
{
+3 −0
Original line number Diff line number Diff line
@@ -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)
+53 −0
Original line number Diff line number Diff line
@@ -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;
}
+22 −0
Original line number Diff line number Diff line
@@ -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
+154 −0
Original line number Diff line number Diff line
@@ -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;
}

Loading