0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029 #include "core_types.h"
0030 #include "clk_mgr_internal.h"
0031 #include "reg_helper.h"
0032 #include "dm_helpers.h"
0033 #include "dcn314_smu.h"
0034
0035 #include "mp/mp_13_0_5_offset.h"
0036
0037
0038 #define MP1_BASE__INST0_SEG0 0x00016000
0039 #define MP1_BASE__INST0_SEG1 0x0243FC00
0040 #define MP1_BASE__INST0_SEG2 0x00DC0000
0041 #define MP1_BASE__INST0_SEG3 0x00E00000
0042 #define MP1_BASE__INST0_SEG4 0x00E40000
0043 #define MP1_BASE__INST0_SEG5 0
0044
0045 #ifdef BASE_INNER
0046 #undef BASE_INNER
0047 #endif
0048
0049 #define BASE_INNER(seg) MP1_BASE__INST0_SEG ## seg
0050
0051 #define BASE(seg) BASE_INNER(seg)
0052
0053 #define REG(reg_name) (BASE(reg##reg_name##_BASE_IDX) + reg##reg_name)
0054
0055 #define FN(reg_name, field) \
0056 FD(reg_name##__##field)
0057
0058 #include "logger_types.h"
0059 #undef DC_LOGGER
0060 #define DC_LOGGER \
0061 CTX->logger
0062 #define smu_print(str, ...) {DC_LOG_SMU(str, ##__VA_ARGS__); }
0063
0064 #define VBIOSSMC_MSG_TestMessage 0x1
0065 #define VBIOSSMC_MSG_GetSmuVersion 0x2
0066 #define VBIOSSMC_MSG_PowerUpGfx 0x3
0067 #define VBIOSSMC_MSG_SetDispclkFreq 0x4
0068 #define VBIOSSMC_MSG_SetDprefclkFreq 0x5
0069 #define VBIOSSMC_MSG_SetDppclkFreq 0x6
0070 #define VBIOSSMC_MSG_SetHardMinDcfclkByFreq 0x7
0071 #define VBIOSSMC_MSG_SetMinDeepSleepDcfclk 0x8
0072 #define VBIOSSMC_MSG_SetPhyclkVoltageByFreq 0x9
0073 #define VBIOSSMC_MSG_GetFclkFrequency 0xA
0074 #define VBIOSSMC_MSG_SetDisplayCount 0xB
0075 #define VBIOSSMC_MSG_EnableTmdp48MHzRefclkPwrDown 0xC
0076 #define VBIOSSMC_MSG_UpdatePmeRestore 0xD
0077 #define VBIOSSMC_MSG_SetVbiosDramAddrHigh 0xE
0078 #define VBIOSSMC_MSG_SetVbiosDramAddrLow 0xF
0079 #define VBIOSSMC_MSG_TransferTableSmu2Dram 0x10
0080 #define VBIOSSMC_MSG_TransferTableDram2Smu 0x11
0081 #define VBIOSSMC_MSG_SetDisplayIdleOptimizations 0x12
0082 #define VBIOSSMC_MSG_GetDprefclkFreq 0x13
0083 #define VBIOSSMC_MSG_GetDtbclkFreq 0x14
0084 #define VBIOSSMC_MSG_AllowZstatesEntry 0x15
0085 #define VBIOSSMC_MSG_DisallowZstatesEntry 0x16
0086 #define VBIOSSMC_MSG_SetDtbClk 0x17
0087 #define VBIOSSMC_Message_Count 0x18
0088
0089 #define VBIOSSMC_Status_BUSY 0x0
0090 #define VBIOSSMC_Result_OK 0x1
0091 #define VBIOSSMC_Result_Failed 0xFF
0092 #define VBIOSSMC_Result_UnknownCmd 0xFE
0093 #define VBIOSSMC_Result_CmdRejectedPrereq 0xFD
0094 #define VBIOSSMC_Result_CmdRejectedBusy 0xFC
0095
0096
0097
0098
0099
0100
0101 static uint32_t dcn314_smu_wait_for_response(struct clk_mgr_internal *clk_mgr, unsigned int delay_us, unsigned int max_retries)
0102 {
0103 uint32_t res_val = VBIOSSMC_Status_BUSY;
0104
0105 do {
0106 res_val = REG_READ(MP1_SMN_C2PMSG_91);
0107 if (res_val != VBIOSSMC_Status_BUSY)
0108 break;
0109
0110 if (delay_us >= 1000)
0111 msleep(delay_us/1000);
0112 else if (delay_us > 0)
0113 udelay(delay_us);
0114 } while (max_retries--);
0115
0116 return res_val;
0117 }
0118
0119 static int dcn314_smu_send_msg_with_param(struct clk_mgr_internal *clk_mgr,
0120 unsigned int msg_id,
0121 unsigned int param)
0122 {
0123 uint32_t result;
0124
0125 result = dcn314_smu_wait_for_response(clk_mgr, 10, 200000);
0126 ASSERT(result == VBIOSSMC_Result_OK);
0127
0128 smu_print("SMU response after wait: %d\n", result);
0129
0130 if (result == VBIOSSMC_Status_BUSY)
0131 return -1;
0132
0133
0134 REG_WRITE(MP1_SMN_C2PMSG_91, VBIOSSMC_Status_BUSY);
0135
0136
0137 REG_WRITE(MP1_SMN_C2PMSG_83, param);
0138
0139
0140 REG_WRITE(MP1_SMN_C2PMSG_67, msg_id);
0141
0142 result = dcn314_smu_wait_for_response(clk_mgr, 10, 200000);
0143
0144 if (result == VBIOSSMC_Result_Failed) {
0145 if (msg_id == VBIOSSMC_MSG_TransferTableDram2Smu &&
0146 param == TABLE_WATERMARKS)
0147 DC_LOG_WARNING("Watermarks table not configured properly by SMU");
0148 else
0149 ASSERT(0);
0150 REG_WRITE(MP1_SMN_C2PMSG_91, VBIOSSMC_Result_OK);
0151 return -1;
0152 }
0153
0154 if (IS_SMU_TIMEOUT(result)) {
0155 ASSERT(0);
0156 dm_helpers_smu_timeout(CTX, msg_id, param, 10 * 200000);
0157 }
0158
0159 return REG_READ(MP1_SMN_C2PMSG_83);
0160 }
0161
0162 int dcn314_smu_get_smu_version(struct clk_mgr_internal *clk_mgr)
0163 {
0164 return dcn314_smu_send_msg_with_param(
0165 clk_mgr,
0166 VBIOSSMC_MSG_GetSmuVersion,
0167 0);
0168 }
0169
0170
0171 int dcn314_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_dispclk_khz)
0172 {
0173 int actual_dispclk_set_mhz = -1;
0174
0175 if (!clk_mgr->smu_present)
0176 return requested_dispclk_khz;
0177
0178
0179 actual_dispclk_set_mhz = dcn314_smu_send_msg_with_param(
0180 clk_mgr,
0181 VBIOSSMC_MSG_SetDispclkFreq,
0182 khz_to_mhz_ceil(requested_dispclk_khz));
0183
0184 return actual_dispclk_set_mhz * 1000;
0185 }
0186
0187 int dcn314_smu_set_dprefclk(struct clk_mgr_internal *clk_mgr)
0188 {
0189 int actual_dprefclk_set_mhz = -1;
0190
0191 if (!clk_mgr->smu_present)
0192 return clk_mgr->base.dprefclk_khz;
0193
0194 actual_dprefclk_set_mhz = dcn314_smu_send_msg_with_param(
0195 clk_mgr,
0196 VBIOSSMC_MSG_SetDprefclkFreq,
0197 khz_to_mhz_ceil(clk_mgr->base.dprefclk_khz));
0198
0199
0200
0201 return actual_dprefclk_set_mhz * 1000;
0202 }
0203
0204 int dcn314_smu_set_hard_min_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_dcfclk_khz)
0205 {
0206 int actual_dcfclk_set_mhz = -1;
0207
0208 if (!clk_mgr->base.ctx->dc->debug.pstate_enabled)
0209 return -1;
0210
0211 if (!clk_mgr->smu_present)
0212 return requested_dcfclk_khz;
0213
0214 actual_dcfclk_set_mhz = dcn314_smu_send_msg_with_param(
0215 clk_mgr,
0216 VBIOSSMC_MSG_SetHardMinDcfclkByFreq,
0217 khz_to_mhz_ceil(requested_dcfclk_khz));
0218
0219 return actual_dcfclk_set_mhz * 1000;
0220 }
0221
0222 int dcn314_smu_set_min_deep_sleep_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_min_ds_dcfclk_khz)
0223 {
0224 int actual_min_ds_dcfclk_mhz = -1;
0225
0226 if (!clk_mgr->base.ctx->dc->debug.pstate_enabled)
0227 return -1;
0228
0229 if (!clk_mgr->smu_present)
0230 return requested_min_ds_dcfclk_khz;
0231
0232 actual_min_ds_dcfclk_mhz = dcn314_smu_send_msg_with_param(
0233 clk_mgr,
0234 VBIOSSMC_MSG_SetMinDeepSleepDcfclk,
0235 khz_to_mhz_ceil(requested_min_ds_dcfclk_khz));
0236
0237 return actual_min_ds_dcfclk_mhz * 1000;
0238 }
0239
0240 int dcn314_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_khz)
0241 {
0242 int actual_dppclk_set_mhz = -1;
0243
0244 if (!clk_mgr->smu_present)
0245 return requested_dpp_khz;
0246
0247 actual_dppclk_set_mhz = dcn314_smu_send_msg_with_param(
0248 clk_mgr,
0249 VBIOSSMC_MSG_SetDppclkFreq,
0250 khz_to_mhz_ceil(requested_dpp_khz));
0251
0252 return actual_dppclk_set_mhz * 1000;
0253 }
0254
0255 void dcn314_smu_set_display_idle_optimization(struct clk_mgr_internal *clk_mgr, uint32_t idle_info)
0256 {
0257 if (!clk_mgr->base.ctx->dc->debug.pstate_enabled)
0258 return;
0259
0260 if (!clk_mgr->smu_present)
0261 return;
0262
0263
0264 dcn314_smu_send_msg_with_param(
0265 clk_mgr,
0266 VBIOSSMC_MSG_SetDisplayIdleOptimizations,
0267 idle_info);
0268 }
0269
0270 void dcn314_smu_enable_phy_refclk_pwrdwn(struct clk_mgr_internal *clk_mgr, bool enable)
0271 {
0272 union display_idle_optimization_u idle_info = { 0 };
0273
0274 if (!clk_mgr->smu_present)
0275 return;
0276
0277 if (enable) {
0278 idle_info.idle_info.df_request_disabled = 1;
0279 idle_info.idle_info.phy_ref_clk_off = 1;
0280 }
0281
0282 dcn314_smu_send_msg_with_param(
0283 clk_mgr,
0284 VBIOSSMC_MSG_SetDisplayIdleOptimizations,
0285 idle_info.data);
0286 }
0287
0288 void dcn314_smu_enable_pme_wa(struct clk_mgr_internal *clk_mgr)
0289 {
0290 if (!clk_mgr->smu_present)
0291 return;
0292
0293 dcn314_smu_send_msg_with_param(
0294 clk_mgr,
0295 VBIOSSMC_MSG_UpdatePmeRestore,
0296 0);
0297 }
0298
0299 void dcn314_smu_set_dram_addr_high(struct clk_mgr_internal *clk_mgr, uint32_t addr_high)
0300 {
0301 if (!clk_mgr->smu_present)
0302 return;
0303
0304 dcn314_smu_send_msg_with_param(clk_mgr,
0305 VBIOSSMC_MSG_SetVbiosDramAddrHigh, addr_high);
0306 }
0307
0308 void dcn314_smu_set_dram_addr_low(struct clk_mgr_internal *clk_mgr, uint32_t addr_low)
0309 {
0310 if (!clk_mgr->smu_present)
0311 return;
0312
0313 dcn314_smu_send_msg_with_param(clk_mgr,
0314 VBIOSSMC_MSG_SetVbiosDramAddrLow, addr_low);
0315 }
0316
0317 void dcn314_smu_transfer_dpm_table_smu_2_dram(struct clk_mgr_internal *clk_mgr)
0318 {
0319 if (!clk_mgr->smu_present)
0320 return;
0321
0322 dcn314_smu_send_msg_with_param(clk_mgr,
0323 VBIOSSMC_MSG_TransferTableSmu2Dram, TABLE_DPMCLOCKS);
0324 }
0325
0326 void dcn314_smu_transfer_wm_table_dram_2_smu(struct clk_mgr_internal *clk_mgr)
0327 {
0328 if (!clk_mgr->smu_present)
0329 return;
0330
0331 dcn314_smu_send_msg_with_param(clk_mgr,
0332 VBIOSSMC_MSG_TransferTableDram2Smu, TABLE_WATERMARKS);
0333 }
0334
0335 void dcn314_smu_set_zstate_support(struct clk_mgr_internal *clk_mgr, enum dcn_zstate_support_state support)
0336 {
0337 unsigned int msg_id, param;
0338
0339 if (!clk_mgr->smu_present)
0340 return;
0341
0342 if (!clk_mgr->base.ctx->dc->debug.enable_z9_disable_interface &&
0343 (support == DCN_ZSTATE_SUPPORT_ALLOW_Z10_ONLY))
0344 support = DCN_ZSTATE_SUPPORT_DISALLOW;
0345
0346
0347
0348
0349 switch (support) {
0350
0351 case DCN_ZSTATE_SUPPORT_ALLOW:
0352 msg_id = VBIOSSMC_MSG_AllowZstatesEntry;
0353 param = 9;
0354 break;
0355
0356 case DCN_ZSTATE_SUPPORT_DISALLOW:
0357 msg_id = VBIOSSMC_MSG_AllowZstatesEntry;
0358 param = 8;
0359 break;
0360
0361
0362 case DCN_ZSTATE_SUPPORT_ALLOW_Z10_ONLY:
0363 msg_id = VBIOSSMC_MSG_AllowZstatesEntry;
0364 param = 0x00010008;
0365 break;
0366
0367 default:
0368 msg_id = VBIOSSMC_MSG_AllowZstatesEntry;
0369 param = 0;
0370 break;
0371 }
0372
0373
0374 dcn314_smu_send_msg_with_param(
0375 clk_mgr,
0376 msg_id,
0377 param);
0378
0379 }
0380
0381
0382 void dcn314_smu_set_dtbclk(struct clk_mgr_internal *clk_mgr, bool enable)
0383 {
0384 if (!clk_mgr->smu_present)
0385 return;
0386
0387 dcn314_smu_send_msg_with_param(
0388 clk_mgr,
0389 VBIOSSMC_MSG_SetDtbClk,
0390 enable);
0391 }