aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorAlex Deucher <alexander.deucher@amd.com>2013-04-12 16:40:41 -0400
committerAlex Deucher <alexander.deucher@amd.com>2013-06-27 19:15:45 -0400
commitd70229f704474b2932e03367a528773e336f6205 (patch)
tree8e56480f4073505457f212706f7f3f81b89583bc /drivers/gpu/drm
parent80ea2c129c76a4159a93efeaef4385b6c964dfac (diff)
drm/radeon/kms: add dpm support for trinity asics
This adds dpm support for trinity asics. This includes: - clockgating - powergating - dynamic engine clock scaling - dynamic voltage scaling set radeon.dpm=1 to enable it. Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/radeon/Makefile3
-rw-r--r--drivers/gpu/drm/radeon/evergreen.c13
-rw-r--r--drivers/gpu/drm/radeon/evergreend.h10
-rw-r--r--drivers/gpu/drm/radeon/ppsmc.h10
-rw-r--r--drivers/gpu/drm/radeon/radeon_asic.c12
-rw-r--r--drivers/gpu/drm/radeon/radeon_asic.h12
-rw-r--r--drivers/gpu/drm/radeon/radeon_pm.c1
-rw-r--r--drivers/gpu/drm/radeon/sumo_dpm.c90
-rw-r--r--drivers/gpu/drm/radeon/sumo_dpm.h21
-rw-r--r--drivers/gpu/drm/radeon/sumo_smc.c2
-rw-r--r--drivers/gpu/drm/radeon/trinity_dpm.c1613
-rw-r--r--drivers/gpu/drm/radeon/trinity_dpm.h110
-rw-r--r--drivers/gpu/drm/radeon/trinity_smc.c110
-rw-r--r--drivers/gpu/drm/radeon/trinityd.h223
14 files changed, 2179 insertions, 51 deletions
diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile
index 7c77e1d8b5ce..2239ec27e63b 100644
--- a/drivers/gpu/drm/radeon/Makefile
+++ b/drivers/gpu/drm/radeon/Makefile
@@ -78,7 +78,8 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \
78 atombios_encoders.o radeon_semaphore.o radeon_sa.o atombios_i2c.o si.o \ 78 atombios_encoders.o radeon_semaphore.o radeon_sa.o atombios_i2c.o si.o \
79 si_blit_shaders.o radeon_prime.o radeon_uvd.o cik.o cik_blit_shaders.o \ 79 si_blit_shaders.o radeon_prime.o radeon_uvd.o cik.o cik_blit_shaders.o \
80 r600_dpm.o rs780_dpm.o rv6xx_dpm.o rv770_dpm.o rv730_dpm.o rv740_dpm.o \ 80 r600_dpm.o rs780_dpm.o rv6xx_dpm.o rv770_dpm.o rv730_dpm.o rv740_dpm.o \
81 rv770_smc.o cypress_dpm.o btc_dpm.o sumo_dpm.o sumo_smc.o 81 rv770_smc.o cypress_dpm.o btc_dpm.o sumo_dpm.o sumo_smc.o trinity_dpm.o \
82 trinity_smc.o
82 83
83radeon-$(CONFIG_COMPAT) += radeon_ioc32.o 84radeon-$(CONFIG_COMPAT) += radeon_ioc32.o
84radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o 85radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 54d1d736dee2..d0aef76121d5 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -4187,8 +4187,12 @@ int evergreen_irq_set(struct radeon_device *rdev)
4187 hpd4 = RREG32(DC_HPD4_INT_CONTROL) & ~DC_HPDx_INT_EN; 4187 hpd4 = RREG32(DC_HPD4_INT_CONTROL) & ~DC_HPDx_INT_EN;
4188 hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~DC_HPDx_INT_EN; 4188 hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~DC_HPDx_INT_EN;
4189 hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~DC_HPDx_INT_EN; 4189 hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~DC_HPDx_INT_EN;
4190 thermal_int = RREG32(CG_THERMAL_INT) & 4190 if (rdev->family == CHIP_ARUBA)
4191 ~(THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW); 4191 thermal_int = RREG32(TN_CG_THERMAL_INT_CTRL) &
4192 ~(THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW);
4193 else
4194 thermal_int = RREG32(CG_THERMAL_INT) &
4195 ~(THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW);
4192 4196
4193 afmt1 = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) & ~AFMT_AZ_FORMAT_WTRIG_MASK; 4197 afmt1 = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) & ~AFMT_AZ_FORMAT_WTRIG_MASK;
4194 afmt2 = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET) & ~AFMT_AZ_FORMAT_WTRIG_MASK; 4198 afmt2 = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET) & ~AFMT_AZ_FORMAT_WTRIG_MASK;
@@ -4360,7 +4364,10 @@ int evergreen_irq_set(struct radeon_device *rdev)
4360 WREG32(DC_HPD4_INT_CONTROL, hpd4); 4364 WREG32(DC_HPD4_INT_CONTROL, hpd4);
4361 WREG32(DC_HPD5_INT_CONTROL, hpd5); 4365 WREG32(DC_HPD5_INT_CONTROL, hpd5);
4362 WREG32(DC_HPD6_INT_CONTROL, hpd6); 4366 WREG32(DC_HPD6_INT_CONTROL, hpd6);
4363 WREG32(CG_THERMAL_INT, thermal_int); 4367 if (rdev->family == CHIP_ARUBA)
4368 WREG32(TN_CG_THERMAL_INT_CTRL, thermal_int);
4369 else
4370 WREG32(CG_THERMAL_INT, thermal_int);
4364 4371
4365 WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, afmt1); 4372 WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, afmt1);
4366 WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, afmt2); 4373 WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, afmt2);
diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h
index 93b91a38200a..35e61539b5f8 100644
--- a/drivers/gpu/drm/radeon/evergreend.h
+++ b/drivers/gpu/drm/radeon/evergreend.h
@@ -823,6 +823,16 @@
823#define THERM_INT_MASK_HIGH (1 << 24) 823#define THERM_INT_MASK_HIGH (1 << 24)
824#define THERM_INT_MASK_LOW (1 << 25) 824#define THERM_INT_MASK_LOW (1 << 25)
825 825
826#define TN_CG_THERMAL_INT_CTRL 0x738
827#define TN_DIG_THERM_INTH(x) ((x) << 0)
828#define TN_DIG_THERM_INTH_MASK 0x000000FF
829#define TN_DIG_THERM_INTH_SHIFT 0
830#define TN_DIG_THERM_INTL(x) ((x) << 8)
831#define TN_DIG_THERM_INTL_MASK 0x0000FF00
832#define TN_DIG_THERM_INTL_SHIFT 8
833#define TN_THERM_INT_MASK_HIGH (1 << 24)
834#define TN_THERM_INT_MASK_LOW (1 << 25)
835
826#define CG_MULT_THERMAL_STATUS 0x740 836#define CG_MULT_THERMAL_STATUS 0x740
827#define ASIC_T(x) ((x) << 16) 837#define ASIC_T(x) ((x) << 16)
828#define ASIC_T_MASK 0x07FF0000 838#define ASIC_T_MASK 0x07FF0000
diff --git a/drivers/gpu/drm/radeon/ppsmc.h b/drivers/gpu/drm/radeon/ppsmc.h
index c85b96eac75f..88838083448b 100644
--- a/drivers/gpu/drm/radeon/ppsmc.h
+++ b/drivers/gpu/drm/radeon/ppsmc.h
@@ -71,7 +71,15 @@ typedef uint8_t PPSMC_Result;
71#define PPSMC_MSG_ExitULV ((uint8_t)0x65) 71#define PPSMC_MSG_ExitULV ((uint8_t)0x65)
72#define PPSMC_MSG_ResetToDefaults ((uint8_t)0x84) 72#define PPSMC_MSG_ResetToDefaults ((uint8_t)0x84)
73 73
74typedef uint8_t PPSMC_Msg; 74/* TN */
75#define PPSMC_MSG_DPM_Config ((uint32_t) 0x102)
76#define PPSMC_MSG_DPM_ForceState ((uint32_t) 0x104)
77#define PPSMC_MSG_PG_SIMD_Config ((uint32_t) 0x108)
78#define PPSMC_MSG_DCE_RemoveVoltageAdjustment ((uint32_t) 0x11d)
79#define PPSMC_MSG_DCE_AllowVoltageAdjustment ((uint32_t) 0x11e)
80
81
82typedef uint16_t PPSMC_Msg;
75 83
76#pragma pack(pop) 84#pragma pack(pop)
77 85
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c
index 1419eddf5e1d..ca0ddc8aabe5 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.c
+++ b/drivers/gpu/drm/radeon/radeon_asic.c
@@ -2064,6 +2064,18 @@ static struct radeon_asic trinity_asic = {
2064 .set_uvd_clocks = &sumo_set_uvd_clocks, 2064 .set_uvd_clocks = &sumo_set_uvd_clocks,
2065 .get_temperature = &tn_get_temp, 2065 .get_temperature = &tn_get_temp,
2066 }, 2066 },
2067 .dpm = {
2068 .init = &trinity_dpm_init,
2069 .setup_asic = &trinity_dpm_setup_asic,
2070 .enable = &trinity_dpm_enable,
2071 .disable = &trinity_dpm_disable,
2072 .set_power_state = &trinity_dpm_set_power_state,
2073 .display_configuration_changed = &trinity_dpm_display_configuration_changed,
2074 .fini = &trinity_dpm_fini,
2075 .get_sclk = &trinity_dpm_get_sclk,
2076 .get_mclk = &trinity_dpm_get_mclk,
2077 .print_power_state = &trinity_dpm_print_power_state,
2078 },
2067 .pflip = { 2079 .pflip = {
2068 .pre_page_flip = &evergreen_pre_page_flip, 2080 .pre_page_flip = &evergreen_pre_page_flip,
2069 .page_flip = &evergreen_page_flip, 2081 .page_flip = &evergreen_page_flip,
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h
index 336e3b63cfd6..709e5c9cad1b 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.h
+++ b/drivers/gpu/drm/radeon/radeon_asic.h
@@ -587,6 +587,18 @@ bool cayman_gfx_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring);
587bool cayman_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring); 587bool cayman_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring);
588void cayman_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm); 588void cayman_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm);
589 589
590int trinity_dpm_init(struct radeon_device *rdev);
591int trinity_dpm_enable(struct radeon_device *rdev);
592void trinity_dpm_disable(struct radeon_device *rdev);
593int trinity_dpm_set_power_state(struct radeon_device *rdev);
594void trinity_dpm_setup_asic(struct radeon_device *rdev);
595void trinity_dpm_display_configuration_changed(struct radeon_device *rdev);
596void trinity_dpm_fini(struct radeon_device *rdev);
597u32 trinity_dpm_get_sclk(struct radeon_device *rdev, bool low);
598u32 trinity_dpm_get_mclk(struct radeon_device *rdev, bool low);
599void trinity_dpm_print_power_state(struct radeon_device *rdev,
600 struct radeon_ps *ps);
601
590/* DCE6 - SI */ 602/* DCE6 - SI */
591void dce6_bandwidth_update(struct radeon_device *rdev); 603void dce6_bandwidth_update(struct radeon_device *rdev);
592 604
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c
index 8e913a9ec8b2..2998e75423a0 100644
--- a/drivers/gpu/drm/radeon/radeon_pm.c
+++ b/drivers/gpu/drm/radeon/radeon_pm.c
@@ -1052,6 +1052,7 @@ int radeon_pm_init(struct radeon_device *rdev)
1052 case CHIP_BARTS: 1052 case CHIP_BARTS:
1053 case CHIP_TURKS: 1053 case CHIP_TURKS:
1054 case CHIP_CAICOS: 1054 case CHIP_CAICOS:
1055 case CHIP_ARUBA:
1055 if (radeon_dpm == 1) 1056 if (radeon_dpm == 1)
1056 rdev->pm.pm_method = PM_METHOD_DPM; 1057 rdev->pm.pm_method = PM_METHOD_DPM;
1057 else 1058 else
diff --git a/drivers/gpu/drm/radeon/sumo_dpm.c b/drivers/gpu/drm/radeon/sumo_dpm.c
index fa2a72e17d07..7ab60068396e 100644
--- a/drivers/gpu/drm/radeon/sumo_dpm.c
+++ b/drivers/gpu/drm/radeon/sumo_dpm.c
@@ -27,7 +27,6 @@
27#include "r600_dpm.h" 27#include "r600_dpm.h"
28#include "cypress_dpm.h" 28#include "cypress_dpm.h"
29#include "sumo_dpm.h" 29#include "sumo_dpm.h"
30#include "atom.h"
31 30
32#define SUMO_MAX_DEEPSLEEP_DIVIDER_ID 5 31#define SUMO_MAX_DEEPSLEEP_DIVIDER_ID 5
33#define SUMO_MINIMUM_ENGINE_CLOCK 800 32#define SUMO_MINIMUM_ENGINE_CLOCK 800
@@ -144,7 +143,7 @@ static void sumo_program_grsd(struct radeon_device *rdev)
144 WREG32(CG_GCOOR, PHC(grs) | SDC(p) | SU(u)); 143 WREG32(CG_GCOOR, PHC(grs) | SDC(p) | SU(u));
145} 144}
146 145
147static void sumo_gfx_clockgating_initialize(struct radeon_device *rdev) 146void sumo_gfx_clockgating_initialize(struct radeon_device *rdev)
148{ 147{
149 sumo_program_git(rdev); 148 sumo_program_git(rdev);
150 sumo_program_grsd(rdev); 149 sumo_program_grsd(rdev);
@@ -452,17 +451,17 @@ static void sumo_program_tp(struct radeon_device *rdev)
452 WREG32_P(SCLK_PWRMGT_CNTL, FIR_TREND_MODE, ~FIR_TREND_MODE); 451 WREG32_P(SCLK_PWRMGT_CNTL, FIR_TREND_MODE, ~FIR_TREND_MODE);
453} 452}
454 453
455static void sumo_program_vc(struct radeon_device *rdev) 454void sumo_program_vc(struct radeon_device *rdev, u32 vrc)
456{ 455{
457 WREG32(CG_FTV, SUMO_VRC_DFLT); 456 WREG32(CG_FTV, vrc);
458} 457}
459 458
460static void sumo_clear_vc(struct radeon_device *rdev) 459void sumo_clear_vc(struct radeon_device *rdev)
461{ 460{
462 WREG32(CG_FTV, 0); 461 WREG32(CG_FTV, 0);
463} 462}
464 463
465static void sumo_program_sstp(struct radeon_device *rdev) 464void sumo_program_sstp(struct radeon_device *rdev)
466{ 465{
467 u32 p, u; 466 u32 p, u;
468 u32 xclk = sumo_get_xclk(rdev); 467 u32 xclk = sumo_get_xclk(rdev);
@@ -812,7 +811,7 @@ static void sumo_program_bootup_state(struct radeon_device *rdev)
812 sumo_power_level_enable(rdev, i, false); 811 sumo_power_level_enable(rdev, i, false);
813} 812}
814 813
815static void sumo_take_smu_control(struct radeon_device *rdev, bool enable) 814void sumo_take_smu_control(struct radeon_device *rdev, bool enable)
816{ 815{
817 u32 v = RREG32(DOUT_SCRATCH3); 816 u32 v = RREG32(DOUT_SCRATCH3);
818 817
@@ -933,14 +932,14 @@ static void sumo_force_nbp_state(struct radeon_device *rdev)
933 } 932 }
934} 933}
935 934
936static u32 sumo_get_sleep_divider_from_id(u32 id) 935u32 sumo_get_sleep_divider_from_id(u32 id)
937{ 936{
938 return 1 << id; 937 return 1 << id;
939} 938}
940 939
941static u32 sumo_get_sleep_divider_id_from_clock(struct radeon_device *rdev, 940u32 sumo_get_sleep_divider_id_from_clock(struct radeon_device *rdev,
942 u32 sclk, 941 u32 sclk,
943 u32 min_sclk_in_sr) 942 u32 min_sclk_in_sr)
944{ 943{
945 struct sumo_power_info *pi = sumo_get_pi(rdev); 944 struct sumo_power_info *pi = sumo_get_pi(rdev);
946 u32 i; 945 u32 i;
@@ -1136,7 +1135,7 @@ int sumo_dpm_enable(struct radeon_device *rdev)
1136 sumo_program_power_level_enter_state(rdev); 1135 sumo_program_power_level_enter_state(rdev);
1137 sumo_enable_voltage_scaling(rdev, true); 1136 sumo_enable_voltage_scaling(rdev, true);
1138 sumo_program_sstp(rdev); 1137 sumo_program_sstp(rdev);
1139 sumo_program_vc(rdev); 1138 sumo_program_vc(rdev, SUMO_VRC_DFLT);
1140 sumo_override_cnb_thermal_events(rdev); 1139 sumo_override_cnb_thermal_events(rdev);
1141 sumo_start_dpm(rdev); 1140 sumo_start_dpm(rdev);
1142 sumo_wait_for_level_0(rdev); 1141 sumo_wait_for_level_0(rdev);
@@ -1393,23 +1392,25 @@ static int sumo_parse_power_table(struct radeon_device *rdev)
1393 return 0; 1392 return 0;
1394} 1393}
1395 1394
1396static u32 sumo_convert_vid2_to_vid7(struct radeon_device *rdev, u32 vid_2bit) 1395u32 sumo_convert_vid2_to_vid7(struct radeon_device *rdev,
1396 struct sumo_vid_mapping_table *vid_mapping_table,
1397 u32 vid_2bit)
1397{ 1398{
1398 struct sumo_power_info *pi = sumo_get_pi(rdev);
1399 u32 i; 1399 u32 i;
1400 1400
1401 for (i = 0; i < pi->sys_info.vid_mapping_table.num_entries; i++) { 1401 for (i = 0; i < vid_mapping_table->num_entries; i++) {
1402 if (pi->sys_info.vid_mapping_table.entries[i].vid_2bit == vid_2bit) 1402 if (vid_mapping_table->entries[i].vid_2bit == vid_2bit)
1403 return pi->sys_info.vid_mapping_table.entries[i].vid_7bit; 1403 return vid_mapping_table->entries[i].vid_7bit;
1404 } 1404 }
1405 1405
1406 return pi->sys_info.vid_mapping_table.entries[pi->sys_info.vid_mapping_table.num_entries - 1].vid_7bit; 1406 return vid_mapping_table->entries[vid_mapping_table->num_entries - 1].vid_7bit;
1407} 1407}
1408 1408
1409static u16 sumo_convert_voltage_index_to_value(struct radeon_device *rdev, 1409static u16 sumo_convert_voltage_index_to_value(struct radeon_device *rdev,
1410 u32 vid_2bit) 1410 u32 vid_2bit)
1411{ 1411{
1412 u32 vid_7bit = sumo_convert_vid2_to_vid7(rdev, vid_2bit); 1412 struct sumo_power_info *pi = sumo_get_pi(rdev);
1413 u32 vid_7bit = sumo_convert_vid2_to_vid7(rdev, &pi->sys_info.vid_mapping_table, vid_2bit);
1413 1414
1414 if (vid_7bit > 0x7C) 1415 if (vid_7bit > 0x7C)
1415 return 0; 1416 return 0;
@@ -1418,71 +1419,71 @@ static u16 sumo_convert_voltage_index_to_value(struct radeon_device *rdev,
1418} 1419}
1419 1420
1420static void sumo_construct_display_voltage_mapping_table(struct radeon_device *rdev, 1421static void sumo_construct_display_voltage_mapping_table(struct radeon_device *rdev,
1422 struct sumo_disp_clock_voltage_mapping_table *disp_clk_voltage_mapping_table,
1421 ATOM_CLK_VOLT_CAPABILITY *table) 1423 ATOM_CLK_VOLT_CAPABILITY *table)
1422{ 1424{
1423 struct sumo_power_info *pi = sumo_get_pi(rdev);
1424 u32 i; 1425 u32 i;
1425 1426
1426 for (i = 0; i < SUMO_MAX_NUMBER_VOLTAGES; i++) { 1427 for (i = 0; i < SUMO_MAX_NUMBER_VOLTAGES; i++) {
1427 if (table[i].ulMaximumSupportedCLK == 0) 1428 if (table[i].ulMaximumSupportedCLK == 0)
1428 break; 1429 break;
1429 1430
1430 pi->sys_info.disp_clk_voltage_mapping_table.display_clock_frequency[i] = 1431 disp_clk_voltage_mapping_table->display_clock_frequency[i] =
1431 table[i].ulMaximumSupportedCLK; 1432 table[i].ulMaximumSupportedCLK;
1432 } 1433 }
1433 1434
1434 pi->sys_info.disp_clk_voltage_mapping_table.num_max_voltage_levels = i; 1435 disp_clk_voltage_mapping_table->num_max_voltage_levels = i;
1435 1436
1436 if (pi->sys_info.disp_clk_voltage_mapping_table.num_max_voltage_levels == 0) { 1437 if (disp_clk_voltage_mapping_table->num_max_voltage_levels == 0) {
1437 pi->sys_info.disp_clk_voltage_mapping_table.display_clock_frequency[0] = 80000; 1438 disp_clk_voltage_mapping_table->display_clock_frequency[0] = 80000;
1438 pi->sys_info.disp_clk_voltage_mapping_table.num_max_voltage_levels = 1; 1439 disp_clk_voltage_mapping_table->num_max_voltage_levels = 1;
1439 } 1440 }
1440} 1441}
1441 1442
1442static void sumo_construct_sclk_voltage_mapping_table(struct radeon_device *rdev, 1443void sumo_construct_sclk_voltage_mapping_table(struct radeon_device *rdev,
1443 ATOM_AVAILABLE_SCLK_LIST *table) 1444 struct sumo_sclk_voltage_mapping_table *sclk_voltage_mapping_table,
1445 ATOM_AVAILABLE_SCLK_LIST *table)
1444{ 1446{
1445 struct sumo_power_info *pi = sumo_get_pi(rdev);
1446 u32 i; 1447 u32 i;
1447 u32 n = 0; 1448 u32 n = 0;
1448 u32 prev_sclk = 0; 1449 u32 prev_sclk = 0;
1449 1450
1450 for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++) { 1451 for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++) {
1451 if (table[i].ulSupportedSCLK > prev_sclk) { 1452 if (table[i].ulSupportedSCLK > prev_sclk) {
1452 pi->sys_info.sclk_voltage_mapping_table.entries[n].sclk_frequency = 1453 sclk_voltage_mapping_table->entries[n].sclk_frequency =
1453 table[i].ulSupportedSCLK; 1454 table[i].ulSupportedSCLK;
1454 pi->sys_info.sclk_voltage_mapping_table.entries[n].vid_2bit = 1455 sclk_voltage_mapping_table->entries[n].vid_2bit =
1455 table[i].usVoltageIndex; 1456 table[i].usVoltageIndex;
1456 prev_sclk = table[i].ulSupportedSCLK; 1457 prev_sclk = table[i].ulSupportedSCLK;
1457 n++; 1458 n++;
1458 } 1459 }
1459 } 1460 }
1460 1461
1461 pi->sys_info.sclk_voltage_mapping_table.num_max_dpm_entries = n; 1462 sclk_voltage_mapping_table->num_max_dpm_entries = n;
1462} 1463}
1463 1464
1464static void sumo_construct_vid_mapping_table(struct radeon_device *rdev, 1465void sumo_construct_vid_mapping_table(struct radeon_device *rdev,
1465 ATOM_AVAILABLE_SCLK_LIST *table) 1466 struct sumo_vid_mapping_table *vid_mapping_table,
1467 ATOM_AVAILABLE_SCLK_LIST *table)
1466{ 1468{
1467 struct sumo_power_info *pi = sumo_get_pi(rdev);
1468 u32 i, j; 1469 u32 i, j;
1469 1470
1470 for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++) { 1471 for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++) {
1471 if (table[i].ulSupportedSCLK != 0) { 1472 if (table[i].ulSupportedSCLK != 0) {
1472 pi->sys_info.vid_mapping_table.entries[table[i].usVoltageIndex].vid_7bit = 1473 vid_mapping_table->entries[table[i].usVoltageIndex].vid_7bit =
1473 table[i].usVoltageID; 1474 table[i].usVoltageID;
1474 pi->sys_info.vid_mapping_table.entries[table[i].usVoltageIndex].vid_2bit = 1475 vid_mapping_table->entries[table[i].usVoltageIndex].vid_2bit =
1475 table[i].usVoltageIndex; 1476 table[i].usVoltageIndex;
1476 } 1477 }
1477 } 1478 }
1478 1479
1479 for (i = 0; i < SUMO_MAX_NUMBER_VOLTAGES; i++) { 1480 for (i = 0; i < SUMO_MAX_NUMBER_VOLTAGES; i++) {
1480 if (pi->sys_info.vid_mapping_table.entries[i].vid_7bit == 0) { 1481 if (vid_mapping_table->entries[i].vid_7bit == 0) {
1481 for (j = i + 1; j < SUMO_MAX_NUMBER_VOLTAGES; j++) { 1482 for (j = i + 1; j < SUMO_MAX_NUMBER_VOLTAGES; j++) {
1482 if (pi->sys_info.vid_mapping_table.entries[j].vid_7bit != 0) { 1483 if (vid_mapping_table->entries[j].vid_7bit != 0) {
1483 pi->sys_info.vid_mapping_table.entries[i] = 1484 vid_mapping_table->entries[i] =
1484 pi->sys_info.vid_mapping_table.entries[j]; 1485 vid_mapping_table->entries[j];
1485 pi->sys_info.vid_mapping_table.entries[j].vid_7bit = 0; 1486 vid_mapping_table->entries[j].vid_7bit = 0;
1486 break; 1487 break;
1487 } 1488 }
1488 } 1489 }
@@ -1492,7 +1493,7 @@ static void sumo_construct_vid_mapping_table(struct radeon_device *rdev,
1492 } 1493 }
1493 } 1494 }
1494 1495
1495 pi->sys_info.vid_mapping_table.num_entries = i; 1496 vid_mapping_table->num_entries = i;
1496} 1497}
1497 1498
1498union igp_info { 1499union igp_info {
@@ -1561,10 +1562,13 @@ static int sumo_parse_sys_info_table(struct radeon_device *rdev)
1561 else 1562 else
1562 pi->sys_info.enable_boost = false; 1563 pi->sys_info.enable_boost = false;
1563 sumo_construct_display_voltage_mapping_table(rdev, 1564 sumo_construct_display_voltage_mapping_table(rdev,
1565 &pi->sys_info.disp_clk_voltage_mapping_table,
1564 igp_info->info_6.sDISPCLK_Voltage); 1566 igp_info->info_6.sDISPCLK_Voltage);
1565 sumo_construct_sclk_voltage_mapping_table(rdev, 1567 sumo_construct_sclk_voltage_mapping_table(rdev,
1568 &pi->sys_info.sclk_voltage_mapping_table,
1566 igp_info->info_6.sAvail_SCLK); 1569 igp_info->info_6.sAvail_SCLK);
1567 sumo_construct_vid_mapping_table(rdev, igp_info->info_6.sAvail_SCLK); 1570 sumo_construct_vid_mapping_table(rdev, &pi->sys_info.vid_mapping_table,
1571 igp_info->info_6.sAvail_SCLK);
1568 1572
1569 } 1573 }
1570 return 0; 1574 return 0;
diff --git a/drivers/gpu/drm/radeon/sumo_dpm.h b/drivers/gpu/drm/radeon/sumo_dpm.h
index 561bee16039a..d041a6cf11ba 100644
--- a/drivers/gpu/drm/radeon/sumo_dpm.h
+++ b/drivers/gpu/drm/radeon/sumo_dpm.h
@@ -23,6 +23,8 @@
23#ifndef __SUMO_DPM_H__ 23#ifndef __SUMO_DPM_H__
24#define __SUMO_DPM_H__ 24#define __SUMO_DPM_H__
25 25
26#include "atom.h"
27
26#define SUMO_MAX_HARDWARE_POWERLEVELS 5 28#define SUMO_MAX_HARDWARE_POWERLEVELS 5
27#define SUMO_PM_NUMBER_OF_TC 15 29#define SUMO_PM_NUMBER_OF_TC 15
28 30
@@ -184,7 +186,24 @@ struct sumo_power_info {
184 186
185/* sumo_dpm.c */ 187/* sumo_dpm.c */
186u32 sumo_get_xclk(struct radeon_device *rdev); 188u32 sumo_get_xclk(struct radeon_device *rdev);
187 189void sumo_gfx_clockgating_initialize(struct radeon_device *rdev);
190void sumo_program_vc(struct radeon_device *rdev, u32 vrc);
191void sumo_clear_vc(struct radeon_device *rdev);
192void sumo_program_sstp(struct radeon_device *rdev);
193void sumo_take_smu_control(struct radeon_device *rdev, bool enable);
194void sumo_construct_sclk_voltage_mapping_table(struct radeon_device *rdev,
195 struct sumo_sclk_voltage_mapping_table *sclk_voltage_mapping_table,
196 ATOM_AVAILABLE_SCLK_LIST *table);
197void sumo_construct_vid_mapping_table(struct radeon_device *rdev,
198 struct sumo_vid_mapping_table *vid_mapping_table,
199 ATOM_AVAILABLE_SCLK_LIST *table);
200u32 sumo_convert_vid2_to_vid7(struct radeon_device *rdev,
201 struct sumo_vid_mapping_table *vid_mapping_table,
202 u32 vid_2bit);
203u32 sumo_get_sleep_divider_from_id(u32 id);
204u32 sumo_get_sleep_divider_id_from_clock(struct radeon_device *rdev,
205 u32 sclk,
206 u32 min_sclk_in_sr);
188 207
189/* sumo_smc.c */ 208/* sumo_smc.c */
190void sumo_initialize_m3_arb(struct radeon_device *rdev); 209void sumo_initialize_m3_arb(struct radeon_device *rdev);
diff --git a/drivers/gpu/drm/radeon/sumo_smc.c b/drivers/gpu/drm/radeon/sumo_smc.c
index 7abbca6426d6..22c8151fb8f5 100644
--- a/drivers/gpu/drm/radeon/sumo_smc.c
+++ b/drivers/gpu/drm/radeon/sumo_smc.c
@@ -21,13 +21,11 @@
21 * 21 *
22 */ 22 */
23 23
24#include <linux/firmware.h>
25#include "drmP.h" 24#include "drmP.h"
26#include "radeon.h" 25#include "radeon.h"
27#include "sumod.h" 26#include "sumod.h"
28#include "sumo_dpm.h" 27#include "sumo_dpm.h"
29#include "ppsmc.h" 28#include "ppsmc.h"
30#include "radeon_ucode.h"
31 29
32#define SUMO_SMU_SERVICE_ROUTINE_PG_INIT 1 30#define SUMO_SMU_SERVICE_ROUTINE_PG_INIT 1
33#define SUMO_SMU_SERVICE_ROUTINE_ALTVDDNB_NOTIFY 27 31#define SUMO_SMU_SERVICE_ROUTINE_ALTVDDNB_NOTIFY 27
diff --git a/drivers/gpu/drm/radeon/trinity_dpm.c b/drivers/gpu/drm/radeon/trinity_dpm.c
new file mode 100644
index 000000000000..c4779a6ef48f
--- /dev/null
+++ b/drivers/gpu/drm/radeon/trinity_dpm.c
@@ -0,0 +1,1613 @@
1/*
2 * Copyright 2012 Advanced Micro Devices, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 */
23
24#include "drmP.h"
25#include "radeon.h"
26#include "trinityd.h"
27#include "r600_dpm.h"
28#include "trinity_dpm.h"
29
30#define TRINITY_MAX_DEEPSLEEP_DIVIDER_ID 5
31#define TRINITY_MINIMUM_ENGINE_CLOCK 800
32#define SCLK_MIN_DIV_INTV_SHIFT 12
33#define TRINITY_DISPCLK_BYPASS_THRESHOLD 10000
34
35#ifndef TRINITY_MGCG_SEQUENCE
36#define TRINITY_MGCG_SEQUENCE 100
37
38static const u32 trinity_mgcg_shls_default[] =
39{
40 /* Register, Value, Mask */
41 0x0000802c, 0xc0000000, 0xffffffff,
42 0x00003fc4, 0xc0000000, 0xffffffff,
43 0x00005448, 0x00000100, 0xffffffff,
44 0x000055e4, 0x00000100, 0xffffffff,
45 0x0000160c, 0x00000100, 0xffffffff,
46 0x00008984, 0x06000100, 0xffffffff,
47 0x0000c164, 0x00000100, 0xffffffff,
48 0x00008a18, 0x00000100, 0xffffffff,
49 0x0000897c, 0x06000100, 0xffffffff,
50 0x00008b28, 0x00000100, 0xffffffff,
51 0x00009144, 0x00800200, 0xffffffff,
52 0x00009a60, 0x00000100, 0xffffffff,
53 0x00009868, 0x00000100, 0xffffffff,
54 0x00008d58, 0x00000100, 0xffffffff,
55 0x00009510, 0x00000100, 0xffffffff,
56 0x0000949c, 0x00000100, 0xffffffff,
57 0x00009654, 0x00000100, 0xffffffff,
58 0x00009030, 0x00000100, 0xffffffff,
59 0x00009034, 0x00000100, 0xffffffff,
60 0x00009038, 0x00000100, 0xffffffff,
61 0x0000903c, 0x00000100, 0xffffffff,
62 0x00009040, 0x00000100, 0xffffffff,
63 0x0000a200, 0x00000100, 0xffffffff,
64 0x0000a204, 0x00000100, 0xffffffff,
65 0x0000a208, 0x00000100, 0xffffffff,
66 0x0000a20c, 0x00000100, 0xffffffff,
67 0x00009744, 0x00000100, 0xffffffff,
68 0x00003f80, 0x00000100, 0xffffffff,
69 0x0000a210, 0x00000100, 0xffffffff,
70 0x0000a214, 0x00000100, 0xffffffff,
71 0x000004d8, 0x00000100, 0xffffffff,
72 0x00009664, 0x00000100, 0xffffffff,
73 0x00009698, 0x00000100, 0xffffffff,
74 0x000004d4, 0x00000200, 0xffffffff,
75 0x000004d0, 0x00000000, 0xffffffff,
76 0x000030cc, 0x00000104, 0xffffffff,
77 0x0000d0c0, 0x00000100, 0xffffffff,
78 0x0000d8c0, 0x00000100, 0xffffffff,
79 0x0000951c, 0x00010000, 0xffffffff,
80 0x00009160, 0x00030002, 0xffffffff,
81 0x00009164, 0x00050004, 0xffffffff,
82 0x00009168, 0x00070006, 0xffffffff,
83 0x00009178, 0x00070000, 0xffffffff,
84 0x0000917c, 0x00030002, 0xffffffff,
85 0x00009180, 0x00050004, 0xffffffff,
86 0x0000918c, 0x00010006, 0xffffffff,
87 0x00009190, 0x00090008, 0xffffffff,
88 0x00009194, 0x00070000, 0xffffffff,
89 0x00009198, 0x00030002, 0xffffffff,
90 0x0000919c, 0x00050004, 0xffffffff,
91 0x000091a8, 0x00010006, 0xffffffff,
92 0x000091ac, 0x00090008, 0xffffffff,
93 0x000091b0, 0x00070000, 0xffffffff,
94 0x000091b4, 0x00030002, 0xffffffff,
95 0x000091b8, 0x00050004, 0xffffffff,
96 0x000091c4, 0x00010006, 0xffffffff,
97 0x000091c8, 0x00090008, 0xffffffff,
98 0x000091cc, 0x00070000, 0xffffffff,
99 0x000091d0, 0x00030002, 0xffffffff,
100 0x000091d4, 0x00050004, 0xffffffff,
101 0x000091e0, 0x00010006, 0xffffffff,
102 0x000091e4, 0x00090008, 0xffffffff,
103 0x000091e8, 0x00000000, 0xffffffff,
104 0x000091ec, 0x00070000, 0xffffffff,
105 0x000091f0, 0x00030002, 0xffffffff,
106 0x000091f4, 0x00050004, 0xffffffff,
107 0x00009200, 0x00010006, 0xffffffff,
108 0x00009204, 0x00090008, 0xffffffff,
109 0x00009208, 0x00070000, 0xffffffff,
110 0x0000920c, 0x00030002, 0xffffffff,
111 0x00009210, 0x00050004, 0xffffffff,
112 0x0000921c, 0x00010006, 0xffffffff,
113 0x00009220, 0x00090008, 0xffffffff,
114 0x00009294, 0x00000000, 0xffffffff
115};
116
117static const u32 trinity_mgcg_shls_enable[] =
118{
119 /* Register, Value, Mask */
120 0x0000802c, 0xc0000000, 0xffffffff,
121 0x000008f8, 0x00000000, 0xffffffff,
122 0x000008fc, 0x00000000, 0x000133FF,
123 0x000008f8, 0x00000001, 0xffffffff,
124 0x000008fc, 0x00000000, 0xE00B03FC,
125 0x00009150, 0x96944200, 0xffffffff
126};
127
128static const u32 trinity_mgcg_shls_disable[] =
129{
130 /* Register, Value, Mask */
131 0x0000802c, 0xc0000000, 0xffffffff,
132 0x00009150, 0x00600000, 0xffffffff,
133 0x000008f8, 0x00000000, 0xffffffff,
134 0x000008fc, 0xffffffff, 0x000133FF,
135 0x000008f8, 0x00000001, 0xffffffff,
136 0x000008fc, 0xffffffff, 0xE00B03FC
137};
138#endif
139
140#ifndef TRINITY_SYSLS_SEQUENCE
141#define TRINITY_SYSLS_SEQUENCE 100
142
143static const u32 trinity_sysls_default[] =
144{
145 /* Register, Value, Mask */
146 0x000055e8, 0x00000000, 0xffffffff,
147 0x0000d0bc, 0x00000000, 0xffffffff,
148 0x0000d8bc, 0x00000000, 0xffffffff,
149 0x000015c0, 0x000c1401, 0xffffffff,
150 0x0000264c, 0x000c0400, 0xffffffff,
151 0x00002648, 0x000c0400, 0xffffffff,
152 0x00002650, 0x000c0400, 0xffffffff,
153 0x000020b8, 0x000c0400, 0xffffffff,
154 0x000020bc, 0x000c0400, 0xffffffff,
155 0x000020c0, 0x000c0c80, 0xffffffff,
156 0x0000f4a0, 0x000000c0, 0xffffffff,
157 0x0000f4a4, 0x00680fff, 0xffffffff,
158 0x00002f50, 0x00000404, 0xffffffff,
159 0x000004c8, 0x00000001, 0xffffffff,
160 0x0000641c, 0x00000000, 0xffffffff,
161 0x00000c7c, 0x00000000, 0xffffffff,
162 0x00006dfc, 0x00000000, 0xffffffff
163};
164
165static const u32 trinity_sysls_disable[] =
166{
167 /* Register, Value, Mask */
168 0x0000d0c0, 0x00000000, 0xffffffff,
169 0x0000d8c0, 0x00000000, 0xffffffff,
170 0x000055e8, 0x00000000, 0xffffffff,
171 0x0000d0bc, 0x00000000, 0xffffffff,
172 0x0000d8bc, 0x00000000, 0xffffffff,
173 0x000015c0, 0x00041401, 0xffffffff,
174 0x0000264c, 0x00040400, 0xffffffff,
175 0x00002648, 0x00040400, 0xffffffff,
176 0x00002650, 0x00040400, 0xffffffff,
177 0x000020b8, 0x00040400, 0xffffffff,
178 0x000020bc, 0x00040400, 0xffffffff,
179 0x000020c0, 0x00040c80, 0xffffffff,
180 0x0000f4a0, 0x000000c0, 0xffffffff,
181 0x0000f4a4, 0x00680000, 0xffffffff,
182 0x00002f50, 0x00000404, 0xffffffff,
183 0x000004c8, 0x00000001, 0xffffffff,
184 0x0000641c, 0x00007ffd, 0xffffffff,
185 0x00000c7c, 0x0000ff00, 0xffffffff,
186 0x00006dfc, 0x0000007f, 0xffffffff
187};
188
189static const u32 trinity_sysls_enable[] =
190{
191 /* Register, Value, Mask */
192 0x000055e8, 0x00000001, 0xffffffff,
193 0x0000d0bc, 0x00000100, 0xffffffff,
194 0x0000d8bc, 0x00000100, 0xffffffff,
195 0x000015c0, 0x000c1401, 0xffffffff,
196 0x0000264c, 0x000c0400, 0xffffffff,
197 0x00002648, 0x000c0400, 0xffffffff,
198 0x00002650, 0x000c0400, 0xffffffff,
199 0x000020b8, 0x000c0400, 0xffffffff,
200 0x000020bc, 0x000c0400, 0xffffffff,
201 0x000020c0, 0x000c0c80, 0xffffffff,
202 0x0000f4a0, 0x000000c0, 0xffffffff,
203 0x0000f4a4, 0x00680fff, 0xffffffff,
204 0x00002f50, 0x00000903, 0xffffffff,
205 0x000004c8, 0x00000000, 0xffffffff,
206 0x0000641c, 0x00000000, 0xffffffff,
207 0x00000c7c, 0x00000000, 0xffffffff,
208 0x00006dfc, 0x00000000, 0xffffffff
209};
210#endif
211
212static const u32 trinity_override_mgpg_sequences[] =
213{
214 /* Register, Value */
215 0x00000200, 0xE030032C,
216 0x00000204, 0x00000FFF,
217 0x00000200, 0xE0300058,
218 0x00000204, 0x00030301,
219 0x00000200, 0xE0300054,
220 0x00000204, 0x500010FF,
221 0x00000200, 0xE0300074,
222 0x00000204, 0x00030301,
223 0x00000200, 0xE0300070,
224 0x00000204, 0x500010FF,
225 0x00000200, 0xE0300090,
226 0x00000204, 0x00030301,
227 0x00000200, 0xE030008C,
228 0x00000204, 0x500010FF,
229 0x00000200, 0xE03000AC,
230 0x00000204, 0x00030301,
231 0x00000200, 0xE03000A8,
232 0x00000204, 0x500010FF,
233 0x00000200, 0xE03000C8,
234 0x00000204, 0x00030301,
235 0x00000200, 0xE03000C4,
236 0x00000204, 0x500010FF,
237 0x00000200, 0xE03000E4,
238 0x00000204, 0x00030301,
239 0x00000200, 0xE03000E0,
240 0x00000204, 0x500010FF,
241 0x00000200, 0xE0300100,
242 0x00000204, 0x00030301,
243 0x00000200, 0xE03000FC,
244 0x00000204, 0x500010FF,
245 0x00000200, 0xE0300058,
246 0x00000204, 0x00030303,
247 0x00000200, 0xE0300054,
248 0x00000204, 0x600010FF,
249 0x00000200, 0xE0300074,
250 0x00000204, 0x00030303,
251 0x00000200, 0xE0300070,
252 0x00000204, 0x600010FF,
253 0x00000200, 0xE0300090,
254 0x00000204, 0x00030303,
255 0x00000200, 0xE030008C,
256 0x00000204, 0x600010FF,
257 0x00000200, 0xE03000AC,
258 0x00000204, 0x00030303,
259 0x00000200, 0xE03000A8,
260 0x00000204, 0x600010FF,
261 0x00000200, 0xE03000C8,
262 0x00000204, 0x00030303,
263 0x00000200, 0xE03000C4,
264 0x00000204, 0x600010FF,
265 0x00000200, 0xE03000E4,
266 0x00000204, 0x00030303,
267 0x00000200, 0xE03000E0,
268 0x00000204, 0x600010FF,
269 0x00000200, 0xE0300100,
270 0x00000204, 0x00030303,
271 0x00000200, 0xE03000FC,
272 0x00000204, 0x600010FF,
273 0x00000200, 0xE0300058,
274 0x00000204, 0x00030303,
275 0x00000200, 0xE0300054,
276 0x00000204, 0x700010FF,
277 0x00000200, 0xE0300074,
278 0x00000204, 0x00030303,
279 0x00000200, 0xE0300070,
280 0x00000204, 0x700010FF,
281 0x00000200, 0xE0300090,
282 0x00000204, 0x00030303,
283 0x00000200, 0xE030008C,
284 0x00000204, 0x700010FF,
285 0x00000200, 0xE03000AC,
286 0x00000204, 0x00030303,
287 0x00000200, 0xE03000A8,
288 0x00000204, 0x700010FF,
289 0x00000200, 0xE03000C8,
290 0x00000204, 0x00030303,
291 0x00000200, 0xE03000C4,
292 0x00000204, 0x700010FF,
293 0x00000200, 0xE03000E4,
294 0x00000204, 0x00030303,
295 0x00000200, 0xE03000E0,
296 0x00000204, 0x700010FF,
297 0x00000200, 0xE0300100,
298 0x00000204, 0x00030303,
299 0x00000200, 0xE03000FC,
300 0x00000204, 0x700010FF,
301 0x00000200, 0xE0300058,
302 0x00000204, 0x00010303,
303 0x00000200, 0xE0300054,
304 0x00000204, 0x800010FF,
305 0x00000200, 0xE0300074,
306 0x00000204, 0x00010303,
307 0x00000200, 0xE0300070,
308 0x00000204, 0x800010FF,
309 0x00000200, 0xE0300090,
310 0x00000204, 0x00010303,
311 0x00000200, 0xE030008C,
312 0x00000204, 0x800010FF,
313 0x00000200, 0xE03000AC,
314 0x00000204, 0x00010303,
315 0x00000200, 0xE03000A8,
316 0x00000204, 0x800010FF,
317 0x00000200, 0xE03000C4,
318 0x00000204, 0x800010FF,
319 0x00000200, 0xE03000C8,
320 0x00000204, 0x00010303,
321 0x00000200, 0xE03000E4,
322 0x00000204, 0x00010303,
323 0x00000200, 0xE03000E0,
324 0x00000204, 0x800010FF,
325 0x00000200, 0xE0300100,
326 0x00000204, 0x00010303,
327 0x00000200, 0xE03000FC,
328 0x00000204, 0x800010FF,
329 0x00000200, 0x0001f198,
330 0x00000204, 0x0003ffff,
331 0x00000200, 0x0001f19C,
332 0x00000204, 0x3fffffff,
333 0x00000200, 0xE030032C,
334 0x00000204, 0x00000000,
335};
336
337static void trinity_program_clk_gating_hw_sequence(struct radeon_device *rdev,
338 const u32 *seq, u32 count);
339static void trinity_override_dynamic_mg_powergating(struct radeon_device *rdev);
340static void trinity_apply_state_adjust_rules(struct radeon_device *rdev);
341
342struct trinity_ps *trinity_get_ps(struct radeon_ps *rps)
343{
344 struct trinity_ps *ps = rps->ps_priv;
345
346 return ps;
347}
348
349struct trinity_power_info *trinity_get_pi(struct radeon_device *rdev)
350{
351 struct trinity_power_info *pi = rdev->pm.dpm.priv;
352
353 return pi;
354}
355
356static void trinity_gfx_powergating_initialize(struct radeon_device *rdev)
357{
358 struct trinity_power_info *pi = trinity_get_pi(rdev);
359 u32 p, u;
360 u32 value;
361 struct atom_clock_dividers dividers;
362 u32 xclk = sumo_get_xclk(rdev);
363 u32 sssd = 1;
364 int ret;
365 u32 hw_rev = (RREG32(HW_REV) & ATI_REV_ID_MASK) >> ATI_REV_ID_SHIFT;
366
367 ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
368 25000, false, &dividers);
369 if (ret)
370 return;
371
372 value = RREG32_SMC(GFX_POWER_GATING_CNTL);
373 value &= ~(SSSD_MASK | PDS_DIV_MASK);
374 if (sssd)
375 value |= SSSD(1);
376 value |= PDS_DIV(dividers.post_div);
377 WREG32_SMC(GFX_POWER_GATING_CNTL, value);
378
379 r600_calculate_u_and_p(500, xclk, 16, &p, &u);
380
381 WREG32(CG_PG_CTRL, SP(p) | SU(u));
382
383 WREG32_P(CG_GIPOTS, CG_GIPOT(p), ~CG_GIPOT_MASK);
384
385 /* XXX double check hw_rev */
386 if (pi->override_dynamic_mgpg && (hw_rev == 0))
387 trinity_override_dynamic_mg_powergating(rdev);
388
389}
390
391#define CGCG_CGTT_LOCAL0_MASK 0xFFFF33FF
392#define CGCG_CGTT_LOCAL1_MASK 0xFFFB0FFE
393#define CGTS_SM_CTRL_REG_DISABLE 0x00600000
394#define CGTS_SM_CTRL_REG_ENABLE 0x96944200
395
396static void trinity_mg_clockgating_enable(struct radeon_device *rdev,
397 bool enable)
398{
399 u32 local0;
400 u32 local1;
401
402 if (enable) {
403 local0 = RREG32_CG(CG_CGTT_LOCAL_0);
404 local1 = RREG32_CG(CG_CGTT_LOCAL_1);
405
406 WREG32_CG(CG_CGTT_LOCAL_0,
407 (0x00380000 & CGCG_CGTT_LOCAL0_MASK) | (local0 & ~CGCG_CGTT_LOCAL0_MASK) );
408 WREG32_CG(CG_CGTT_LOCAL_1,
409 (0x0E000000 & CGCG_CGTT_LOCAL1_MASK) | (local1 & ~CGCG_CGTT_LOCAL1_MASK) );
410
411 WREG32(CGTS_SM_CTRL_REG, CGTS_SM_CTRL_REG_ENABLE);
412 } else {
413 WREG32(CGTS_SM_CTRL_REG, CGTS_SM_CTRL_REG_DISABLE);
414
415 local0 = RREG32_CG(CG_CGTT_LOCAL_0);
416 local1 = RREG32_CG(CG_CGTT_LOCAL_1);
417
418 WREG32_CG(CG_CGTT_LOCAL_0,
419 CGCG_CGTT_LOCAL0_MASK | (local0 & ~CGCG_CGTT_LOCAL0_MASK) );
420 WREG32_CG(CG_CGTT_LOCAL_1,
421 CGCG_CGTT_LOCAL1_MASK | (local1 & ~CGCG_CGTT_LOCAL1_MASK) );
422 }
423}
424
425static void trinity_mg_clockgating_initialize(struct radeon_device *rdev)
426{
427 u32 count;
428 const u32 *seq = NULL;
429
430 seq = &trinity_mgcg_shls_default[0];
431 count = sizeof(trinity_mgcg_shls_default) / (3 * sizeof(u32));
432
433 trinity_program_clk_gating_hw_sequence(rdev, seq, count);
434}
435
436static void trinity_gfx_clockgating_enable(struct radeon_device *rdev,
437 bool enable)
438{
439 if (enable) {
440 WREG32_P(SCLK_PWRMGT_CNTL, DYN_GFX_CLK_OFF_EN, ~DYN_GFX_CLK_OFF_EN);
441 } else {
442 WREG32_P(SCLK_PWRMGT_CNTL, 0, ~DYN_GFX_CLK_OFF_EN);
443 WREG32_P(SCLK_PWRMGT_CNTL, GFX_CLK_FORCE_ON, ~GFX_CLK_FORCE_ON);
444 WREG32_P(SCLK_PWRMGT_CNTL, 0, ~GFX_CLK_FORCE_ON);
445 RREG32(GB_ADDR_CONFIG);
446 }
447}
448
449static void trinity_program_clk_gating_hw_sequence(struct radeon_device *rdev,
450 const u32 *seq, u32 count)
451{
452 u32 i, length = count * 3;
453
454 for (i = 0; i < length; i += 3)
455 WREG32_P(seq[i], seq[i+1], ~seq[i+2]);
456}
457
458static void trinity_program_override_mgpg_sequences(struct radeon_device *rdev,
459 const u32 *seq, u32 count)
460{
461 u32 i, length = count * 2;
462
463 for (i = 0; i < length; i += 2)
464 WREG32(seq[i], seq[i+1]);
465
466}
467
468static void trinity_override_dynamic_mg_powergating(struct radeon_device *rdev)
469{
470 u32 count;
471 const u32 *seq = NULL;
472
473 seq = &trinity_override_mgpg_sequences[0];
474 count = sizeof(trinity_override_mgpg_sequences) / (2 * sizeof(u32));
475
476 trinity_program_override_mgpg_sequences(rdev, seq, count);
477}
478
479static void trinity_ls_clockgating_enable(struct radeon_device *rdev,
480 bool enable)
481{
482 u32 count;
483 const u32 *seq = NULL;
484
485 if (enable) {
486 seq = &trinity_sysls_enable[0];
487 count = sizeof(trinity_sysls_enable) / (3 * sizeof(u32));
488 } else {
489 seq = &trinity_sysls_disable[0];
490 count = sizeof(trinity_sysls_disable) / (3 * sizeof(u32));
491 }
492
493 trinity_program_clk_gating_hw_sequence(rdev, seq, count);
494}
495
496static void trinity_gfx_powergating_enable(struct radeon_device *rdev,
497 bool enable)
498{
499 if (enable) {
500 if (RREG32_SMC(CC_SMU_TST_EFUSE1_MISC) & RB_BACKEND_DISABLE_MASK)
501 WREG32_SMC(SMU_SCRATCH_A, (RREG32_SMC(SMU_SCRATCH_A) | 0x01));
502
503 WREG32_P(SCLK_PWRMGT_CNTL, DYN_PWR_DOWN_EN, ~DYN_PWR_DOWN_EN);
504 } else {
505 WREG32_P(SCLK_PWRMGT_CNTL, 0, ~DYN_PWR_DOWN_EN);
506 RREG32(GB_ADDR_CONFIG);
507 }
508}
509
510static void trinity_gfx_dynamic_mgpg_enable(struct radeon_device *rdev,
511 bool enable)
512{
513 u32 value;
514
515 if (enable) {
516 value = RREG32_SMC(PM_I_CNTL_1);
517 value &= ~DS_PG_CNTL_MASK;
518 value |= DS_PG_CNTL(1);
519 WREG32_SMC(PM_I_CNTL_1, value);
520
521 value = RREG32_SMC(SMU_S_PG_CNTL);
522 value &= ~DS_PG_EN_MASK;
523 value |= DS_PG_EN(1);
524 WREG32_SMC(SMU_S_PG_CNTL, value);
525 } else {
526 value = RREG32_SMC(SMU_S_PG_CNTL);
527 value &= ~DS_PG_EN_MASK;
528 WREG32_SMC(SMU_S_PG_CNTL, value);
529
530 value = RREG32_SMC(PM_I_CNTL_1);
531 value &= ~DS_PG_CNTL_MASK;
532 WREG32_SMC(PM_I_CNTL_1, value);
533 }
534
535 trinity_gfx_dynamic_mgpg_config(rdev);
536
537}
538
539static void trinity_enable_clock_power_gating(struct radeon_device *rdev)
540{
541 struct trinity_power_info *pi = trinity_get_pi(rdev);
542
543 if (pi->enable_gfx_clock_gating)
544 sumo_gfx_clockgating_initialize(rdev);
545 if (pi->enable_mg_clock_gating)
546 trinity_mg_clockgating_initialize(rdev);
547 if (pi->enable_gfx_power_gating)
548 trinity_gfx_powergating_initialize(rdev);
549 if (pi->enable_mg_clock_gating) {
550 trinity_ls_clockgating_enable(rdev, true);
551 trinity_mg_clockgating_enable(rdev, true);
552 }
553 if (pi->enable_gfx_clock_gating)
554 trinity_gfx_clockgating_enable(rdev, true);
555 if (pi->enable_gfx_dynamic_mgpg)
556 trinity_gfx_dynamic_mgpg_enable(rdev, true);
557 if (pi->enable_gfx_power_gating)
558 trinity_gfx_powergating_enable(rdev, true);
559}
560
561static void trinity_disable_clock_power_gating(struct radeon_device *rdev)
562{
563 struct trinity_power_info *pi = trinity_get_pi(rdev);
564
565 if (pi->enable_gfx_power_gating)
566 trinity_gfx_powergating_enable(rdev, false);
567 if (pi->enable_gfx_dynamic_mgpg)
568 trinity_gfx_dynamic_mgpg_enable(rdev, false);
569 if (pi->enable_gfx_clock_gating)
570 trinity_gfx_clockgating_enable(rdev, false);
571 if (pi->enable_mg_clock_gating) {
572 trinity_mg_clockgating_enable(rdev, false);
573 trinity_ls_clockgating_enable(rdev, false);
574 }
575}
576
577static void trinity_set_divider_value(struct radeon_device *rdev,
578 u32 index, u32 sclk)
579{
580 struct atom_clock_dividers dividers;
581 int ret;
582 u32 value;
583 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
584
585 ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
586 sclk, false, &dividers);
587 if (ret)
588 return;
589
590 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix);
591 value &= ~CLK_DIVIDER_MASK;
592 value |= CLK_DIVIDER(dividers.post_div);
593 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix, value);
594
595 ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
596 sclk/2, false, &dividers);
597 if (ret)
598 return;
599
600 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_PG_CNTL + ix);
601 value &= ~PD_SCLK_DIVIDER_MASK;
602 value |= PD_SCLK_DIVIDER(dividers.post_div);
603 WREG32_SMC(SMU_SCLK_DPM_STATE_0_PG_CNTL + ix, value);
604}
605
606static void trinity_set_ds_dividers(struct radeon_device *rdev,
607 u32 index, u32 divider)
608{
609 u32 value;
610 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
611
612 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix);
613 value &= ~DS_DIV_MASK;
614 value |= DS_DIV(divider);
615 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix, value);
616}
617
618static void trinity_set_ss_dividers(struct radeon_device *rdev,
619 u32 index, u32 divider)
620{
621 u32 value;
622 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
623
624 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix);
625 value &= ~DS_SH_DIV_MASK;
626 value |= DS_SH_DIV(divider);
627 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix, value);
628}
629
630static void trinity_set_vid(struct radeon_device *rdev, u32 index, u32 vid)
631{
632 struct trinity_power_info *pi = trinity_get_pi(rdev);
633 u32 vid_7bit = sumo_convert_vid2_to_vid7(rdev, &pi->sys_info.vid_mapping_table, vid);
634 u32 value;
635 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
636
637 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix);
638 value &= ~VID_MASK;
639 value |= VID(vid_7bit);
640 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix, value);
641
642 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix);
643 value &= ~LVRT_MASK;
644 value |= LVRT(0);
645 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix, value);
646}
647
648static void trinity_set_allos_gnb_slow(struct radeon_device *rdev,
649 u32 index, u32 gnb_slow)
650{
651 u32 value;
652 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
653
654 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_3 + ix);
655 value &= ~GNB_SLOW_MASK;
656 value |= GNB_SLOW(gnb_slow);
657 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_3 + ix, value);
658}
659
660static void trinity_set_force_nbp_state(struct radeon_device *rdev,
661 u32 index, u32 force_nbp_state)
662{
663 u32 value;
664 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
665
666 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_3 + ix);
667 value &= ~FORCE_NBPS1_MASK;
668 value |= FORCE_NBPS1(force_nbp_state);
669 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_3 + ix, value);
670}
671
672static void trinity_set_display_wm(struct radeon_device *rdev,
673 u32 index, u32 wm)
674{
675 u32 value;
676 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
677
678 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix);
679 value &= ~DISPLAY_WM_MASK;
680 value |= DISPLAY_WM(wm);
681 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix, value);
682}
683
684static void trinity_set_vce_wm(struct radeon_device *rdev,
685 u32 index, u32 wm)
686{
687 u32 value;
688 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
689
690 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix);
691 value &= ~VCE_WM_MASK;
692 value |= VCE_WM(wm);
693 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix, value);
694}
695
696static void trinity_set_at(struct radeon_device *rdev,
697 u32 index, u32 at)
698{
699 u32 value;
700 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
701
702 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_AT + ix);
703 value &= ~AT_MASK;
704 value |= AT(at);
705 WREG32_SMC(SMU_SCLK_DPM_STATE_0_AT + ix, value);
706}
707
708static void trinity_program_power_level(struct radeon_device *rdev,
709 struct trinity_pl *pl, u32 index)
710{
711 struct trinity_power_info *pi = trinity_get_pi(rdev);
712
713 if (index >= SUMO_MAX_HARDWARE_POWERLEVELS)
714 return;
715
716 trinity_set_divider_value(rdev, index, pl->sclk);
717 trinity_set_vid(rdev, index, pl->vddc_index);
718 trinity_set_ss_dividers(rdev, index, pl->ss_divider_index);
719 trinity_set_ds_dividers(rdev, index, pl->ds_divider_index);
720 trinity_set_allos_gnb_slow(rdev, index, pl->allow_gnb_slow);
721 trinity_set_force_nbp_state(rdev, index, pl->force_nbp_state);
722 trinity_set_display_wm(rdev, index, pl->display_wm);
723 trinity_set_vce_wm(rdev, index, pl->vce_wm);
724 trinity_set_at(rdev, index, pi->at[index]);
725}
726
727static void trinity_power_level_enable_disable(struct radeon_device *rdev,
728 u32 index, bool enable)
729{
730 u32 value;
731 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
732
733 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix);
734 value &= ~STATE_VALID_MASK;
735 if (enable)
736 value |= STATE_VALID(1);
737 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix, value);
738}
739
740static bool trinity_dpm_enabled(struct radeon_device *rdev)
741{
742 if (RREG32_SMC(SMU_SCLK_DPM_CNTL) & SCLK_DPM_EN(1))
743 return true;
744 else
745 return false;
746}
747
748static void trinity_start_dpm(struct radeon_device *rdev)
749{
750 u32 value = RREG32_SMC(SMU_SCLK_DPM_CNTL);
751
752 value &= ~(SCLK_DPM_EN_MASK | SCLK_DPM_BOOT_STATE_MASK | VOLTAGE_CHG_EN_MASK);
753 value |= SCLK_DPM_EN(1) | SCLK_DPM_BOOT_STATE(0) | VOLTAGE_CHG_EN(1);
754 WREG32_SMC(SMU_SCLK_DPM_CNTL, value);
755
756 WREG32_P(GENERAL_PWRMGT, GLOBAL_PWRMGT_EN, ~GLOBAL_PWRMGT_EN);
757 WREG32_P(CG_CG_VOLTAGE_CNTL, 0, ~EN);
758
759 trinity_dpm_config(rdev, true);
760}
761
762static void trinity_wait_for_dpm_enabled(struct radeon_device *rdev)
763{
764 int i;
765
766 for (i = 0; i < rdev->usec_timeout; i++) {
767 if (RREG32(SCLK_PWRMGT_CNTL) & DYNAMIC_PM_EN)
768 break;
769 udelay(1);
770 }
771 for (i = 0; i < rdev->usec_timeout; i++) {
772 if ((RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & TARGET_STATE_MASK) == 0)
773 break;
774 udelay(1);
775 }
776 for (i = 0; i < rdev->usec_timeout; i++) {
777 if ((RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_MASK) == 0)
778 break;
779 udelay(1);
780 }
781}
782
783static void trinity_stop_dpm(struct radeon_device *rdev)
784{
785 u32 sclk_dpm_cntl;
786
787 WREG32_P(CG_CG_VOLTAGE_CNTL, EN, ~EN);
788
789 sclk_dpm_cntl = RREG32_SMC(SMU_SCLK_DPM_CNTL);
790 sclk_dpm_cntl &= ~(SCLK_DPM_EN_MASK | VOLTAGE_CHG_EN_MASK);
791 WREG32_SMC(SMU_SCLK_DPM_CNTL, sclk_dpm_cntl);
792
793 trinity_dpm_config(rdev, false);
794}
795
796static void trinity_start_am(struct radeon_device *rdev)
797{
798 WREG32_P(SCLK_PWRMGT_CNTL, 0, ~(RESET_SCLK_CNT | RESET_BUSY_CNT));
799}
800
801static void trinity_reset_am(struct radeon_device *rdev)
802{
803 WREG32_P(SCLK_PWRMGT_CNTL, RESET_SCLK_CNT | RESET_BUSY_CNT,
804 ~(RESET_SCLK_CNT | RESET_BUSY_CNT));
805}
806
807static void trinity_wait_for_level_0(struct radeon_device *rdev)
808{
809 int i;
810
811 for (i = 0; i < rdev->usec_timeout; i++) {
812 if ((RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_MASK) == 0)
813 break;
814 udelay(1);
815 }
816}
817
818static void trinity_enable_power_level_0(struct radeon_device *rdev)
819{
820 trinity_power_level_enable_disable(rdev, 0, true);
821}
822
823static void trinity_force_level_0(struct radeon_device *rdev)
824{
825 trinity_dpm_force_state(rdev, 0);
826}
827
828static void trinity_unforce_levels(struct radeon_device *rdev)
829{
830 trinity_dpm_no_forced_level(rdev);
831}
832
833static void trinity_update_current_power_levels(struct radeon_device *rdev)
834{
835 struct trinity_ps *new_ps = trinity_get_ps(rdev->pm.dpm.requested_ps);
836 struct trinity_power_info *pi = trinity_get_pi(rdev);
837
838 pi->current_ps = *new_ps;
839}
840
841static void trinity_program_power_levels_0_to_n(struct radeon_device *rdev)
842{
843 struct trinity_ps *new_ps = trinity_get_ps(rdev->pm.dpm.requested_ps);
844 struct trinity_ps *old_ps = trinity_get_ps(rdev->pm.dpm.current_ps);
845 u32 i;
846 u32 n_current_state_levels = (old_ps == NULL) ? 1 : old_ps->num_levels;
847
848 for (i = 0; i < new_ps->num_levels; i++) {
849 trinity_program_power_level(rdev, &new_ps->levels[i], i);
850 trinity_power_level_enable_disable(rdev, i, true);
851 }
852
853 for (i = new_ps->num_levels; i < n_current_state_levels; i++)
854 trinity_power_level_enable_disable(rdev, i, false);
855}
856
857static void trinity_program_bootup_state(struct radeon_device *rdev)
858{
859 struct trinity_power_info *pi = trinity_get_pi(rdev);
860 u32 i;
861
862 trinity_program_power_level(rdev, &pi->boot_pl, 0);
863 trinity_power_level_enable_disable(rdev, 0, true);
864
865 for (i = 1; i < 8; i++)
866 trinity_power_level_enable_disable(rdev, i, false);
867}
868
869static void trinity_program_ttt(struct radeon_device *rdev)
870{
871 struct trinity_power_info *pi = trinity_get_pi(rdev);
872 u32 value = RREG32_SMC(SMU_SCLK_DPM_TTT);
873
874 value &= ~(HT_MASK | LT_MASK);
875 value |= HT((pi->thermal_auto_throttling + 49) * 8);
876 value |= LT((pi->thermal_auto_throttling + 49 - pi->sys_info.htc_hyst_lmt) * 8);
877 WREG32_SMC(SMU_SCLK_DPM_TTT, value);
878}
879
880static void trinity_enable_att(struct radeon_device *rdev)
881{
882 u32 value = RREG32_SMC(SMU_SCLK_DPM_TT_CNTL);
883
884 value &= ~SCLK_TT_EN_MASK;
885 value |= SCLK_TT_EN(1);
886 WREG32_SMC(SMU_SCLK_DPM_TT_CNTL, value);
887}
888
889static void trinity_program_sclk_dpm(struct radeon_device *rdev)
890{
891 u32 p, u;
892 u32 tp = RREG32_SMC(PM_TP);
893 u32 ni;
894 u32 xclk = sumo_get_xclk(rdev);
895 u32 value;
896
897 r600_calculate_u_and_p(400, xclk, 16, &p, &u);
898
899 ni = (p + tp - 1) / tp;
900
901 value = RREG32_SMC(PM_I_CNTL_1);
902 value &= ~SCLK_DPM_MASK;
903 value |= SCLK_DPM(ni);
904 WREG32_SMC(PM_I_CNTL_1, value);
905}
906
907static int trinity_set_thermal_temperature_range(struct radeon_device *rdev,
908 int min_temp, int max_temp)
909{
910 int low_temp = 0 * 1000;
911 int high_temp = 255 * 1000;
912
913 if (low_temp < min_temp)
914 low_temp = min_temp;
915 if (high_temp > max_temp)
916 high_temp = max_temp;
917 if (high_temp < low_temp) {
918 DRM_ERROR("invalid thermal range: %d - %d\n", low_temp, high_temp);
919 return -EINVAL;
920 }
921
922 WREG32_P(CG_THERMAL_INT_CTRL, DIG_THERM_INTH(49 + (high_temp / 1000)), ~DIG_THERM_INTH_MASK);
923 WREG32_P(CG_THERMAL_INT_CTRL, DIG_THERM_INTL(49 + (low_temp / 1000)), ~DIG_THERM_INTL_MASK);
924
925 rdev->pm.dpm.thermal.min_temp = low_temp;
926 rdev->pm.dpm.thermal.max_temp = high_temp;
927
928 return 0;
929}
930
931int trinity_dpm_enable(struct radeon_device *rdev)
932{
933 struct trinity_power_info *pi = trinity_get_pi(rdev);
934
935 trinity_acquire_mutex(rdev);
936
937 if (trinity_dpm_enabled(rdev)) {
938 trinity_release_mutex(rdev);
939 return -EINVAL;
940 }
941
942 trinity_enable_clock_power_gating(rdev);
943 trinity_program_bootup_state(rdev);
944 sumo_program_vc(rdev, 0x00C00033);
945 trinity_start_am(rdev);
946 if (pi->enable_auto_thermal_throttling) {
947 trinity_program_ttt(rdev);
948 trinity_enable_att(rdev);
949 }
950 trinity_program_sclk_dpm(rdev);
951 trinity_start_dpm(rdev);
952 trinity_wait_for_dpm_enabled(rdev);
953 trinity_release_mutex(rdev);
954
955 if (rdev->irq.installed &&
956 r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
957 trinity_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX);
958 rdev->irq.dpm_thermal = true;
959 radeon_irq_set(rdev);
960 }
961
962 return 0;
963}
964
965void trinity_dpm_disable(struct radeon_device *rdev)
966{
967 trinity_acquire_mutex(rdev);
968 if (!trinity_dpm_enabled(rdev)) {
969 trinity_release_mutex(rdev);
970 return;
971 }
972 trinity_disable_clock_power_gating(rdev);
973 sumo_clear_vc(rdev);
974 trinity_wait_for_level_0(rdev);
975 trinity_stop_dpm(rdev);
976 trinity_reset_am(rdev);
977 trinity_release_mutex(rdev);
978
979 if (rdev->irq.installed &&
980 r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
981 rdev->irq.dpm_thermal = false;
982 radeon_irq_set(rdev);
983 }
984}
985
986static void trinity_get_min_sclk_divider(struct radeon_device *rdev)
987{
988 struct trinity_power_info *pi = trinity_get_pi(rdev);
989
990 pi->min_sclk_did =
991 (RREG32_SMC(CC_SMU_MISC_FUSES) & MinSClkDid_MASK) >> MinSClkDid_SHIFT;
992}
993
994static void trinity_setup_nbp_sim(struct radeon_device *rdev)
995{
996 struct trinity_power_info *pi = trinity_get_pi(rdev);
997 struct trinity_ps *new_ps = trinity_get_ps(rdev->pm.dpm.requested_ps);
998 u32 nbpsconfig;
999
1000 if (pi->sys_info.nb_dpm_enable) {
1001 nbpsconfig = RREG32_SMC(NB_PSTATE_CONFIG);
1002 nbpsconfig &= ~(Dpm0PgNbPsLo_MASK | Dpm0PgNbPsHi_MASK | DpmXNbPsLo_MASK | DpmXNbPsHi_MASK);
1003 nbpsconfig |= (Dpm0PgNbPsLo(new_ps->Dpm0PgNbPsLo) |
1004 Dpm0PgNbPsHi(new_ps->Dpm0PgNbPsHi) |
1005 DpmXNbPsLo(new_ps->DpmXNbPsLo) |
1006 DpmXNbPsHi(new_ps->DpmXNbPsHi));
1007 WREG32_SMC(NB_PSTATE_CONFIG, nbpsconfig);
1008 }
1009}
1010
1011int trinity_dpm_set_power_state(struct radeon_device *rdev)
1012{
1013 struct trinity_power_info *pi = trinity_get_pi(rdev);
1014
1015 trinity_apply_state_adjust_rules(rdev);
1016 trinity_update_current_power_levels(rdev);
1017
1018 trinity_acquire_mutex(rdev);
1019 if (pi->enable_dpm) {
1020 trinity_enable_power_level_0(rdev);
1021 trinity_force_level_0(rdev);
1022 trinity_wait_for_level_0(rdev);
1023 trinity_setup_nbp_sim(rdev);
1024 trinity_program_power_levels_0_to_n(rdev);
1025 trinity_force_level_0(rdev);
1026 trinity_unforce_levels(rdev);
1027 }
1028 trinity_release_mutex(rdev);
1029
1030 return 0;
1031}
1032
1033void trinity_dpm_setup_asic(struct radeon_device *rdev)
1034{
1035 trinity_acquire_mutex(rdev);
1036 sumo_program_sstp(rdev);
1037 sumo_take_smu_control(rdev, true);
1038 trinity_get_min_sclk_divider(rdev);
1039 trinity_release_mutex(rdev);
1040}
1041
1042void trinity_dpm_reset_asic(struct radeon_device *rdev)
1043{
1044 struct trinity_power_info *pi = trinity_get_pi(rdev);
1045
1046 trinity_acquire_mutex(rdev);
1047 if (pi->enable_dpm) {
1048 trinity_enable_power_level_0(rdev);
1049 trinity_force_level_0(rdev);
1050 trinity_wait_for_level_0(rdev);
1051 trinity_program_bootup_state(rdev);
1052 trinity_force_level_0(rdev);
1053 trinity_unforce_levels(rdev);
1054 }
1055 trinity_release_mutex(rdev);
1056}
1057
1058static u16 trinity_convert_voltage_index_to_value(struct radeon_device *rdev,
1059 u32 vid_2bit)
1060{
1061 struct trinity_power_info *pi = trinity_get_pi(rdev);
1062 u32 vid_7bit = sumo_convert_vid2_to_vid7(rdev, &pi->sys_info.vid_mapping_table, vid_2bit);
1063 u32 svi_mode = (RREG32_SMC(PM_CONFIG) & SVI_Mode) ? 1 : 0;
1064 u32 step = (svi_mode == 0) ? 1250 : 625;
1065 u32 delta = vid_7bit * step + 50;
1066
1067 if (delta > 155000)
1068 return 0;
1069
1070 return (155000 - delta) / 100;
1071}
1072
1073static void trinity_patch_boot_state(struct radeon_device *rdev,
1074 struct trinity_ps *ps)
1075{
1076 struct trinity_power_info *pi = trinity_get_pi(rdev);
1077
1078 ps->num_levels = 1;
1079 ps->nbps_flags = 0;
1080 ps->bapm_flags = 0;
1081 ps->levels[0] = pi->boot_pl;
1082}
1083
1084static u8 trinity_calculate_vce_wm(struct radeon_device *rdev, u32 sclk)
1085{
1086 if (sclk < 20000)
1087 return 1;
1088 return 0;
1089}
1090
1091static void trinity_construct_boot_state(struct radeon_device *rdev)
1092{
1093 struct trinity_power_info *pi = trinity_get_pi(rdev);
1094
1095 pi->boot_pl.sclk = pi->sys_info.bootup_sclk;
1096 pi->boot_pl.vddc_index = pi->sys_info.bootup_nb_voltage_index;
1097 pi->boot_pl.ds_divider_index = 0;
1098 pi->boot_pl.ss_divider_index = 0;
1099 pi->boot_pl.allow_gnb_slow = 1;
1100 pi->boot_pl.force_nbp_state = 0;
1101 pi->boot_pl.display_wm = 0;
1102 pi->boot_pl.vce_wm = 0;
1103 pi->current_ps.num_levels = 1;
1104 pi->current_ps.levels[0] = pi->boot_pl;
1105}
1106
1107static u8 trinity_get_sleep_divider_id_from_clock(struct radeon_device *rdev,
1108 u32 sclk, u32 min_sclk_in_sr)
1109{
1110 struct trinity_power_info *pi = trinity_get_pi(rdev);
1111 u32 i;
1112 u32 temp;
1113 u32 min = (min_sclk_in_sr > TRINITY_MINIMUM_ENGINE_CLOCK) ?
1114 min_sclk_in_sr : TRINITY_MINIMUM_ENGINE_CLOCK;
1115
1116 if (sclk < min)
1117 return 0;
1118
1119 if (!pi->enable_sclk_ds)
1120 return 0;
1121
1122 for (i = TRINITY_MAX_DEEPSLEEP_DIVIDER_ID; ; i--) {
1123 temp = sclk / sumo_get_sleep_divider_from_id(i);
1124 if (temp >= min || i == 0)
1125 break;
1126 }
1127
1128 return (u8)i;
1129}
1130
1131static u32 trinity_get_valid_engine_clock(struct radeon_device *rdev,
1132 u32 lower_limit)
1133{
1134 struct trinity_power_info *pi = trinity_get_pi(rdev);
1135 u32 i;
1136
1137 for (i = 0; i < pi->sys_info.sclk_voltage_mapping_table.num_max_dpm_entries; i++) {
1138 if (pi->sys_info.sclk_voltage_mapping_table.entries[i].sclk_frequency >= lower_limit)
1139 return pi->sys_info.sclk_voltage_mapping_table.entries[i].sclk_frequency;
1140 }
1141
1142 if (i == pi->sys_info.sclk_voltage_mapping_table.num_max_dpm_entries)
1143 DRM_ERROR("engine clock out of range!");
1144
1145 return 0;
1146}
1147
1148static void trinity_patch_thermal_state(struct radeon_device *rdev,
1149 struct trinity_ps *ps,
1150 struct trinity_ps *current_ps)
1151{
1152 struct trinity_power_info *pi = trinity_get_pi(rdev);
1153 u32 sclk_in_sr = pi->sys_info.min_sclk; /* ??? */
1154 u32 current_vddc;
1155 u32 current_sclk;
1156 u32 current_index = 0;
1157
1158 if (current_ps) {
1159 current_vddc = current_ps->levels[current_index].vddc_index;
1160 current_sclk = current_ps->levels[current_index].sclk;
1161 } else {
1162 current_vddc = pi->boot_pl.vddc_index;
1163 current_sclk = pi->boot_pl.sclk;
1164 }
1165
1166 ps->levels[0].vddc_index = current_vddc;
1167
1168 if (ps->levels[0].sclk > current_sclk)
1169 ps->levels[0].sclk = current_sclk;
1170
1171 ps->levels[0].ds_divider_index =
1172 trinity_get_sleep_divider_id_from_clock(rdev, ps->levels[0].sclk, sclk_in_sr);
1173 ps->levels[0].ss_divider_index = ps->levels[0].ds_divider_index;
1174 ps->levels[0].allow_gnb_slow = 1;
1175 ps->levels[0].force_nbp_state = 0;
1176 ps->levels[0].display_wm = 0;
1177 ps->levels[0].vce_wm =
1178 trinity_calculate_vce_wm(rdev, ps->levels[0].sclk);
1179}
1180
1181static u8 trinity_calculate_display_wm(struct radeon_device *rdev,
1182 struct trinity_ps *ps, u32 index)
1183{
1184 if (ps == NULL || ps->num_levels <= 1)
1185 return 0;
1186 else if (ps->num_levels == 2) {
1187 if (index == 0)
1188 return 0;
1189 else
1190 return 1;
1191 } else {
1192 if (index == 0)
1193 return 0;
1194 else if (ps->levels[index].sclk < 30000)
1195 return 0;
1196 else
1197 return 1;
1198 }
1199}
1200
1201static void trinity_apply_state_adjust_rules(struct radeon_device *rdev)
1202{
1203 struct radeon_ps *rps = rdev->pm.dpm.requested_ps;
1204 struct trinity_ps *ps = trinity_get_ps(rps);
1205 struct trinity_ps *current_ps = trinity_get_ps(rdev->pm.dpm.current_ps);
1206 struct trinity_power_info *pi = trinity_get_pi(rdev);
1207 u32 min_voltage = 0; /* ??? */
1208 u32 min_sclk = pi->sys_info.min_sclk; /* XXX check against disp reqs */
1209 u32 sclk_in_sr = pi->sys_info.min_sclk; /* ??? */
1210 u32 i;
1211 bool force_high;
1212 u32 num_active_displays = rdev->pm.dpm.new_active_crtc_count;
1213
1214 if (rps->class & ATOM_PPLIB_CLASSIFICATION_THERMAL)
1215 return trinity_patch_thermal_state(rdev, ps, current_ps);
1216
1217 for (i = 0; i < ps->num_levels; i++) {
1218 if (ps->levels[i].vddc_index < min_voltage)
1219 ps->levels[i].vddc_index = min_voltage;
1220
1221 if (ps->levels[i].sclk < min_sclk)
1222 ps->levels[i].sclk =
1223 trinity_get_valid_engine_clock(rdev, min_sclk);
1224
1225 ps->levels[i].ds_divider_index =
1226 sumo_get_sleep_divider_id_from_clock(rdev, ps->levels[i].sclk, sclk_in_sr);
1227
1228 ps->levels[i].ss_divider_index = ps->levels[i].ds_divider_index;
1229
1230 ps->levels[i].allow_gnb_slow = 1;
1231 ps->levels[i].force_nbp_state = 0;
1232 ps->levels[i].display_wm =
1233 trinity_calculate_display_wm(rdev, ps, i);
1234 ps->levels[i].vce_wm =
1235 trinity_calculate_vce_wm(rdev, ps->levels[0].sclk);
1236 }
1237
1238 if ((rps->class & (ATOM_PPLIB_CLASSIFICATION_HDSTATE | ATOM_PPLIB_CLASSIFICATION_SDSTATE)) ||
1239 ((rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY))
1240 ps->bapm_flags |= TRINITY_POWERSTATE_FLAGS_BAPM_DISABLE;
1241
1242 if (pi->sys_info.nb_dpm_enable) {
1243 ps->Dpm0PgNbPsLo = 0x1;
1244 ps->Dpm0PgNbPsHi = 0x0;
1245 ps->DpmXNbPsLo = 0x2;
1246 ps->DpmXNbPsHi = 0x1;
1247
1248 if ((rps->class & (ATOM_PPLIB_CLASSIFICATION_HDSTATE | ATOM_PPLIB_CLASSIFICATION_SDSTATE)) ||
1249 ((rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY)) {
1250 force_high = ((rps->class & ATOM_PPLIB_CLASSIFICATION_HDSTATE) ||
1251 ((rps->class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) &&
1252 (pi->sys_info.uma_channel_number == 1)));
1253 force_high = (num_active_displays >= 3) || force_high;
1254 ps->Dpm0PgNbPsLo = force_high ? 0x2 : 0x3;
1255 ps->Dpm0PgNbPsHi = 0x1;
1256 ps->DpmXNbPsLo = force_high ? 0x2 : 0x3;
1257 ps->DpmXNbPsHi = 0x2;
1258 ps->levels[ps->num_levels - 1].allow_gnb_slow = 0;
1259 }
1260 }
1261}
1262
1263static void trinity_cleanup_asic(struct radeon_device *rdev)
1264{
1265 sumo_take_smu_control(rdev, false);
1266}
1267
1268#if 0
1269static void trinity_pre_display_configuration_change(struct radeon_device *rdev)
1270{
1271 struct trinity_power_info *pi = trinity_get_pi(rdev);
1272
1273 if (pi->voltage_drop_in_dce)
1274 trinity_dce_enable_voltage_adjustment(rdev, false);
1275}
1276#endif
1277
1278static void trinity_add_dccac_value(struct radeon_device *rdev)
1279{
1280 u32 gpu_cac_avrg_cntl_window_size;
1281 u32 num_active_displays = rdev->pm.dpm.new_active_crtc_count;
1282 u64 disp_clk = rdev->clock.default_dispclk / 100;
1283 u32 dc_cac_value;
1284
1285 gpu_cac_avrg_cntl_window_size =
1286 (RREG32_SMC(GPU_CAC_AVRG_CNTL) & WINDOW_SIZE_MASK) >> WINDOW_SIZE_SHIFT;
1287
1288 dc_cac_value = (u32)((14213 * disp_clk * disp_clk * (u64)num_active_displays) >>
1289 (32 - gpu_cac_avrg_cntl_window_size));
1290
1291 WREG32_SMC(DC_CAC_VALUE, dc_cac_value);
1292}
1293
1294void trinity_dpm_display_configuration_changed(struct radeon_device *rdev)
1295{
1296 struct trinity_power_info *pi = trinity_get_pi(rdev);
1297
1298 if (pi->voltage_drop_in_dce)
1299 trinity_dce_enable_voltage_adjustment(rdev, true);
1300 trinity_add_dccac_value(rdev);
1301}
1302
1303union power_info {
1304 struct _ATOM_POWERPLAY_INFO info;
1305 struct _ATOM_POWERPLAY_INFO_V2 info_2;
1306 struct _ATOM_POWERPLAY_INFO_V3 info_3;
1307 struct _ATOM_PPLIB_POWERPLAYTABLE pplib;
1308 struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2;
1309 struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3;
1310};
1311
1312union pplib_clock_info {
1313 struct _ATOM_PPLIB_R600_CLOCK_INFO r600;
1314 struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780;
1315 struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen;
1316 struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo;
1317};
1318
1319union pplib_power_state {
1320 struct _ATOM_PPLIB_STATE v1;
1321 struct _ATOM_PPLIB_STATE_V2 v2;
1322};
1323
1324static void trinity_parse_pplib_non_clock_info(struct radeon_device *rdev,
1325 struct radeon_ps *rps,
1326 struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info,
1327 u8 table_rev)
1328{
1329 struct trinity_ps *ps = trinity_get_ps(rps);
1330
1331 rps->caps = le32_to_cpu(non_clock_info->ulCapsAndSettings);
1332 rps->class = le16_to_cpu(non_clock_info->usClassification);
1333 rps->class2 = le16_to_cpu(non_clock_info->usClassification2);
1334
1335 if (ATOM_PPLIB_NONCLOCKINFO_VER1 < table_rev) {
1336 rps->vclk = le32_to_cpu(non_clock_info->ulVCLK);
1337 rps->dclk = le32_to_cpu(non_clock_info->ulDCLK);
1338 } else {
1339 rps->vclk = 0;
1340 rps->dclk = 0;
1341 }
1342
1343 if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT) {
1344 rdev->pm.dpm.boot_ps = rps;
1345 trinity_patch_boot_state(rdev, ps);
1346 }
1347 if (rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)
1348 rdev->pm.dpm.uvd_ps = rps;
1349}
1350
1351static void trinity_parse_pplib_clock_info(struct radeon_device *rdev,
1352 struct radeon_ps *rps, int index,
1353 union pplib_clock_info *clock_info)
1354{
1355 struct trinity_power_info *pi = trinity_get_pi(rdev);
1356 struct trinity_ps *ps = trinity_get_ps(rps);
1357 struct trinity_pl *pl = &ps->levels[index];
1358 u32 sclk;
1359
1360 sclk = le16_to_cpu(clock_info->sumo.usEngineClockLow);
1361 sclk |= clock_info->sumo.ucEngineClockHigh << 16;
1362 pl->sclk = sclk;
1363 pl->vddc_index = clock_info->sumo.vddcIndex;
1364
1365 ps->num_levels = index + 1;
1366
1367 if (pi->enable_sclk_ds) {
1368 pl->ds_divider_index = 5;
1369 pl->ss_divider_index = 5;
1370 }
1371}
1372
1373static int trinity_parse_power_table(struct radeon_device *rdev)
1374{
1375 struct radeon_mode_info *mode_info = &rdev->mode_info;
1376 struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info;
1377 union pplib_power_state *power_state;
1378 int i, j, k, non_clock_array_index, clock_array_index;
1379 union pplib_clock_info *clock_info;
1380 struct _StateArray *state_array;
1381 struct _ClockInfoArray *clock_info_array;
1382 struct _NonClockInfoArray *non_clock_info_array;
1383 union power_info *power_info;
1384 int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
1385 u16 data_offset;
1386 u8 frev, crev;
1387 u8 *power_state_offset;
1388 struct sumo_ps *ps;
1389
1390 if (!atom_parse_data_header(mode_info->atom_context, index, NULL,
1391 &frev, &crev, &data_offset))
1392 return -EINVAL;
1393 power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
1394
1395 state_array = (struct _StateArray *)
1396 (mode_info->atom_context->bios + data_offset +
1397 le16_to_cpu(power_info->pplib.usStateArrayOffset));
1398 clock_info_array = (struct _ClockInfoArray *)
1399 (mode_info->atom_context->bios + data_offset +
1400 le16_to_cpu(power_info->pplib.usClockInfoArrayOffset));
1401 non_clock_info_array = (struct _NonClockInfoArray *)
1402 (mode_info->atom_context->bios + data_offset +
1403 le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset));
1404
1405 rdev->pm.dpm.ps = kzalloc(sizeof(struct radeon_ps) *
1406 state_array->ucNumEntries, GFP_KERNEL);
1407 if (!rdev->pm.dpm.ps)
1408 return -ENOMEM;
1409 power_state_offset = (u8 *)state_array->states;
1410 rdev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps);
1411 rdev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime);
1412 rdev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime);
1413 for (i = 0; i < state_array->ucNumEntries; i++) {
1414 power_state = (union pplib_power_state *)power_state_offset;
1415 non_clock_array_index = power_state->v2.nonClockInfoIndex;
1416 non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
1417 &non_clock_info_array->nonClockInfo[non_clock_array_index];
1418 if (!rdev->pm.power_state[i].clock_info)
1419 return -EINVAL;
1420 ps = kzalloc(sizeof(struct sumo_ps), GFP_KERNEL);
1421 if (ps == NULL) {
1422 kfree(rdev->pm.dpm.ps);
1423 return -ENOMEM;
1424 }
1425 rdev->pm.dpm.ps[i].ps_priv = ps;
1426 k = 0;
1427 for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) {
1428 clock_array_index = power_state->v2.clockInfoIndex[j];
1429 if (clock_array_index >= clock_info_array->ucNumEntries)
1430 continue;
1431 if (k >= SUMO_MAX_HARDWARE_POWERLEVELS)
1432 break;
1433 clock_info = (union pplib_clock_info *)
1434 &clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize];
1435 trinity_parse_pplib_clock_info(rdev,
1436 &rdev->pm.dpm.ps[i], k,
1437 clock_info);
1438 k++;
1439 }
1440 trinity_parse_pplib_non_clock_info(rdev, &rdev->pm.dpm.ps[i],
1441 non_clock_info,
1442 non_clock_info_array->ucEntrySize);
1443 power_state_offset += 2 + power_state->v2.ucNumDPMLevels;
1444 }
1445 rdev->pm.dpm.num_ps = state_array->ucNumEntries;
1446 return 0;
1447}
1448
1449union igp_info {
1450 struct _ATOM_INTEGRATED_SYSTEM_INFO info;
1451 struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2;
1452 struct _ATOM_INTEGRATED_SYSTEM_INFO_V5 info_5;
1453 struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 info_6;
1454 struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7 info_7;
1455};
1456
1457static int trinity_parse_sys_info_table(struct radeon_device *rdev)
1458{
1459 struct trinity_power_info *pi = trinity_get_pi(rdev);
1460 struct radeon_mode_info *mode_info = &rdev->mode_info;
1461 int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo);
1462 union igp_info *igp_info;
1463 u8 frev, crev;
1464 u16 data_offset;
1465 int i;
1466
1467 if (atom_parse_data_header(mode_info->atom_context, index, NULL,
1468 &frev, &crev, &data_offset)) {
1469 igp_info = (union igp_info *)(mode_info->atom_context->bios +
1470 data_offset);
1471
1472 if (crev != 7) {
1473 DRM_ERROR("Unsupported IGP table: %d %d\n", frev, crev);
1474 return -EINVAL;
1475 }
1476 pi->sys_info.bootup_sclk = le32_to_cpu(igp_info->info_7.ulBootUpEngineClock);
1477 pi->sys_info.min_sclk = le32_to_cpu(igp_info->info_7.ulMinEngineClock);
1478 pi->sys_info.bootup_uma_clk = le32_to_cpu(igp_info->info_7.ulBootUpUMAClock);
1479 pi->sys_info.bootup_nb_voltage_index =
1480 le16_to_cpu(igp_info->info_7.usBootUpNBVoltage);
1481 if (igp_info->info_7.ucHtcTmpLmt == 0)
1482 pi->sys_info.htc_tmp_lmt = 203;
1483 else
1484 pi->sys_info.htc_tmp_lmt = igp_info->info_7.ucHtcTmpLmt;
1485 if (igp_info->info_7.ucHtcHystLmt == 0)
1486 pi->sys_info.htc_hyst_lmt = 5;
1487 else
1488 pi->sys_info.htc_hyst_lmt = igp_info->info_7.ucHtcHystLmt;
1489 if (pi->sys_info.htc_tmp_lmt <= pi->sys_info.htc_hyst_lmt) {
1490 DRM_ERROR("The htcTmpLmt should be larger than htcHystLmt.\n");
1491 }
1492
1493 if (pi->enable_nbps_policy)
1494 pi->sys_info.nb_dpm_enable = igp_info->info_7.ucNBDPMEnable;
1495 else
1496 pi->sys_info.nb_dpm_enable = 0;
1497
1498 for (i = 0; i < TRINITY_NUM_NBPSTATES; i++) {
1499 pi->sys_info.nbp_mclk[i] = le32_to_cpu(igp_info->info_7.ulNbpStateMemclkFreq[i]);
1500 pi->sys_info.nbp_nclk[i] = le32_to_cpu(igp_info->info_7.ulNbpStateNClkFreq[i]);
1501 }
1502
1503 pi->sys_info.nbp_voltage_index[0] = le16_to_cpu(igp_info->info_7.usNBP0Voltage);
1504 pi->sys_info.nbp_voltage_index[1] = le16_to_cpu(igp_info->info_7.usNBP1Voltage);
1505 pi->sys_info.nbp_voltage_index[2] = le16_to_cpu(igp_info->info_7.usNBP2Voltage);
1506 pi->sys_info.nbp_voltage_index[3] = le16_to_cpu(igp_info->info_7.usNBP3Voltage);
1507
1508 if (!pi->sys_info.nb_dpm_enable) {
1509 for (i = 1; i < TRINITY_NUM_NBPSTATES; i++) {
1510 pi->sys_info.nbp_mclk[i] = pi->sys_info.nbp_mclk[0];
1511 pi->sys_info.nbp_nclk[i] = pi->sys_info.nbp_nclk[0];
1512 pi->sys_info.nbp_voltage_index[i] = pi->sys_info.nbp_voltage_index[0];
1513 }
1514 }
1515
1516 pi->sys_info.uma_channel_number = igp_info->info_7.ucUMAChannelNumber;
1517
1518 sumo_construct_sclk_voltage_mapping_table(rdev,
1519 &pi->sys_info.sclk_voltage_mapping_table,
1520 igp_info->info_7.sAvail_SCLK);
1521 sumo_construct_vid_mapping_table(rdev, &pi->sys_info.vid_mapping_table,
1522 igp_info->info_7.sAvail_SCLK);
1523
1524 }
1525 return 0;
1526}
1527
1528int trinity_dpm_init(struct radeon_device *rdev)
1529{
1530 struct trinity_power_info *pi;
1531 int ret, i;
1532
1533 pi = kzalloc(sizeof(struct trinity_power_info), GFP_KERNEL);
1534 if (pi == NULL)
1535 return -ENOMEM;
1536 rdev->pm.dpm.priv = pi;
1537
1538 for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++)
1539 pi->at[i] = TRINITY_AT_DFLT;
1540
1541 pi->enable_nbps_policy = true;
1542 pi->enable_sclk_ds = true;
1543 pi->enable_gfx_power_gating = true;
1544 pi->enable_gfx_clock_gating = true;
1545 pi->enable_mg_clock_gating = true;
1546 pi->enable_gfx_dynamic_mgpg = true; /* ??? */
1547 pi->override_dynamic_mgpg = true;
1548 pi->enable_auto_thermal_throttling = true;
1549 pi->voltage_drop_in_dce = false; /* need to restructure dpm/modeset interaction */
1550
1551 ret = trinity_parse_sys_info_table(rdev);
1552 if (ret)
1553 return ret;
1554
1555 trinity_construct_boot_state(rdev);
1556
1557 ret = trinity_parse_power_table(rdev);
1558 if (ret)
1559 return ret;
1560
1561 pi->thermal_auto_throttling = pi->sys_info.htc_tmp_lmt;
1562 pi->enable_dpm = true;
1563
1564 return 0;
1565}
1566
1567void trinity_dpm_print_power_state(struct radeon_device *rdev,
1568 struct radeon_ps *rps)
1569{
1570 int i;
1571 struct trinity_ps *ps = trinity_get_ps(rps);
1572
1573 r600_dpm_print_class_info(rps->class, rps->class2);
1574 r600_dpm_print_cap_info(rps->caps);
1575 printk("\tuvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk);
1576 for (i = 0; i < ps->num_levels; i++) {
1577 struct trinity_pl *pl = &ps->levels[i];
1578 printk("\t\tpower level %d sclk: %u vddc: %u\n",
1579 i, pl->sclk,
1580 trinity_convert_voltage_index_to_value(rdev, pl->vddc_index));
1581 }
1582 r600_dpm_print_ps_status(rdev, rps);
1583}
1584
1585void trinity_dpm_fini(struct radeon_device *rdev)
1586{
1587 int i;
1588
1589 trinity_cleanup_asic(rdev); /* ??? */
1590
1591 for (i = 0; i < rdev->pm.dpm.num_ps; i++) {
1592 kfree(rdev->pm.dpm.ps[i].ps_priv);
1593 }
1594 kfree(rdev->pm.dpm.ps);
1595 kfree(rdev->pm.dpm.priv);
1596}
1597
1598u32 trinity_dpm_get_sclk(struct radeon_device *rdev, bool low)
1599{
1600 struct trinity_ps *requested_state = trinity_get_ps(rdev->pm.dpm.requested_ps);
1601
1602 if (low)
1603 return requested_state->levels[0].sclk;
1604 else
1605 return requested_state->levels[requested_state->num_levels - 1].sclk;
1606}
1607
1608u32 trinity_dpm_get_mclk(struct radeon_device *rdev, bool low)
1609{
1610 struct trinity_power_info *pi = trinity_get_pi(rdev);
1611
1612 return pi->sys_info.bootup_uma_clk;
1613}
diff --git a/drivers/gpu/drm/radeon/trinity_dpm.h b/drivers/gpu/drm/radeon/trinity_dpm.h
new file mode 100644
index 000000000000..15e050fd5446
--- /dev/null
+++ b/drivers/gpu/drm/radeon/trinity_dpm.h
@@ -0,0 +1,110 @@
1/*
2 * Copyright 2012 Advanced Micro Devices, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 */
23#ifndef __TRINITY_DPM_H__
24#define __TRINITY_DPM_H__
25
26#include "sumo_dpm.h"
27
28#define TRINITY_SIZEOF_DPM_STATE_TABLE (SMU_SCLK_DPM_STATE_1_CNTL_0 - SMU_SCLK_DPM_STATE_0_CNTL_0)
29
30struct trinity_pl {
31 u32 sclk;
32 u8 vddc_index;
33 u8 ds_divider_index;
34 u8 ss_divider_index;
35 u8 allow_gnb_slow;
36 u8 force_nbp_state;
37 u8 display_wm;
38 u8 vce_wm;
39};
40
41#define TRINITY_POWERSTATE_FLAGS_NBPS_FORCEHIGH (1 << 0)
42#define TRINITY_POWERSTATE_FLAGS_NBPS_LOCKTOHIGH (1 << 1)
43#define TRINITY_POWERSTATE_FLAGS_NBPS_LOCKTOLOW (1 << 2)
44
45#define TRINITY_POWERSTATE_FLAGS_BAPM_DISABLE (1 << 0)
46
47struct trinity_ps {
48 u32 num_levels;
49 struct trinity_pl levels[SUMO_MAX_HARDWARE_POWERLEVELS];
50
51 u32 nbps_flags;
52 u32 bapm_flags;
53
54 u8 Dpm0PgNbPsLo;
55 u8 Dpm0PgNbPsHi;
56 u8 DpmXNbPsLo;
57 u8 DpmXNbPsHi;
58};
59
60#define TRINITY_NUM_NBPSTATES 4
61
62struct trinity_sys_info {
63 u32 bootup_uma_clk;
64 u32 bootup_sclk;
65 u32 min_sclk;
66 u32 nb_dpm_enable;
67 u32 nbp_mclk[TRINITY_NUM_NBPSTATES];
68 u32 nbp_nclk[TRINITY_NUM_NBPSTATES];
69 u16 nbp_voltage_index[TRINITY_NUM_NBPSTATES];
70 u16 bootup_nb_voltage_index;
71 u8 htc_tmp_lmt;
72 u8 htc_hyst_lmt;
73 struct sumo_sclk_voltage_mapping_table sclk_voltage_mapping_table;
74 struct sumo_vid_mapping_table vid_mapping_table;
75 u32 uma_channel_number;
76};
77
78struct trinity_power_info {
79 u32 at[SUMO_MAX_HARDWARE_POWERLEVELS];
80 u32 dpm_interval;
81 u32 thermal_auto_throttling;
82 struct trinity_sys_info sys_info;
83 struct trinity_pl boot_pl;
84 struct trinity_ps current_ps;
85 u32 min_sclk_did;
86 bool enable_nbps_policy;
87 bool voltage_drop_in_dce;
88 bool override_dynamic_mgpg;
89 bool enable_gfx_clock_gating;
90 bool enable_gfx_power_gating;
91 bool enable_mg_clock_gating;
92 bool enable_gfx_dynamic_mgpg;
93 bool enable_auto_thermal_throttling;
94 bool enable_dpm;
95 bool enable_sclk_ds;
96};
97
98#define TRINITY_AT_DFLT 30
99
100/* trinity_smc.c */
101int trinity_dpm_config(struct radeon_device *rdev, bool enable);
102int trinity_dpm_force_state(struct radeon_device *rdev, u32 n);
103int trinity_dpm_no_forced_level(struct radeon_device *rdev);
104int trinity_dce_enable_voltage_adjustment(struct radeon_device *rdev,
105 bool enable);
106int trinity_gfx_dynamic_mgpg_config(struct radeon_device *rdev);
107void trinity_acquire_mutex(struct radeon_device *rdev);
108void trinity_release_mutex(struct radeon_device *rdev);
109
110#endif
diff --git a/drivers/gpu/drm/radeon/trinity_smc.c b/drivers/gpu/drm/radeon/trinity_smc.c
new file mode 100644
index 000000000000..60ffc1e6f21b
--- /dev/null
+++ b/drivers/gpu/drm/radeon/trinity_smc.c
@@ -0,0 +1,110 @@
1/*
2 * Copyright 2012 Advanced Micro Devices, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 */
23
24#include "drmP.h"
25#include "radeon.h"
26#include "trinityd.h"
27#include "trinity_dpm.h"
28#include "ppsmc.h"
29
30struct trinity_ps *trinity_get_ps(struct radeon_ps *rps);
31struct trinity_power_info *trinity_get_pi(struct radeon_device *rdev);
32
33static int trinity_notify_message_to_smu(struct radeon_device *rdev, u32 id)
34{
35 int i;
36 u32 v = 0;
37
38 WREG32(SMC_MESSAGE_0, id);
39 for (i = 0; i < rdev->usec_timeout; i++) {
40 if (RREG32(SMC_RESP_0) != 0)
41 break;
42 udelay(1);
43 }
44 v = RREG32(SMC_RESP_0);
45
46 if (v != 1) {
47 if (v == 0xFF) {
48 DRM_ERROR("SMC failed to handle the message!\n");
49 return -EINVAL;
50 } else if (v == 0xFE) {
51 DRM_ERROR("Unknown SMC message!\n");
52 return -EINVAL;
53 }
54 }
55
56 return 0;
57}
58
59int trinity_dpm_config(struct radeon_device *rdev, bool enable)
60{
61 if (enable)
62 WREG32_SMC(SMU_SCRATCH0, 1);
63 else
64 WREG32_SMC(SMU_SCRATCH0, 0);
65
66 return trinity_notify_message_to_smu(rdev, PPSMC_MSG_DPM_Config);
67}
68
69int trinity_dpm_force_state(struct radeon_device *rdev, u32 n)
70{
71 WREG32_SMC(SMU_SCRATCH0, n);
72
73 return trinity_notify_message_to_smu(rdev, PPSMC_MSG_DPM_ForceState);
74}
75
76int trinity_dpm_no_forced_level(struct radeon_device *rdev)
77{
78 return trinity_notify_message_to_smu(rdev, PPSMC_MSG_NoForcedLevel);
79}
80
81int trinity_dce_enable_voltage_adjustment(struct radeon_device *rdev,
82 bool enable)
83{
84 if (enable)
85 return trinity_notify_message_to_smu(rdev, PPSMC_MSG_DCE_AllowVoltageAdjustment);
86 else
87 return trinity_notify_message_to_smu(rdev, PPSMC_MSG_DCE_RemoveVoltageAdjustment);
88}
89
90int trinity_gfx_dynamic_mgpg_config(struct radeon_device *rdev)
91{
92 return trinity_notify_message_to_smu(rdev, PPSMC_MSG_PG_SIMD_Config);
93}
94
95void trinity_acquire_mutex(struct radeon_device *rdev)
96{
97 int i;
98
99 WREG32(SMC_INT_REQ, 1);
100 for (i = 0; i < rdev->usec_timeout; i++) {
101 if ((RREG32(SMC_INT_REQ) & 0xffff) == 1)
102 break;
103 udelay(1);
104 }
105}
106
107void trinity_release_mutex(struct radeon_device *rdev)
108{
109 WREG32(SMC_INT_REQ, 0);
110}
diff --git a/drivers/gpu/drm/radeon/trinityd.h b/drivers/gpu/drm/radeon/trinityd.h
new file mode 100644
index 000000000000..b234d36ddce0
--- /dev/null
+++ b/drivers/gpu/drm/radeon/trinityd.h
@@ -0,0 +1,223 @@
1/*
2 * Copyright 2012 Advanced Micro Devices, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Alex Deucher
23 */
24#ifndef _TRINITYD_H_
25#define _TRINITYD_H_
26
27/* pm registers */
28
29/* cg */
30#define CG_CGTT_LOCAL_0 0x0
31#define CG_CGTT_LOCAL_1 0x1
32
33/* smc */
34#define SMU_SCLK_DPM_STATE_0_CNTL_0 0x1f000
35# define STATE_VALID(x) ((x) << 0)
36# define STATE_VALID_MASK (0xff << 0)
37# define STATE_VALID_SHIFT 0
38# define CLK_DIVIDER(x) ((x) << 8)
39# define CLK_DIVIDER_MASK (0xff << 8)
40# define CLK_DIVIDER_SHIFT 8
41# define VID(x) ((x) << 16)
42# define VID_MASK (0xff << 16)
43# define VID_SHIFT 16
44# define LVRT(x) ((x) << 24)
45# define LVRT_MASK (0xff << 24)
46# define LVRT_SHIFT 24
47#define SMU_SCLK_DPM_STATE_0_CNTL_1 0x1f004
48# define DS_DIV(x) ((x) << 0)
49# define DS_DIV_MASK (0xff << 0)
50# define DS_DIV_SHIFT 0
51# define DS_SH_DIV(x) ((x) << 8)
52# define DS_SH_DIV_MASK (0xff << 8)
53# define DS_SH_DIV_SHIFT 8
54# define DISPLAY_WM(x) ((x) << 16)
55# define DISPLAY_WM_MASK (0xff << 16)
56# define DISPLAY_WM_SHIFT 16
57# define VCE_WM(x) ((x) << 24)
58# define VCE_WM_MASK (0xff << 24)
59# define VCE_WM_SHIFT 24
60
61#define SMU_SCLK_DPM_STATE_0_CNTL_3 0x1f00c
62# define GNB_SLOW(x) ((x) << 0)
63# define GNB_SLOW_MASK (0xff << 0)
64# define GNB_SLOW_SHIFT 0
65# define FORCE_NBPS1(x) ((x) << 8)
66# define FORCE_NBPS1_MASK (0xff << 8)
67# define FORCE_NBPS1_SHIFT 8
68#define SMU_SCLK_DPM_STATE_0_AT 0x1f010
69# define AT(x) ((x) << 0)
70# define AT_MASK (0xff << 0)
71# define AT_SHIFT 0
72
73#define SMU_SCLK_DPM_STATE_0_PG_CNTL 0x1f014
74# define PD_SCLK_DIVIDER(x) ((x) << 16)
75# define PD_SCLK_DIVIDER_MASK (0xff << 16)
76# define PD_SCLK_DIVIDER_SHIFT 16
77
78#define SMU_SCLK_DPM_STATE_1_CNTL_0 0x1f020
79
80#define SMU_SCLK_DPM_CNTL 0x1f100
81# define SCLK_DPM_EN(x) ((x) << 0)
82# define SCLK_DPM_EN_MASK (0xff << 0)
83# define SCLK_DPM_EN_SHIFT 0
84# define SCLK_DPM_BOOT_STATE(x) ((x) << 16)
85# define SCLK_DPM_BOOT_STATE_MASK (0xff << 16)
86# define SCLK_DPM_BOOT_STATE_SHIFT 16
87# define VOLTAGE_CHG_EN(x) ((x) << 24)
88# define VOLTAGE_CHG_EN_MASK (0xff << 24)
89# define VOLTAGE_CHG_EN_SHIFT 24
90
91#define SMU_SCLK_DPM_TT_CNTL 0x1f108
92# define SCLK_TT_EN(x) ((x) << 0)
93# define SCLK_TT_EN_MASK (0xff << 0)
94# define SCLK_TT_EN_SHIFT 0
95#define SMU_SCLK_DPM_TTT 0x1f10c
96# define LT(x) ((x) << 0)
97# define LT_MASK (0xffff << 0)
98# define LT_SHIFT 0
99# define HT(x) ((x) << 16)
100# define HT_MASK (0xffff << 16)
101# define HT_SHIFT 16
102
103#define SMU_S_PG_CNTL 0x1f118
104# define DS_PG_EN(x) ((x) << 16)
105# define DS_PG_EN_MASK (0xff << 16)
106# define DS_PG_EN_SHIFT 16
107
108#define GFX_POWER_GATING_CNTL 0x1f38c
109# define PDS_DIV(x) ((x) << 0)
110# define PDS_DIV_MASK (0xff << 0)
111# define PDS_DIV_SHIFT 0
112# define SSSD(x) ((x) << 8)
113# define SSSD_MASK (0xff << 8)
114# define SSSD_SHIFT 8
115
116#define PM_CONFIG 0x1f428
117# define SVI_Mode (1 << 29)
118
119#define PM_I_CNTL_1 0x1f464
120# define SCLK_DPM(x) ((x) << 0)
121# define SCLK_DPM_MASK (0xff << 0)
122# define SCLK_DPM_SHIFT 0
123# define DS_PG_CNTL(x) ((x) << 16)
124# define DS_PG_CNTL_MASK (0xff << 16)
125# define DS_PG_CNTL_SHIFT 16
126#define PM_TP 0x1f468
127
128#define NB_PSTATE_CONFIG 0x1f5f8
129# define Dpm0PgNbPsLo(x) ((x) << 0)
130# define Dpm0PgNbPsLo_MASK (3 << 0)
131# define Dpm0PgNbPsLo_SHIFT 0
132# define Dpm0PgNbPsHi(x) ((x) << 2)
133# define Dpm0PgNbPsHi_MASK (3 << 2)
134# define Dpm0PgNbPsHi_SHIFT 2
135# define DpmXNbPsLo(x) ((x) << 4)
136# define DpmXNbPsLo_MASK (3 << 4)
137# define DpmXNbPsLo_SHIFT 4
138# define DpmXNbPsHi(x) ((x) << 6)
139# define DpmXNbPsHi_MASK (3 << 6)
140# define DpmXNbPsHi_SHIFT 6
141
142#define DC_CAC_VALUE 0x1f908
143
144#define GPU_CAC_AVRG_CNTL 0x1f920
145# define WINDOW_SIZE(x) ((x) << 0)
146# define WINDOW_SIZE_MASK (0xff << 0)
147# define WINDOW_SIZE_SHIFT 0
148
149#define CC_SMU_MISC_FUSES 0xe0001004
150# define MinSClkDid(x) ((x) << 2)
151# define MinSClkDid_MASK (0x7f << 2)
152# define MinSClkDid_SHIFT 2
153
154#define CC_SMU_TST_EFUSE1_MISC 0xe000101c
155# define RB_BACKEND_DISABLE(x) ((x) << 16)
156# define RB_BACKEND_DISABLE_MASK (3 << 16)
157# define RB_BACKEND_DISABLE_SHIFT 16
158
159#define SMU_SCRATCH_A 0xe0003024
160
161#define SMU_SCRATCH0 0xe0003040
162
163/* mmio */
164#define SMC_INT_REQ 0x220
165
166#define SMC_MESSAGE_0 0x22c
167#define SMC_RESP_0 0x230
168
169#define GENERAL_PWRMGT 0x670
170# define GLOBAL_PWRMGT_EN (1 << 0)
171
172#define SCLK_PWRMGT_CNTL 0x678
173# define DYN_PWR_DOWN_EN (1 << 2)
174# define RESET_BUSY_CNT (1 << 4)
175# define RESET_SCLK_CNT (1 << 5)
176# define DYN_GFX_CLK_OFF_EN (1 << 7)
177# define GFX_CLK_FORCE_ON (1 << 8)
178# define DYNAMIC_PM_EN (1 << 21)
179
180#define TARGET_AND_CURRENT_PROFILE_INDEX 0x684
181# define TARGET_STATE(x) ((x) << 0)
182# define TARGET_STATE_MASK (0xf << 0)
183# define TARGET_STATE_SHIFT 0
184# define CURRENT_STATE(x) ((x) << 4)
185# define CURRENT_STATE_MASK (0xf << 4)
186# define CURRENT_STATE_SHIFT 4
187
188#define CG_GIPOTS 0x6d8
189# define CG_GIPOT(x) ((x) << 16)
190# define CG_GIPOT_MASK (0xffff << 16)
191# define CG_GIPOT_SHIFT 16
192
193#define CG_PG_CTRL 0x6e0
194# define SP(x) ((x) << 0)
195# define SP_MASK (0xffff << 0)
196# define SP_SHIFT 0
197# define SU(x) ((x) << 16)
198# define SU_MASK (0xffff << 16)
199# define SU_SHIFT 16
200
201#define CG_THERMAL_INT_CTRL 0x738
202# define DIG_THERM_INTH(x) ((x) << 0)
203# define DIG_THERM_INTH_MASK (0xff << 0)
204# define DIG_THERM_INTH_SHIFT 0
205# define DIG_THERM_INTL(x) ((x) << 8)
206# define DIG_THERM_INTL_MASK (0xff << 8)
207# define DIG_THERM_INTL_SHIFT 8
208# define THERM_INTH_MASK (1 << 24)
209# define THERM_INTL_MASK (1 << 25)
210
211#define CG_CG_VOLTAGE_CNTL 0x770
212# define EN (1 << 9)
213
214#define HW_REV 0x5564
215# define ATI_REV_ID_MASK (0xf << 28)
216# define ATI_REV_ID_SHIFT 28
217/* 0 = A0, 1 = A1, 2 = B0, 3 = C0, etc. */
218
219#define CGTS_SM_CTRL_REG 0x9150
220
221#define GB_ADDR_CONFIG 0x98f8
222
223#endif