Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 636e2582 authored by Alex Deucher's avatar Alex Deucher
Browse files

drm/radeon/dpm: add support for SVI2 voltage for SI



Some newer boards use SVI2 for voltage control rather
than GPIO.

Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent a91576d7
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -317,6 +317,9 @@ int radeon_atom_get_voltage_table(struct radeon_device *rdev,
				  struct atom_voltage_table *voltage_table);
bool radeon_atom_is_voltage_gpio(struct radeon_device *rdev,
				 u8 voltage_type, u8 voltage_mode);
int radeon_atom_get_svi2_info(struct radeon_device *rdev,
			      u8 voltage_type,
			      u8 *svd_gpio_id, u8 *svc_gpio_id);
void radeon_atom_update_memory_dll(struct radeon_device *rdev,
				   u32 mem_clock);
void radeon_atom_set_ac_timing(struct radeon_device *rdev,
+44 −0
Original line number Diff line number Diff line
@@ -3397,6 +3397,50 @@ radeon_atom_is_voltage_gpio(struct radeon_device *rdev,
	return false;
}

int radeon_atom_get_svi2_info(struct radeon_device *rdev,
			      u8 voltage_type,
			      u8 *svd_gpio_id, u8 *svc_gpio_id)
{
	int index = GetIndexIntoMasterTable(DATA, VoltageObjectInfo);
	u8 frev, crev;
	u16 data_offset, size;
	union voltage_object_info *voltage_info;
	union voltage_object *voltage_object = NULL;

	if (atom_parse_data_header(rdev->mode_info.atom_context, index, &size,
				   &frev, &crev, &data_offset)) {
		voltage_info = (union voltage_object_info *)
			(rdev->mode_info.atom_context->bios + data_offset);

		switch (frev) {
		case 3:
			switch (crev) {
			case 1:
				voltage_object = (union voltage_object *)
					atom_lookup_voltage_object_v3(&voltage_info->v3,
								      voltage_type,
								      VOLTAGE_OBJ_SVID2);
				if (voltage_object) {
					*svd_gpio_id = voltage_object->v3.asSVID2Obj.ucSVDGpioId;
					*svc_gpio_id = voltage_object->v3.asSVID2Obj.ucSVCGpioId;
				} else {
					return -EINVAL;
				}
				break;
			default:
				DRM_ERROR("unknown voltage object table\n");
				return -EINVAL;
			}
			break;
		default:
			DRM_ERROR("unknown voltage object table\n");
			return -EINVAL;
		}

	}
	return 0;
}

int radeon_atom_get_max_voltage(struct radeon_device *rdev,
				u8 voltage_type, u16 *max_voltage)
{
+108 −44
Original line number Diff line number Diff line
@@ -3812,6 +3812,27 @@ void si_trim_voltage_table_to_fit_state_table(struct radeon_device *rdev,
	voltage_table->count = max_voltage_steps;
}

static int si_get_svi2_voltage_table(struct radeon_device *rdev,
				     struct radeon_clock_voltage_dependency_table *voltage_dependency_table,
				     struct atom_voltage_table *voltage_table)
{
	u32 i;

	if (voltage_dependency_table == NULL)
		return -EINVAL;

	voltage_table->mask_low = 0;
	voltage_table->phase_delay = 0;

	voltage_table->count = voltage_dependency_table->count;
	for (i = 0; i < voltage_table->count; i++) {
		voltage_table->entries[i].value = voltage_dependency_table->entries[i].v;
		voltage_table->entries[i].smio_low = 0;
	}

	return 0;
}

static int si_construct_voltage_tables(struct radeon_device *rdev)
{
	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
@@ -3819,6 +3840,7 @@ static int si_construct_voltage_tables(struct radeon_device *rdev)
	struct si_power_info *si_pi = si_get_pi(rdev);
	int ret;

	if (pi->voltage_control) {
		ret = radeon_atom_get_voltage_table(rdev, VOLTAGE_TYPE_VDDC,
						    VOLTAGE_OBJ_GPIO_LUT, &eg_pi->vddc_voltage_table);
		if (ret)
@@ -3828,6 +3850,15 @@ static int si_construct_voltage_tables(struct radeon_device *rdev)
			si_trim_voltage_table_to_fit_state_table(rdev,
								 SISLANDS_MAX_NO_VREG_STEPS,
								 &eg_pi->vddc_voltage_table);
	} else if (si_pi->voltage_control_svi2) {
		ret = si_get_svi2_voltage_table(rdev,
						&rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk,
						&eg_pi->vddc_voltage_table);
		if (ret)
			return ret;
	} else {
		return -EINVAL;
	}

	if (eg_pi->vddci_control) {
		ret = radeon_atom_get_voltage_table(rdev, VOLTAGE_TYPE_VDDCI,
@@ -3840,6 +3871,13 @@ static int si_construct_voltage_tables(struct radeon_device *rdev)
								 SISLANDS_MAX_NO_VREG_STEPS,
								 &eg_pi->vddci_voltage_table);
	}
	if (si_pi->vddci_control_svi2) {
		ret = si_get_svi2_voltage_table(rdev,
						&rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk,
						&eg_pi->vddci_voltage_table);
		if (ret)
			return ret;
	}

	if (pi->mvdd_control) {
		ret = radeon_atom_get_voltage_table(rdev, VOLTAGE_TYPE_MVDDC,
@@ -3893,6 +3931,14 @@ static int si_populate_smc_voltage_tables(struct radeon_device *rdev,
	struct si_power_info *si_pi = si_get_pi(rdev);
	u8 i;

	if (si_pi->voltage_control_svi2) {
		si_write_smc_soft_register(rdev, SI_SMC_SOFT_REGISTER_svi_rework_gpio_id_svc,
			si_pi->svc_gpio_id);
		si_write_smc_soft_register(rdev, SI_SMC_SOFT_REGISTER_svi_rework_gpio_id_svd,
			si_pi->svd_gpio_id);
		si_write_smc_soft_register(rdev, SI_SMC_SOFT_REGISTER_svi_rework_plat_type,
					   2);
	} else {
		if (eg_pi->vddc_voltage_table.count) {
			si_populate_smc_voltage_table(rdev, &eg_pi->vddc_voltage_table, table);
			table->voltageMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_VDDC] =
@@ -3935,6 +3981,7 @@ static int si_populate_smc_voltage_tables(struct radeon_device *rdev,
				si_pi->vddc_phase_shed_control = false;
			}
		}
	}

	return 0;
}
@@ -5798,16 +5845,17 @@ int si_dpm_enable(struct radeon_device *rdev)
{
	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
	struct si_power_info *si_pi = si_get_pi(rdev);
	struct radeon_ps *boot_ps = rdev->pm.dpm.boot_ps;
	int ret;

	if (si_is_smc_running(rdev))
		return -EINVAL;
	if (pi->voltage_control)
	if (pi->voltage_control || si_pi->voltage_control_svi2)
		si_enable_voltage_control(rdev, true);
	if (pi->mvdd_control)
		si_get_mvdd_configuration(rdev);
	if (pi->voltage_control) {
	if (pi->voltage_control || si_pi->voltage_control_svi2) {
		ret = si_construct_voltage_tables(rdev);
		if (ret) {
			DRM_ERROR("si_construct_voltage_tables failed\n");
@@ -6406,16 +6454,32 @@ int si_dpm_init(struct radeon_device *rdev)
	ni_pi->mclk_rtt_mode_threshold = eg_pi->mclk_edc_wr_enable_threshold;

	pi->voltage_control =
		radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC, VOLTAGE_OBJ_GPIO_LUT);
		radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC,
					    VOLTAGE_OBJ_GPIO_LUT);
	if (!pi->voltage_control) {
		si_pi->voltage_control_svi2 =
			radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC,
						    VOLTAGE_OBJ_SVID2);
		if (si_pi->voltage_control_svi2)
			radeon_atom_get_svi2_info(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC,
						  &si_pi->svd_gpio_id, &si_pi->svc_gpio_id);
	}

	pi->mvdd_control =
		radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_MVDDC, VOLTAGE_OBJ_GPIO_LUT);
		radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_MVDDC,
					    VOLTAGE_OBJ_GPIO_LUT);

	eg_pi->vddci_control =
		radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDCI, VOLTAGE_OBJ_GPIO_LUT);
		radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDCI,
					    VOLTAGE_OBJ_GPIO_LUT);
	if (!eg_pi->vddci_control)
		si_pi->vddci_control_svi2 =
			radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDCI,
						    VOLTAGE_OBJ_SVID2);

	si_pi->vddc_phase_shed_control =
		radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC, VOLTAGE_OBJ_PHASE_LUT);
		radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC,
					    VOLTAGE_OBJ_PHASE_LUT);

	rv770_get_engine_memory_ss(rdev);

+5 −0
Original line number Diff line number Diff line
@@ -170,6 +170,8 @@ struct si_power_info {
	bool vddc_phase_shed_control;
	bool pspp_notify_required;
	bool sclk_deep_sleep_above_low;
	bool voltage_control_svi2;
	bool vddci_control_svi2;
	/* smc offsets */
	u32 sram_end;
	u32 state_table_start;
@@ -192,6 +194,9 @@ struct si_power_info {
	SMC_SIslands_MCRegisters smc_mc_reg_table;
	SISLANDS_SMC_STATETABLE smc_statetable;
	PP_SIslands_PAPMParameters papm_parm;
	/* SVI2 */
	u8 svd_gpio_id;
	u8 svc_gpio_id;
};

#define SISLANDS_INITIAL_STATE_ARB_INDEX    0
+3 −0
Original line number Diff line number Diff line
@@ -241,6 +241,9 @@ typedef struct SISLANDS_SMC_STATETABLE SISLANDS_SMC_STATETABLE;
#define SI_SMC_SOFT_REGISTER_non_ulv_pcie_link_width  0xF4
#define SI_SMC_SOFT_REGISTER_tdr_is_about_to_happen   0xFC
#define SI_SMC_SOFT_REGISTER_vr_hot_gpio              0x100
#define SI_SMC_SOFT_REGISTER_svi_rework_plat_type     0x118
#define SI_SMC_SOFT_REGISTER_svi_rework_gpio_id_svd   0x11c
#define SI_SMC_SOFT_REGISTER_svi_rework_gpio_id_svc   0x120

#define SMC_SISLANDS_LKGE_LUT_NUM_OF_TEMP_ENTRIES 16
#define SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES 32