Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2017 Advanced Micro Devices, Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  *
0022  */
0023 
0024 #include "smumgr.h"
0025 #include "vega12_inc.h"
0026 #include "soc15_common.h"
0027 #include "smu9_smumgr.h"
0028 #include "vega12_smumgr.h"
0029 #include "vega12_ppsmc.h"
0030 #include "vega12/smu9_driver_if.h"
0031 #include "ppatomctrl.h"
0032 #include "pp_debug.h"
0033 
0034 
0035 /*
0036  * Copy table from SMC into driver FB
0037  * @param   hwmgr    the address of the HW manager
0038  * @param   table_id    the driver's table ID to copy from
0039  */
0040 static int vega12_copy_table_from_smc(struct pp_hwmgr *hwmgr,
0041                       uint8_t *table, int16_t table_id)
0042 {
0043     struct vega12_smumgr *priv =
0044             (struct vega12_smumgr *)(hwmgr->smu_backend);
0045     struct amdgpu_device *adev = hwmgr->adev;
0046 
0047     PP_ASSERT_WITH_CODE(table_id < TABLE_COUNT,
0048             "Invalid SMU Table ID!", return -EINVAL);
0049     PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
0050             "Invalid SMU Table version!", return -EINVAL);
0051     PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
0052             "Invalid SMU Table Length!", return -EINVAL);
0053     PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr,
0054             PPSMC_MSG_SetDriverDramAddrHigh,
0055             upper_32_bits(priv->smu_tables.entry[table_id].mc_addr),
0056             NULL) == 0,
0057             "[CopyTableFromSMC] Attempt to Set Dram Addr High Failed!", return -EINVAL);
0058     PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr,
0059             PPSMC_MSG_SetDriverDramAddrLow,
0060             lower_32_bits(priv->smu_tables.entry[table_id].mc_addr),
0061             NULL) == 0,
0062             "[CopyTableFromSMC] Attempt to Set Dram Addr Low Failed!",
0063             return -EINVAL);
0064     PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr,
0065             PPSMC_MSG_TransferTableSmu2Dram,
0066             table_id,
0067             NULL) == 0,
0068             "[CopyTableFromSMC] Attempt to Transfer Table From SMU Failed!",
0069             return -EINVAL);
0070 
0071     amdgpu_asic_invalidate_hdp(adev, NULL);
0072 
0073     memcpy(table, priv->smu_tables.entry[table_id].table,
0074             priv->smu_tables.entry[table_id].size);
0075 
0076     return 0;
0077 }
0078 
0079 /*
0080  * Copy table from Driver FB into SMC
0081  * @param   hwmgr    the address of the HW manager
0082  * @param   table_id    the table to copy from
0083  */
0084 static int vega12_copy_table_to_smc(struct pp_hwmgr *hwmgr,
0085                     uint8_t *table, int16_t table_id)
0086 {
0087     struct vega12_smumgr *priv =
0088             (struct vega12_smumgr *)(hwmgr->smu_backend);
0089     struct amdgpu_device *adev = hwmgr->adev;
0090 
0091     PP_ASSERT_WITH_CODE(table_id < TABLE_COUNT,
0092             "Invalid SMU Table ID!", return -EINVAL);
0093     PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
0094             "Invalid SMU Table version!", return -EINVAL);
0095     PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
0096             "Invalid SMU Table Length!", return -EINVAL);
0097 
0098     memcpy(priv->smu_tables.entry[table_id].table, table,
0099             priv->smu_tables.entry[table_id].size);
0100 
0101     amdgpu_asic_flush_hdp(adev, NULL);
0102 
0103     PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr,
0104             PPSMC_MSG_SetDriverDramAddrHigh,
0105             upper_32_bits(priv->smu_tables.entry[table_id].mc_addr),
0106             NULL) == 0,
0107             "[CopyTableToSMC] Attempt to Set Dram Addr High Failed!",
0108             return -EINVAL;);
0109     PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr,
0110             PPSMC_MSG_SetDriverDramAddrLow,
0111             lower_32_bits(priv->smu_tables.entry[table_id].mc_addr),
0112             NULL) == 0,
0113             "[CopyTableToSMC] Attempt to Set Dram Addr Low Failed!",
0114             return -EINVAL);
0115     PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr,
0116             PPSMC_MSG_TransferTableDram2Smu,
0117             table_id,
0118             NULL) == 0,
0119             "[CopyTableToSMC] Attempt to Transfer Table To SMU Failed!",
0120             return -EINVAL);
0121 
0122     return 0;
0123 }
0124 
0125 int vega12_enable_smc_features(struct pp_hwmgr *hwmgr,
0126         bool enable, uint64_t feature_mask)
0127 {
0128     uint32_t smu_features_low, smu_features_high;
0129 
0130     smu_features_low = (uint32_t)((feature_mask & SMU_FEATURES_LOW_MASK) >> SMU_FEATURES_LOW_SHIFT);
0131     smu_features_high = (uint32_t)((feature_mask & SMU_FEATURES_HIGH_MASK) >> SMU_FEATURES_HIGH_SHIFT);
0132 
0133     if (enable) {
0134         PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr,
0135                 PPSMC_MSG_EnableSmuFeaturesLow, smu_features_low, NULL) == 0,
0136                 "[EnableDisableSMCFeatures] Attempt to enable SMU features Low failed!",
0137                 return -EINVAL);
0138         PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr,
0139                 PPSMC_MSG_EnableSmuFeaturesHigh, smu_features_high, NULL) == 0,
0140                 "[EnableDisableSMCFeatures] Attempt to enable SMU features High failed!",
0141                 return -EINVAL);
0142     } else {
0143         PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr,
0144                 PPSMC_MSG_DisableSmuFeaturesLow, smu_features_low, NULL) == 0,
0145                 "[EnableDisableSMCFeatures] Attempt to disable SMU features Low failed!",
0146                 return -EINVAL);
0147         PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr,
0148                 PPSMC_MSG_DisableSmuFeaturesHigh, smu_features_high, NULL) == 0,
0149                 "[EnableDisableSMCFeatures] Attempt to disable SMU features High failed!",
0150                 return -EINVAL);
0151     }
0152 
0153     return 0;
0154 }
0155 
0156 int vega12_get_enabled_smc_features(struct pp_hwmgr *hwmgr,
0157         uint64_t *features_enabled)
0158 {
0159     uint32_t smc_features_low, smc_features_high;
0160 
0161     if (features_enabled == NULL)
0162         return -EINVAL;
0163 
0164     PP_ASSERT_WITH_CODE(smum_send_msg_to_smc(hwmgr,
0165             PPSMC_MSG_GetEnabledSmuFeaturesLow,
0166             &smc_features_low) == 0,
0167             "[GetEnabledSMCFeatures] Attempt to get SMU features Low failed!",
0168             return -EINVAL);
0169 
0170     PP_ASSERT_WITH_CODE(smum_send_msg_to_smc(hwmgr,
0171             PPSMC_MSG_GetEnabledSmuFeaturesHigh,
0172             &smc_features_high) == 0,
0173             "[GetEnabledSMCFeatures] Attempt to get SMU features High failed!",
0174             return -EINVAL);
0175 
0176     *features_enabled = ((((uint64_t)smc_features_low << SMU_FEATURES_LOW_SHIFT) & SMU_FEATURES_LOW_MASK) |
0177             (((uint64_t)smc_features_high << SMU_FEATURES_HIGH_SHIFT) & SMU_FEATURES_HIGH_MASK));
0178 
0179     return 0;
0180 }
0181 
0182 static bool vega12_is_dpm_running(struct pp_hwmgr *hwmgr)
0183 {
0184     uint64_t features_enabled = 0;
0185 
0186     vega12_get_enabled_smc_features(hwmgr, &features_enabled);
0187 
0188     if (features_enabled & SMC_DPM_FEATURES)
0189         return true;
0190     else
0191         return false;
0192 }
0193 
0194 static int vega12_set_tools_address(struct pp_hwmgr *hwmgr)
0195 {
0196     struct vega12_smumgr *priv =
0197             (struct vega12_smumgr *)(hwmgr->smu_backend);
0198 
0199     if (priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr) {
0200         if (!smum_send_msg_to_smc_with_parameter(hwmgr,
0201                 PPSMC_MSG_SetToolsDramAddrHigh,
0202                 upper_32_bits(priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr),
0203                 NULL))
0204             smum_send_msg_to_smc_with_parameter(hwmgr,
0205                     PPSMC_MSG_SetToolsDramAddrLow,
0206                     lower_32_bits(priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr),
0207                     NULL);
0208     }
0209     return 0;
0210 }
0211 
0212 static int vega12_smu_init(struct pp_hwmgr *hwmgr)
0213 {
0214     struct vega12_smumgr *priv;
0215     unsigned long tools_size;
0216     struct cgs_firmware_info info = {0};
0217     int ret;
0218 
0219     ret = cgs_get_firmware_info(hwmgr->device, CGS_UCODE_ID_SMU,
0220                 &info);
0221     if (ret || !info.kptr)
0222         return -EINVAL;
0223 
0224     priv = kzalloc(sizeof(struct vega12_smumgr), GFP_KERNEL);
0225     if (!priv)
0226         return -ENOMEM;
0227 
0228     hwmgr->smu_backend = priv;
0229 
0230     /* allocate space for pptable */
0231     ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
0232             sizeof(PPTable_t),
0233             PAGE_SIZE,
0234             AMDGPU_GEM_DOMAIN_VRAM,
0235             &priv->smu_tables.entry[TABLE_PPTABLE].handle,
0236             &priv->smu_tables.entry[TABLE_PPTABLE].mc_addr,
0237             &priv->smu_tables.entry[TABLE_PPTABLE].table);
0238     if (ret)
0239         goto free_backend;
0240 
0241     priv->smu_tables.entry[TABLE_PPTABLE].version = 0x01;
0242     priv->smu_tables.entry[TABLE_PPTABLE].size = sizeof(PPTable_t);
0243 
0244     /* allocate space for watermarks table */
0245     ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
0246                       sizeof(Watermarks_t),
0247                       PAGE_SIZE,
0248                       AMDGPU_GEM_DOMAIN_VRAM,
0249                       &priv->smu_tables.entry[TABLE_WATERMARKS].handle,
0250                       &priv->smu_tables.entry[TABLE_WATERMARKS].mc_addr,
0251                       &priv->smu_tables.entry[TABLE_WATERMARKS].table);
0252 
0253     if (ret)
0254         goto err0;
0255 
0256     priv->smu_tables.entry[TABLE_WATERMARKS].version = 0x01;
0257     priv->smu_tables.entry[TABLE_WATERMARKS].size = sizeof(Watermarks_t);
0258 
0259     tools_size = 0x19000;
0260     if (tools_size) {
0261         ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
0262                           tools_size,
0263                           PAGE_SIZE,
0264                           AMDGPU_GEM_DOMAIN_VRAM,
0265                           &priv->smu_tables.entry[TABLE_PMSTATUSLOG].handle,
0266                           &priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr,
0267                           &priv->smu_tables.entry[TABLE_PMSTATUSLOG].table);
0268         if (ret)
0269             goto err1;
0270 
0271         priv->smu_tables.entry[TABLE_PMSTATUSLOG].version = 0x01;
0272         priv->smu_tables.entry[TABLE_PMSTATUSLOG].size = tools_size;
0273     }
0274 
0275     /* allocate space for AVFS Fuse table */
0276     ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
0277                       sizeof(AvfsFuseOverride_t),
0278                       PAGE_SIZE,
0279                       AMDGPU_GEM_DOMAIN_VRAM,
0280                       &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].handle,
0281                       &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].mc_addr,
0282                       &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].table);
0283 
0284     if (ret)
0285         goto err2;
0286 
0287     priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].version = 0x01;
0288     priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].size = sizeof(AvfsFuseOverride_t);
0289 
0290     /* allocate space for OverDrive table */
0291     ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
0292                       sizeof(OverDriveTable_t),
0293                       PAGE_SIZE,
0294                       AMDGPU_GEM_DOMAIN_VRAM,
0295                       &priv->smu_tables.entry[TABLE_OVERDRIVE].handle,
0296                       &priv->smu_tables.entry[TABLE_OVERDRIVE].mc_addr,
0297                       &priv->smu_tables.entry[TABLE_OVERDRIVE].table);
0298     if (ret)
0299         goto err3;
0300 
0301     priv->smu_tables.entry[TABLE_OVERDRIVE].version = 0x01;
0302     priv->smu_tables.entry[TABLE_OVERDRIVE].size = sizeof(OverDriveTable_t);
0303 
0304     /* allocate space for SMU_METRICS table */
0305     ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
0306                       sizeof(SmuMetrics_t),
0307                       PAGE_SIZE,
0308                       AMDGPU_GEM_DOMAIN_VRAM,
0309                       &priv->smu_tables.entry[TABLE_SMU_METRICS].handle,
0310                       &priv->smu_tables.entry[TABLE_SMU_METRICS].mc_addr,
0311                       &priv->smu_tables.entry[TABLE_SMU_METRICS].table);
0312     if (ret)
0313         goto err4;
0314 
0315     priv->smu_tables.entry[TABLE_SMU_METRICS].version = 0x01;
0316     priv->smu_tables.entry[TABLE_SMU_METRICS].size = sizeof(SmuMetrics_t);
0317 
0318     return 0;
0319 
0320 err4:
0321     amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_OVERDRIVE].handle,
0322                 &priv->smu_tables.entry[TABLE_OVERDRIVE].mc_addr,
0323                 &priv->smu_tables.entry[TABLE_OVERDRIVE].table);
0324 err3:
0325     amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].handle,
0326                 &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].mc_addr,
0327                 &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].table);
0328 err2:
0329     if (priv->smu_tables.entry[TABLE_PMSTATUSLOG].table)
0330         amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PMSTATUSLOG].handle,
0331                 &priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr,
0332                 &priv->smu_tables.entry[TABLE_PMSTATUSLOG].table);
0333 err1:
0334     amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_WATERMARKS].handle,
0335                 &priv->smu_tables.entry[TABLE_WATERMARKS].mc_addr,
0336                 &priv->smu_tables.entry[TABLE_WATERMARKS].table);
0337 err0:
0338     amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PPTABLE].handle,
0339             &priv->smu_tables.entry[TABLE_PPTABLE].mc_addr,
0340             &priv->smu_tables.entry[TABLE_PPTABLE].table);
0341 free_backend:
0342     kfree(hwmgr->smu_backend);
0343 
0344     return -EINVAL;
0345 }
0346 
0347 static int vega12_smu_fini(struct pp_hwmgr *hwmgr)
0348 {
0349     struct vega12_smumgr *priv =
0350             (struct vega12_smumgr *)(hwmgr->smu_backend);
0351 
0352     if (priv) {
0353         amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PPTABLE].handle,
0354                       &priv->smu_tables.entry[TABLE_PPTABLE].mc_addr,
0355                       &priv->smu_tables.entry[TABLE_PPTABLE].table);
0356         amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_WATERMARKS].handle,
0357                       &priv->smu_tables.entry[TABLE_WATERMARKS].mc_addr,
0358                       &priv->smu_tables.entry[TABLE_WATERMARKS].table);
0359         if (priv->smu_tables.entry[TABLE_PMSTATUSLOG].table)
0360             amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PMSTATUSLOG].handle,
0361                           &priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr,
0362                           &priv->smu_tables.entry[TABLE_PMSTATUSLOG].table);
0363         amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].handle,
0364                       &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].mc_addr,
0365                       &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].table);
0366         amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_OVERDRIVE].handle,
0367                       &priv->smu_tables.entry[TABLE_OVERDRIVE].mc_addr,
0368                       &priv->smu_tables.entry[TABLE_OVERDRIVE].table);
0369         amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_SMU_METRICS].handle,
0370                       &priv->smu_tables.entry[TABLE_SMU_METRICS].mc_addr,
0371                       &priv->smu_tables.entry[TABLE_SMU_METRICS].table);
0372         kfree(hwmgr->smu_backend);
0373         hwmgr->smu_backend = NULL;
0374     }
0375     return 0;
0376 }
0377 
0378 static int vega12_start_smu(struct pp_hwmgr *hwmgr)
0379 {
0380     PP_ASSERT_WITH_CODE(smu9_is_smc_ram_running(hwmgr),
0381             "SMC is not running!",
0382             return -EINVAL);
0383 
0384     vega12_set_tools_address(hwmgr);
0385 
0386     return 0;
0387 }
0388 
0389 static int vega12_smc_table_manager(struct pp_hwmgr *hwmgr, uint8_t *table,
0390                     uint16_t table_id, bool rw)
0391 {
0392     int ret;
0393 
0394     if (rw)
0395         ret = vega12_copy_table_from_smc(hwmgr, table, table_id);
0396     else
0397         ret = vega12_copy_table_to_smc(hwmgr, table, table_id);
0398 
0399     return ret;
0400 }
0401 
0402 const struct pp_smumgr_func vega12_smu_funcs = {
0403     .name = "vega12_smu",
0404     .smu_init = &vega12_smu_init,
0405     .smu_fini = &vega12_smu_fini,
0406     .start_smu = &vega12_start_smu,
0407     .request_smu_load_specific_fw = NULL,
0408     .send_msg_to_smc = &smu9_send_msg_to_smc,
0409     .send_msg_to_smc_with_parameter = &smu9_send_msg_to_smc_with_parameter,
0410     .download_pptable_settings = NULL,
0411     .upload_pptable_settings = NULL,
0412     .is_dpm_running = vega12_is_dpm_running,
0413     .get_argument = smu9_get_argument,
0414     .smc_table_manager = vega12_smc_table_manager,
0415 };