[PATCH 19/40] drm/amd/pm: add edc leakage controller setting

Evan Quan evan.quan at amd.com
Fri Oct 16 03:26:31 UTC 2020


Enable edc controller table setting.

Change-Id: I38a1873b94f95c3ea8cfdca626bea3f30657bc31
Signed-off-by: Evan Quan <evan.quan at amd.com>
Acked-by: Alex Deucher <alexander.deucher at amd.com>
---
 drivers/gpu/drm/amd/include/atombios.h        |  16 ++
 drivers/gpu/drm/amd/pm/inc/smu7_ppsmc.h       |   3 +
 .../drm/amd/pm/powerplay/hwmgr/ppatomctrl.c   |  53 ++++++
 .../drm/amd/pm/powerplay/hwmgr/ppatomctrl.h   |  22 +++
 .../drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c   | 154 ++++++++++++++++++
 .../drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.h   |   4 +
 6 files changed, 252 insertions(+)

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 */
-- 
2.28.0



More information about the amd-gfx mailing list