LCOV - code coverage report
Current view: top level - drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315 - dcn315_smu.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 89 0.0 %
Date: 2022-12-09 01:23:36 Functions: 0 17 0.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright 2021 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: AMD
      23             :  *
      24             :  */
      25             : 
      26             : #include "core_types.h"
      27             : #include "clk_mgr_internal.h"
      28             : #include "reg_helper.h"
      29             : #include "dm_helpers.h"
      30             : #include "dcn315_smu.h"
      31             : #include "mp/mp_13_0_5_offset.h"
      32             : 
      33             : #define MAX_INSTANCE                                        6
      34             : #define MAX_SEGMENT                                         6
      35             : 
      36             : struct IP_BASE_INSTANCE
      37             : {
      38             :     unsigned int segment[MAX_SEGMENT];
      39             : };
      40             : 
      41             : struct IP_BASE
      42             : {
      43             :     struct IP_BASE_INSTANCE instance[MAX_INSTANCE];
      44             : };
      45             : 
      46             : static const struct IP_BASE MP0_BASE = { { { { 0x00016000, 0x00DC0000, 0x00E00000, 0x00E40000, 0x0243FC00, 0 } },
      47             :                                         { { 0, 0, 0, 0, 0, 0 } },
      48             :                                         { { 0, 0, 0, 0, 0, 0 } },
      49             :                                         { { 0, 0, 0, 0, 0, 0 } },
      50             :                                         { { 0, 0, 0, 0, 0, 0 } },
      51             :                                         { { 0, 0, 0, 0, 0, 0 } } } };
      52             : static const struct IP_BASE NBIO_BASE = { { { { 0x00000000, 0x00000014, 0x00000D20, 0x00010400, 0x0241B000, 0x04040000 } },
      53             :                                         { { 0, 0, 0, 0, 0, 0 } },
      54             :                                         { { 0, 0, 0, 0, 0, 0 } },
      55             :                                         { { 0, 0, 0, 0, 0, 0 } },
      56             :                                         { { 0, 0, 0, 0, 0, 0 } },
      57             :                                         { { 0, 0, 0, 0, 0, 0 } } } };
      58             : 
      59             : #define regBIF_BX_PF2_RSMU_INDEX                                                                        0x0000
      60             : #define regBIF_BX_PF2_RSMU_INDEX_BASE_IDX                                                               1
      61             : #define regBIF_BX_PF2_RSMU_DATA                                                                         0x0001
      62             : #define regBIF_BX_PF2_RSMU_DATA_BASE_IDX                                                                1
      63             : 
      64             : #define REG(reg_name) \
      65             :         (MP0_BASE.instance[0].segment[reg ## reg_name ## _BASE_IDX] + reg ## reg_name)
      66             : 
      67             : #define FN(reg_name, field) \
      68             :         FD(reg_name##__##field)
      69             : 
      70             : #define REG_NBIO(reg_name) \
      71             :         (NBIO_BASE.instance[0].segment[regBIF_BX_PF2_ ## reg_name ## _BASE_IDX] + regBIF_BX_PF2_ ## reg_name)
      72             : 
      73             : #include "logger_types.h"
      74             : #undef DC_LOGGER
      75             : #define DC_LOGGER \
      76             :         CTX->logger
      77             : #define smu_print(str, ...) {DC_LOG_SMU(str, ##__VA_ARGS__); }
      78             : 
      79             : #define mmMP1_C2PMSG_3                            0x3B1050C
      80             : 
      81             : #define VBIOSSMC_MSG_TestMessage                  0x01 ///< To check if PMFW is alive and responding. Requirement specified by PMFW team
      82             : #define VBIOSSMC_MSG_GetPmfwVersion               0x02 ///< Get PMFW version
      83             : #define VBIOSSMC_MSG_Spare0                       0x03 ///< Spare0
      84             : #define VBIOSSMC_MSG_SetDispclkFreq               0x04 ///< Set display clock frequency in MHZ
      85             : #define VBIOSSMC_MSG_Spare1                       0x05 ///< Spare1
      86             : #define VBIOSSMC_MSG_SetDppclkFreq                0x06 ///< Set DPP clock frequency in MHZ
      87             : #define VBIOSSMC_MSG_SetHardMinDcfclkByFreq       0x07 ///< Set DCF clock frequency hard min in MHZ
      88             : #define VBIOSSMC_MSG_SetMinDeepSleepDcfclk        0x08 ///< Set DCF clock minimum frequency in deep sleep in MHZ
      89             : #define VBIOSSMC_MSG_GetDtbclkFreq                0x09 ///< Get display dtb clock frequency in MHZ in case VMIN does not support phy frequency
      90             : #define VBIOSSMC_MSG_SetDtbClk                    0x0A ///< Set dtb clock frequency, return frequemcy in MHZ
      91             : #define VBIOSSMC_MSG_SetDisplayCount              0x0B ///< Inform PMFW of number of display connected
      92             : #define VBIOSSMC_MSG_EnableTmdp48MHzRefclkPwrDown 0x0C ///< To ask PMFW turn off TMDP 48MHz refclk during display off to save power
      93             : #define VBIOSSMC_MSG_UpdatePmeRestore             0x0D ///< To ask PMFW to write into Azalia for PME wake up event
      94             : #define VBIOSSMC_MSG_SetVbiosDramAddrHigh         0x0E ///< Set DRAM address high 32 bits for WM table transfer
      95             : #define VBIOSSMC_MSG_SetVbiosDramAddrLow          0x0F ///< Set DRAM address low 32 bits for WM table transfer
      96             : #define VBIOSSMC_MSG_TransferTableSmu2Dram        0x10 ///< Transfer table from PMFW SRAM to system DRAM
      97             : #define VBIOSSMC_MSG_TransferTableDram2Smu        0x11 ///< Transfer table from system DRAM to PMFW
      98             : #define VBIOSSMC_MSG_SetDisplayIdleOptimizations  0x12 ///< Set Idle state optimization for display off
      99             : #define VBIOSSMC_MSG_GetDprefclkFreq              0x13 ///< Get DPREF clock frequency. Return in MHZ
     100             : #define VBIOSSMC_Message_Count                    0x14 ///< Total number of VBIS and DAL messages
     101             : 
     102             : #define VBIOSSMC_Status_BUSY                      0x0
     103             : #define VBIOSSMC_Result_OK                        0x01 ///< Message Response OK
     104             : #define VBIOSSMC_Result_Failed                    0xFF ///< Message Response Failed
     105             : #define VBIOSSMC_Result_UnknownCmd                0xFE ///< Message Response Unknown Command
     106             : #define VBIOSSMC_Result_CmdRejectedPrereq         0xFD ///< Message Response Command Failed Prerequisite
     107             : #define VBIOSSMC_Result_CmdRejectedBusy           0xFC ///< Message Response Command Rejected due to PMFW is busy. Sender should retry sending this message
     108             : 
     109             : /*
     110             :  * Function to be used instead of REG_WAIT macro because the wait ends when
     111             :  * the register is NOT EQUAL to zero, and because the translation in msg_if.h
     112             :  * won't work with REG_WAIT.
     113             :  */
     114           0 : static uint32_t dcn315_smu_wait_for_response(struct clk_mgr_internal *clk_mgr, unsigned int delay_us, unsigned int max_retries)
     115             : {
     116           0 :         uint32_t res_val = VBIOSSMC_Status_BUSY;
     117             : 
     118             :         do {
     119           0 :                 res_val = REG_READ(MP1_SMN_C2PMSG_38);
     120           0 :                 if (res_val != VBIOSSMC_Status_BUSY)
     121             :                         break;
     122             : 
     123           0 :                 if (delay_us >= 1000)
     124           0 :                         msleep(delay_us/1000);
     125           0 :                 else if (delay_us > 0)
     126           0 :                         udelay(delay_us);
     127           0 :         } while (max_retries--);
     128             : 
     129           0 :         return res_val;
     130             : }
     131             : 
     132           0 : static int dcn315_smu_send_msg_with_param(
     133             :                 struct clk_mgr_internal *clk_mgr,
     134             :                 unsigned int msg_id, unsigned int param)
     135             : {
     136             :         uint32_t result;
     137             : 
     138           0 :         result = dcn315_smu_wait_for_response(clk_mgr, 10, 200000);
     139             : 
     140             :         if (result != VBIOSSMC_Result_OK)
     141             :                 smu_print("SMU Response was not OK. SMU response after wait received is: %d\n", result);
     142             : 
     143           0 :         if (result == VBIOSSMC_Status_BUSY) {
     144             :                 return -1;
     145             :         }
     146             : 
     147             :         /* First clear response register */
     148           0 :         REG_WRITE(MP1_SMN_C2PMSG_38, VBIOSSMC_Status_BUSY);
     149             : 
     150             :         /* Set the parameter register for the SMU message, unit is Mhz */
     151           0 :         REG_WRITE(MP1_SMN_C2PMSG_37, param);
     152             : 
     153             :         /* Trigger the message transaction by writing the message ID */
     154           0 :         generic_write_indirect_reg(CTX,
     155             :                 REG_NBIO(RSMU_INDEX), REG_NBIO(RSMU_DATA),
     156             :                 mmMP1_C2PMSG_3, msg_id);
     157             : 
     158           0 :         result = dcn315_smu_wait_for_response(clk_mgr, 10, 200000);
     159             : 
     160           0 :         if (result == VBIOSSMC_Status_BUSY) {
     161           0 :                 ASSERT(0);
     162           0 :                 dm_helpers_smu_timeout(CTX, msg_id, param, 10 * 200000);
     163             :         }
     164             : 
     165           0 :         return REG_READ(MP1_SMN_C2PMSG_37);
     166             : }
     167             : 
     168           0 : int dcn315_smu_get_smu_version(struct clk_mgr_internal *clk_mgr)
     169             : {
     170           0 :         return dcn315_smu_send_msg_with_param(
     171             :                         clk_mgr,
     172             :                         VBIOSSMC_MSG_GetPmfwVersion,
     173             :                         0);
     174             : }
     175             : 
     176             : 
     177           0 : int dcn315_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_dispclk_khz)
     178             : {
     179           0 :         int actual_dispclk_set_mhz = -1;
     180             : 
     181           0 :         if (!clk_mgr->smu_present)
     182             :                 return requested_dispclk_khz;
     183             : 
     184             :         /*  Unit of SMU msg parameter is Mhz */
     185           0 :         actual_dispclk_set_mhz = dcn315_smu_send_msg_with_param(
     186             :                         clk_mgr,
     187             :                         VBIOSSMC_MSG_SetDispclkFreq,
     188           0 :                         khz_to_mhz_ceil(requested_dispclk_khz));
     189             : 
     190           0 :         return actual_dispclk_set_mhz * 1000;
     191             : }
     192             : 
     193           0 : int dcn315_smu_set_hard_min_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_dcfclk_khz)
     194             : {
     195           0 :         int actual_dcfclk_set_mhz = -1;
     196             : 
     197           0 :         if (!clk_mgr->base.ctx->dc->debug.pstate_enabled)
     198             :                 return -1;
     199             : 
     200           0 :         if (!clk_mgr->smu_present)
     201             :                 return requested_dcfclk_khz;
     202             : 
     203           0 :         actual_dcfclk_set_mhz = dcn315_smu_send_msg_with_param(
     204             :                         clk_mgr,
     205             :                         VBIOSSMC_MSG_SetHardMinDcfclkByFreq,
     206           0 :                         khz_to_mhz_ceil(requested_dcfclk_khz));
     207             : 
     208             : #ifdef DBG
     209             :         smu_print("actual_dcfclk_set_mhz %d is set to : %d\n", actual_dcfclk_set_mhz, actual_dcfclk_set_mhz * 1000);
     210             : #endif
     211             : 
     212           0 :         return actual_dcfclk_set_mhz * 1000;
     213             : }
     214             : 
     215           0 : int dcn315_smu_set_min_deep_sleep_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_min_ds_dcfclk_khz)
     216             : {
     217           0 :         int actual_min_ds_dcfclk_mhz = -1;
     218             : 
     219           0 :         if (!clk_mgr->base.ctx->dc->debug.pstate_enabled)
     220             :                 return -1;
     221             : 
     222           0 :         if (!clk_mgr->smu_present)
     223             :                 return requested_min_ds_dcfclk_khz;
     224             : 
     225           0 :         actual_min_ds_dcfclk_mhz = dcn315_smu_send_msg_with_param(
     226             :                         clk_mgr,
     227             :                         VBIOSSMC_MSG_SetMinDeepSleepDcfclk,
     228           0 :                         khz_to_mhz_ceil(requested_min_ds_dcfclk_khz));
     229             : 
     230           0 :         return actual_min_ds_dcfclk_mhz * 1000;
     231             : }
     232             : 
     233           0 : int dcn315_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_khz)
     234             : {
     235           0 :         int actual_dppclk_set_mhz = -1;
     236             : 
     237           0 :         if (!clk_mgr->smu_present)
     238             :                 return requested_dpp_khz;
     239             : 
     240           0 :         actual_dppclk_set_mhz = dcn315_smu_send_msg_with_param(
     241             :                         clk_mgr,
     242             :                         VBIOSSMC_MSG_SetDppclkFreq,
     243           0 :                         khz_to_mhz_ceil(requested_dpp_khz));
     244             : 
     245           0 :         return actual_dppclk_set_mhz * 1000;
     246             : }
     247             : 
     248           0 : void dcn315_smu_set_display_idle_optimization(struct clk_mgr_internal *clk_mgr, uint32_t idle_info)
     249             : {
     250           0 :         if (!clk_mgr->base.ctx->dc->debug.pstate_enabled)
     251             :                 return;
     252             : 
     253           0 :         if (!clk_mgr->smu_present)
     254             :                 return;
     255             : 
     256             :         //TODO: Work with smu team to define optimization options.
     257           0 :         dcn315_smu_send_msg_with_param(
     258             :                 clk_mgr,
     259             :                 VBIOSSMC_MSG_SetDisplayIdleOptimizations,
     260             :                 idle_info);
     261             : }
     262             : 
     263           0 : void dcn315_smu_enable_phy_refclk_pwrdwn(struct clk_mgr_internal *clk_mgr, bool enable)
     264             : {
     265           0 :         union display_idle_optimization_u idle_info = { 0 };
     266             : 
     267           0 :         if (!clk_mgr->smu_present)
     268           0 :                 return;
     269             : 
     270           0 :         if (enable) {
     271           0 :                 idle_info.idle_info.df_request_disabled = 1;
     272           0 :                 idle_info.idle_info.phy_ref_clk_off = 1;
     273             :         }
     274             : 
     275           0 :         dcn315_smu_send_msg_with_param(
     276             :                         clk_mgr,
     277             :                         VBIOSSMC_MSG_SetDisplayIdleOptimizations,
     278             :                         idle_info.data);
     279             : }
     280             : 
     281           0 : void dcn315_smu_enable_pme_wa(struct clk_mgr_internal *clk_mgr)
     282             : {
     283           0 :         if (!clk_mgr->smu_present)
     284             :                 return;
     285             : 
     286           0 :         dcn315_smu_send_msg_with_param(
     287             :                         clk_mgr,
     288             :                         VBIOSSMC_MSG_UpdatePmeRestore,
     289             :                         0);
     290             : }
     291           0 : void dcn315_smu_set_dram_addr_high(struct clk_mgr_internal *clk_mgr, uint32_t addr_high)
     292             : {
     293           0 :         if (!clk_mgr->smu_present)
     294             :                 return;
     295             : 
     296           0 :         dcn315_smu_send_msg_with_param(clk_mgr,
     297             :                         VBIOSSMC_MSG_SetVbiosDramAddrHigh, addr_high);
     298             : }
     299             : 
     300           0 : void dcn315_smu_set_dram_addr_low(struct clk_mgr_internal *clk_mgr, uint32_t addr_low)
     301             : {
     302           0 :         if (!clk_mgr->smu_present)
     303             :                 return;
     304             : 
     305           0 :         dcn315_smu_send_msg_with_param(clk_mgr,
     306             :                         VBIOSSMC_MSG_SetVbiosDramAddrLow, addr_low);
     307             : }
     308             : 
     309           0 : void dcn315_smu_transfer_dpm_table_smu_2_dram(struct clk_mgr_internal *clk_mgr)
     310             : {
     311           0 :         if (!clk_mgr->smu_present)
     312             :                 return;
     313             : 
     314           0 :         dcn315_smu_send_msg_with_param(clk_mgr,
     315             :                         VBIOSSMC_MSG_TransferTableSmu2Dram, TABLE_DPMCLOCKS);
     316             : }
     317             : 
     318           0 : void dcn315_smu_transfer_wm_table_dram_2_smu(struct clk_mgr_internal *clk_mgr)
     319             : {
     320           0 :         if (!clk_mgr->smu_present)
     321             :                 return;
     322             : 
     323           0 :         dcn315_smu_send_msg_with_param(clk_mgr,
     324             :                         VBIOSSMC_MSG_TransferTableDram2Smu, TABLE_WATERMARKS);
     325             : }
     326             : 
     327           0 : int dcn315_smu_get_dpref_clk(struct clk_mgr_internal *clk_mgr)
     328             : {
     329           0 :         int dprefclk_get_mhz = -1;
     330           0 :         if (clk_mgr->smu_present) {
     331           0 :                 dprefclk_get_mhz = dcn315_smu_send_msg_with_param(
     332             :                         clk_mgr,
     333             :                         VBIOSSMC_MSG_GetDprefclkFreq,
     334             :                         0);
     335             :         }
     336           0 :         return (dprefclk_get_mhz * 1000);
     337             : }
     338             : 
     339           0 : int dcn315_smu_get_dtbclk(struct clk_mgr_internal *clk_mgr)
     340             : {
     341           0 :         int fclk_get_mhz = -1;
     342             : 
     343           0 :         if (clk_mgr->smu_present) {
     344           0 :                 fclk_get_mhz = dcn315_smu_send_msg_with_param(
     345             :                         clk_mgr,
     346             :                         VBIOSSMC_MSG_GetDtbclkFreq,
     347             :                         0);
     348             :         }
     349           0 :         return (fclk_get_mhz * 1000);
     350             : }
     351             : 
     352           0 : void dcn315_smu_set_dtbclk(struct clk_mgr_internal *clk_mgr, bool enable)
     353             : {
     354           0 :         if (!clk_mgr->smu_present)
     355             :                 return;
     356             : 
     357           0 :         dcn315_smu_send_msg_with_param(
     358             :                         clk_mgr,
     359             :                         VBIOSSMC_MSG_SetDtbClk,
     360             :                         enable);
     361             : }

Generated by: LCOV version 1.14