aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Deucher <alexander.deucher@amd.com>2014-06-06 18:43:45 -0400
committerAlex Deucher <alexander.deucher@amd.com>2014-08-05 08:53:21 -0400
commit636e2582658742b94e7620becce58f939996c961 (patch)
tree6299d819263106f81d9902cf3b6d4445e0d8ae79
parenta91576d7916f6cce76d30303e60e1ac47cf4a76d (diff)
drm/radeon/dpm: add support for SVI2 voltage for SI
Some newer boards use SVI2 for voltage control rather than GPIO. Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r--drivers/gpu/drm/radeon/radeon.h3
-rw-r--r--drivers/gpu/drm/radeon/radeon_atombios.c44
-rw-r--r--drivers/gpu/drm/radeon/si_dpm.c152
-rw-r--r--drivers/gpu/drm/radeon/si_dpm.h5
-rw-r--r--drivers/gpu/drm/radeon/sislands_smc.h3
5 files changed, 163 insertions, 44 deletions
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 60c47f829122..d1592a0d602b 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -317,6 +317,9 @@ int radeon_atom_get_voltage_table(struct radeon_device *rdev,
317 struct atom_voltage_table *voltage_table); 317 struct atom_voltage_table *voltage_table);
318bool radeon_atom_is_voltage_gpio(struct radeon_device *rdev, 318bool radeon_atom_is_voltage_gpio(struct radeon_device *rdev,
319 u8 voltage_type, u8 voltage_mode); 319 u8 voltage_type, u8 voltage_mode);
320int radeon_atom_get_svi2_info(struct radeon_device *rdev,
321 u8 voltage_type,
322 u8 *svd_gpio_id, u8 *svc_gpio_id);
320void radeon_atom_update_memory_dll(struct radeon_device *rdev, 323void radeon_atom_update_memory_dll(struct radeon_device *rdev,
321 u32 mem_clock); 324 u32 mem_clock);
322void radeon_atom_set_ac_timing(struct radeon_device *rdev, 325void radeon_atom_set_ac_timing(struct radeon_device *rdev,
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
index 173f378428a9..fda1e4130af7 100644
--- a/drivers/gpu/drm/radeon/radeon_atombios.c
+++ b/drivers/gpu/drm/radeon/radeon_atombios.c
@@ -3397,6 +3397,50 @@ radeon_atom_is_voltage_gpio(struct radeon_device *rdev,
3397 return false; 3397 return false;
3398} 3398}
3399 3399
3400int radeon_atom_get_svi2_info(struct radeon_device *rdev,
3401 u8 voltage_type,
3402 u8 *svd_gpio_id, u8 *svc_gpio_id)
3403{
3404 int index = GetIndexIntoMasterTable(DATA, VoltageObjectInfo);
3405 u8 frev, crev;
3406 u16 data_offset, size;
3407 union voltage_object_info *voltage_info;
3408 union voltage_object *voltage_object = NULL;
3409
3410 if (atom_parse_data_header(rdev->mode_info.atom_context, index, &size,
3411 &frev, &crev, &data_offset)) {
3412 voltage_info = (union voltage_object_info *)
3413 (rdev->mode_info.atom_context->bios + data_offset);
3414
3415 switch (frev) {
3416 case 3:
3417 switch (crev) {
3418 case 1:
3419 voltage_object = (union voltage_object *)
3420 atom_lookup_voltage_object_v3(&voltage_info->v3,
3421 voltage_type,
3422 VOLTAGE_OBJ_SVID2);
3423 if (voltage_object) {
3424 *svd_gpio_id = voltage_object->v3.asSVID2Obj.ucSVDGpioId;
3425 *svc_gpio_id = voltage_object->v3.asSVID2Obj.ucSVCGpioId;
3426 } else {
3427 return -EINVAL;
3428 }
3429 break;
3430 default:
3431 DRM_ERROR("unknown voltage object table\n");
3432 return -EINVAL;
3433 }
3434 break;
3435 default:
3436 DRM_ERROR("unknown voltage object table\n");
3437 return -EINVAL;
3438 }
3439
3440 }
3441 return 0;
3442}
3443
3400int radeon_atom_get_max_voltage(struct radeon_device *rdev, 3444int radeon_atom_get_max_voltage(struct radeon_device *rdev,
3401 u8 voltage_type, u16 *max_voltage) 3445 u8 voltage_type, u16 *max_voltage)
3402{ 3446{
diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c
index 58918868f894..70e61ffeace2 100644
--- a/drivers/gpu/drm/radeon/si_dpm.c
+++ b/drivers/gpu/drm/radeon/si_dpm.c
@@ -3812,6 +3812,27 @@ void si_trim_voltage_table_to_fit_state_table(struct radeon_device *rdev,
3812 voltage_table->count = max_voltage_steps; 3812 voltage_table->count = max_voltage_steps;
3813} 3813}
3814 3814
3815static int si_get_svi2_voltage_table(struct radeon_device *rdev,
3816 struct radeon_clock_voltage_dependency_table *voltage_dependency_table,
3817 struct atom_voltage_table *voltage_table)
3818{
3819 u32 i;
3820
3821 if (voltage_dependency_table == NULL)
3822 return -EINVAL;
3823
3824 voltage_table->mask_low = 0;
3825 voltage_table->phase_delay = 0;
3826
3827 voltage_table->count = voltage_dependency_table->count;
3828 for (i = 0; i < voltage_table->count; i++) {
3829 voltage_table->entries[i].value = voltage_dependency_table->entries[i].v;
3830 voltage_table->entries[i].smio_low = 0;
3831 }
3832
3833 return 0;
3834}
3835
3815static int si_construct_voltage_tables(struct radeon_device *rdev) 3836static int si_construct_voltage_tables(struct radeon_device *rdev)
3816{ 3837{
3817 struct rv7xx_power_info *pi = rv770_get_pi(rdev); 3838 struct rv7xx_power_info *pi = rv770_get_pi(rdev);
@@ -3819,15 +3840,25 @@ static int si_construct_voltage_tables(struct radeon_device *rdev)
3819 struct si_power_info *si_pi = si_get_pi(rdev); 3840 struct si_power_info *si_pi = si_get_pi(rdev);
3820 int ret; 3841 int ret;
3821 3842
3822 ret = radeon_atom_get_voltage_table(rdev, VOLTAGE_TYPE_VDDC, 3843 if (pi->voltage_control) {
3823 VOLTAGE_OBJ_GPIO_LUT, &eg_pi->vddc_voltage_table); 3844 ret = radeon_atom_get_voltage_table(rdev, VOLTAGE_TYPE_VDDC,
3824 if (ret) 3845 VOLTAGE_OBJ_GPIO_LUT, &eg_pi->vddc_voltage_table);
3825 return ret; 3846 if (ret)
3847 return ret;
3826 3848
3827 if (eg_pi->vddc_voltage_table.count > SISLANDS_MAX_NO_VREG_STEPS) 3849 if (eg_pi->vddc_voltage_table.count > SISLANDS_MAX_NO_VREG_STEPS)
3828 si_trim_voltage_table_to_fit_state_table(rdev, 3850 si_trim_voltage_table_to_fit_state_table(rdev,
3829 SISLANDS_MAX_NO_VREG_STEPS, 3851 SISLANDS_MAX_NO_VREG_STEPS,
3830 &eg_pi->vddc_voltage_table); 3852 &eg_pi->vddc_voltage_table);
3853 } else if (si_pi->voltage_control_svi2) {
3854 ret = si_get_svi2_voltage_table(rdev,
3855 &rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk,
3856 &eg_pi->vddc_voltage_table);
3857 if (ret)
3858 return ret;
3859 } else {
3860 return -EINVAL;
3861 }
3831 3862
3832 if (eg_pi->vddci_control) { 3863 if (eg_pi->vddci_control) {
3833 ret = radeon_atom_get_voltage_table(rdev, VOLTAGE_TYPE_VDDCI, 3864 ret = radeon_atom_get_voltage_table(rdev, VOLTAGE_TYPE_VDDCI,
@@ -3840,6 +3871,13 @@ static int si_construct_voltage_tables(struct radeon_device *rdev)
3840 SISLANDS_MAX_NO_VREG_STEPS, 3871 SISLANDS_MAX_NO_VREG_STEPS,
3841 &eg_pi->vddci_voltage_table); 3872 &eg_pi->vddci_voltage_table);
3842 } 3873 }
3874 if (si_pi->vddci_control_svi2) {
3875 ret = si_get_svi2_voltage_table(rdev,
3876 &rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk,
3877 &eg_pi->vddci_voltage_table);
3878 if (ret)
3879 return ret;
3880 }
3843 3881
3844 if (pi->mvdd_control) { 3882 if (pi->mvdd_control) {
3845 ret = radeon_atom_get_voltage_table(rdev, VOLTAGE_TYPE_MVDDC, 3883 ret = radeon_atom_get_voltage_table(rdev, VOLTAGE_TYPE_MVDDC,
@@ -3893,46 +3931,55 @@ static int si_populate_smc_voltage_tables(struct radeon_device *rdev,
3893 struct si_power_info *si_pi = si_get_pi(rdev); 3931 struct si_power_info *si_pi = si_get_pi(rdev);
3894 u8 i; 3932 u8 i;
3895 3933
3896 if (eg_pi->vddc_voltage_table.count) { 3934 if (si_pi->voltage_control_svi2) {
3897 si_populate_smc_voltage_table(rdev, &eg_pi->vddc_voltage_table, table); 3935 si_write_smc_soft_register(rdev, SI_SMC_SOFT_REGISTER_svi_rework_gpio_id_svc,
3898 table->voltageMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_VDDC] = 3936 si_pi->svc_gpio_id);
3899 cpu_to_be32(eg_pi->vddc_voltage_table.mask_low); 3937 si_write_smc_soft_register(rdev, SI_SMC_SOFT_REGISTER_svi_rework_gpio_id_svd,
3900 3938 si_pi->svd_gpio_id);
3901 for (i = 0; i < eg_pi->vddc_voltage_table.count; i++) { 3939 si_write_smc_soft_register(rdev, SI_SMC_SOFT_REGISTER_svi_rework_plat_type,
3902 if (pi->max_vddc_in_table <= eg_pi->vddc_voltage_table.entries[i].value) { 3940 2);
3903 table->maxVDDCIndexInPPTable = i; 3941 } else {
3904 break; 3942 if (eg_pi->vddc_voltage_table.count) {
3943 si_populate_smc_voltage_table(rdev, &eg_pi->vddc_voltage_table, table);
3944 table->voltageMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_VDDC] =
3945 cpu_to_be32(eg_pi->vddc_voltage_table.mask_low);
3946
3947 for (i = 0; i < eg_pi->vddc_voltage_table.count; i++) {
3948 if (pi->max_vddc_in_table <= eg_pi->vddc_voltage_table.entries[i].value) {
3949 table->maxVDDCIndexInPPTable = i;
3950 break;
3951 }
3905 } 3952 }
3906 } 3953 }
3907 }
3908 3954
3909 if (eg_pi->vddci_voltage_table.count) { 3955 if (eg_pi->vddci_voltage_table.count) {
3910 si_populate_smc_voltage_table(rdev, &eg_pi->vddci_voltage_table, table); 3956 si_populate_smc_voltage_table(rdev, &eg_pi->vddci_voltage_table, table);
3911 3957
3912 table->voltageMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_VDDCI] = 3958 table->voltageMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_VDDCI] =
3913 cpu_to_be32(eg_pi->vddci_voltage_table.mask_low); 3959 cpu_to_be32(eg_pi->vddci_voltage_table.mask_low);
3914 } 3960 }
3915 3961
3916 3962
3917 if (si_pi->mvdd_voltage_table.count) { 3963 if (si_pi->mvdd_voltage_table.count) {
3918 si_populate_smc_voltage_table(rdev, &si_pi->mvdd_voltage_table, table); 3964 si_populate_smc_voltage_table(rdev, &si_pi->mvdd_voltage_table, table);
3919 3965
3920 table->voltageMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_MVDD] = 3966 table->voltageMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_MVDD] =
3921 cpu_to_be32(si_pi->mvdd_voltage_table.mask_low); 3967 cpu_to_be32(si_pi->mvdd_voltage_table.mask_low);
3922 } 3968 }
3923 3969
3924 if (si_pi->vddc_phase_shed_control) { 3970 if (si_pi->vddc_phase_shed_control) {
3925 if (si_validate_phase_shedding_tables(rdev, &si_pi->vddc_phase_shed_table, 3971 if (si_validate_phase_shedding_tables(rdev, &si_pi->vddc_phase_shed_table,
3926 &rdev->pm.dpm.dyn_state.phase_shedding_limits_table)) { 3972 &rdev->pm.dpm.dyn_state.phase_shedding_limits_table)) {
3927 si_populate_smc_voltage_table(rdev, &si_pi->vddc_phase_shed_table, table); 3973 si_populate_smc_voltage_table(rdev, &si_pi->vddc_phase_shed_table, table);
3928 3974
3929 table->phaseMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_VDDC] = 3975 table->phaseMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_VDDC] =
3930 cpu_to_be32(si_pi->vddc_phase_shed_table.mask_low); 3976 cpu_to_be32(si_pi->vddc_phase_shed_table.mask_low);
3931 3977
3932 si_write_smc_soft_register(rdev, SI_SMC_SOFT_REGISTER_phase_shedding_delay, 3978 si_write_smc_soft_register(rdev, SI_SMC_SOFT_REGISTER_phase_shedding_delay,
3933 (u32)si_pi->vddc_phase_shed_table.phase_delay); 3979 (u32)si_pi->vddc_phase_shed_table.phase_delay);
3934 } else { 3980 } else {
3935 si_pi->vddc_phase_shed_control = false; 3981 si_pi->vddc_phase_shed_control = false;
3982 }
3936 } 3983 }
3937 } 3984 }
3938 3985
@@ -5798,16 +5845,17 @@ int si_dpm_enable(struct radeon_device *rdev)
5798{ 5845{
5799 struct rv7xx_power_info *pi = rv770_get_pi(rdev); 5846 struct rv7xx_power_info *pi = rv770_get_pi(rdev);
5800 struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev); 5847 struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
5848 struct si_power_info *si_pi = si_get_pi(rdev);
5801 struct radeon_ps *boot_ps = rdev->pm.dpm.boot_ps; 5849 struct radeon_ps *boot_ps = rdev->pm.dpm.boot_ps;
5802 int ret; 5850 int ret;
5803 5851
5804 if (si_is_smc_running(rdev)) 5852 if (si_is_smc_running(rdev))
5805 return -EINVAL; 5853 return -EINVAL;
5806 if (pi->voltage_control) 5854 if (pi->voltage_control || si_pi->voltage_control_svi2)
5807 si_enable_voltage_control(rdev, true); 5855 si_enable_voltage_control(rdev, true);
5808 if (pi->mvdd_control) 5856 if (pi->mvdd_control)
5809 si_get_mvdd_configuration(rdev); 5857 si_get_mvdd_configuration(rdev);
5810 if (pi->voltage_control) { 5858 if (pi->voltage_control || si_pi->voltage_control_svi2) {
5811 ret = si_construct_voltage_tables(rdev); 5859 ret = si_construct_voltage_tables(rdev);
5812 if (ret) { 5860 if (ret) {
5813 DRM_ERROR("si_construct_voltage_tables failed\n"); 5861 DRM_ERROR("si_construct_voltage_tables failed\n");
@@ -6406,16 +6454,32 @@ int si_dpm_init(struct radeon_device *rdev)
6406 ni_pi->mclk_rtt_mode_threshold = eg_pi->mclk_edc_wr_enable_threshold; 6454 ni_pi->mclk_rtt_mode_threshold = eg_pi->mclk_edc_wr_enable_threshold;
6407 6455
6408 pi->voltage_control = 6456 pi->voltage_control =
6409 radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC, VOLTAGE_OBJ_GPIO_LUT); 6457 radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC,
6458 VOLTAGE_OBJ_GPIO_LUT);
6459 if (!pi->voltage_control) {
6460 si_pi->voltage_control_svi2 =
6461 radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC,
6462 VOLTAGE_OBJ_SVID2);
6463 if (si_pi->voltage_control_svi2)
6464 radeon_atom_get_svi2_info(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC,
6465 &si_pi->svd_gpio_id, &si_pi->svc_gpio_id);
6466 }
6410 6467
6411 pi->mvdd_control = 6468 pi->mvdd_control =
6412 radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_MVDDC, VOLTAGE_OBJ_GPIO_LUT); 6469 radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_MVDDC,
6470 VOLTAGE_OBJ_GPIO_LUT);
6413 6471
6414 eg_pi->vddci_control = 6472 eg_pi->vddci_control =
6415 radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDCI, VOLTAGE_OBJ_GPIO_LUT); 6473 radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDCI,
6474 VOLTAGE_OBJ_GPIO_LUT);
6475 if (!eg_pi->vddci_control)
6476 si_pi->vddci_control_svi2 =
6477 radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDCI,
6478 VOLTAGE_OBJ_SVID2);
6416 6479
6417 si_pi->vddc_phase_shed_control = 6480 si_pi->vddc_phase_shed_control =
6418 radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC, VOLTAGE_OBJ_PHASE_LUT); 6481 radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC,
6482 VOLTAGE_OBJ_PHASE_LUT);
6419 6483
6420 rv770_get_engine_memory_ss(rdev); 6484 rv770_get_engine_memory_ss(rdev);
6421 6485
diff --git a/drivers/gpu/drm/radeon/si_dpm.h b/drivers/gpu/drm/radeon/si_dpm.h
index 4ce5032cdf49..8b5c06a0832d 100644
--- a/drivers/gpu/drm/radeon/si_dpm.h
+++ b/drivers/gpu/drm/radeon/si_dpm.h
@@ -170,6 +170,8 @@ struct si_power_info {
170 bool vddc_phase_shed_control; 170 bool vddc_phase_shed_control;
171 bool pspp_notify_required; 171 bool pspp_notify_required;
172 bool sclk_deep_sleep_above_low; 172 bool sclk_deep_sleep_above_low;
173 bool voltage_control_svi2;
174 bool vddci_control_svi2;
173 /* smc offsets */ 175 /* smc offsets */
174 u32 sram_end; 176 u32 sram_end;
175 u32 state_table_start; 177 u32 state_table_start;
@@ -192,6 +194,9 @@ struct si_power_info {
192 SMC_SIslands_MCRegisters smc_mc_reg_table; 194 SMC_SIslands_MCRegisters smc_mc_reg_table;
193 SISLANDS_SMC_STATETABLE smc_statetable; 195 SISLANDS_SMC_STATETABLE smc_statetable;
194 PP_SIslands_PAPMParameters papm_parm; 196 PP_SIslands_PAPMParameters papm_parm;
197 /* SVI2 */
198 u8 svd_gpio_id;
199 u8 svc_gpio_id;
195}; 200};
196 201
197#define SISLANDS_INITIAL_STATE_ARB_INDEX 0 202#define SISLANDS_INITIAL_STATE_ARB_INDEX 0
diff --git a/drivers/gpu/drm/radeon/sislands_smc.h b/drivers/gpu/drm/radeon/sislands_smc.h
index 10e945a49479..623a0b1e2d9d 100644
--- a/drivers/gpu/drm/radeon/sislands_smc.h
+++ b/drivers/gpu/drm/radeon/sislands_smc.h
@@ -241,6 +241,9 @@ typedef struct SISLANDS_SMC_STATETABLE SISLANDS_SMC_STATETABLE;
241#define SI_SMC_SOFT_REGISTER_non_ulv_pcie_link_width 0xF4 241#define SI_SMC_SOFT_REGISTER_non_ulv_pcie_link_width 0xF4
242#define SI_SMC_SOFT_REGISTER_tdr_is_about_to_happen 0xFC 242#define SI_SMC_SOFT_REGISTER_tdr_is_about_to_happen 0xFC
243#define SI_SMC_SOFT_REGISTER_vr_hot_gpio 0x100 243#define SI_SMC_SOFT_REGISTER_vr_hot_gpio 0x100
244#define SI_SMC_SOFT_REGISTER_svi_rework_plat_type 0x118
245#define SI_SMC_SOFT_REGISTER_svi_rework_gpio_id_svd 0x11c
246#define SI_SMC_SOFT_REGISTER_svi_rework_gpio_id_svc 0x120
244 247
245#define SMC_SISLANDS_LKGE_LUT_NUM_OF_TEMP_ENTRIES 16 248#define SMC_SISLANDS_LKGE_LUT_NUM_OF_TEMP_ENTRIES 16
246#define SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES 32 249#define SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES 32