Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2016 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 <linux/pci.h>
0025 
0026 #include "smumgr.h"
0027 #include "vega10_inc.h"
0028 #include "soc15_common.h"
0029 #include "vega10_smumgr.h"
0030 #include "vega10_hwmgr.h"
0031 #include "vega10_ppsmc.h"
0032 #include "smu9_driver_if.h"
0033 #include "smu9_smumgr.h"
0034 #include "ppatomctrl.h"
0035 #include "pp_debug.h"
0036 
0037 
0038 static int vega10_copy_table_from_smc(struct pp_hwmgr *hwmgr,
0039         uint8_t *table, int16_t table_id)
0040 {
0041     struct vega10_smumgr *priv = hwmgr->smu_backend;
0042     struct amdgpu_device *adev = hwmgr->adev;
0043 
0044     PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE,
0045             "Invalid SMU Table ID!", return -EINVAL);
0046     PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
0047             "Invalid SMU Table version!", return -EINVAL);
0048     PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
0049             "Invalid SMU Table Length!", return -EINVAL);
0050     smum_send_msg_to_smc_with_parameter(hwmgr,
0051             PPSMC_MSG_SetDriverDramAddrHigh,
0052             upper_32_bits(priv->smu_tables.entry[table_id].mc_addr),
0053             NULL);
0054     smum_send_msg_to_smc_with_parameter(hwmgr,
0055             PPSMC_MSG_SetDriverDramAddrLow,
0056             lower_32_bits(priv->smu_tables.entry[table_id].mc_addr),
0057             NULL);
0058     smum_send_msg_to_smc_with_parameter(hwmgr,
0059             PPSMC_MSG_TransferTableSmu2Dram,
0060             priv->smu_tables.entry[table_id].table_id,
0061             NULL);
0062 
0063     amdgpu_asic_invalidate_hdp(adev, NULL);
0064 
0065     memcpy(table, priv->smu_tables.entry[table_id].table,
0066             priv->smu_tables.entry[table_id].size);
0067 
0068     return 0;
0069 }
0070 
0071 static int vega10_copy_table_to_smc(struct pp_hwmgr *hwmgr,
0072         uint8_t *table, int16_t table_id)
0073 {
0074     struct vega10_smumgr *priv = hwmgr->smu_backend;
0075     struct amdgpu_device *adev = hwmgr->adev;
0076 
0077     /* under sriov, vbios or hypervisor driver
0078      * has already copy table to smc so here only skip it
0079      */
0080     if (!hwmgr->not_vf)
0081         return 0;
0082 
0083     PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE,
0084             "Invalid SMU Table ID!", return -EINVAL);
0085     PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
0086             "Invalid SMU Table version!", return -EINVAL);
0087     PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
0088             "Invalid SMU Table Length!", return -EINVAL);
0089 
0090     memcpy(priv->smu_tables.entry[table_id].table, table,
0091             priv->smu_tables.entry[table_id].size);
0092 
0093     amdgpu_asic_flush_hdp(adev, NULL);
0094 
0095     smum_send_msg_to_smc_with_parameter(hwmgr,
0096             PPSMC_MSG_SetDriverDramAddrHigh,
0097             upper_32_bits(priv->smu_tables.entry[table_id].mc_addr),
0098             NULL);
0099     smum_send_msg_to_smc_with_parameter(hwmgr,
0100             PPSMC_MSG_SetDriverDramAddrLow,
0101             lower_32_bits(priv->smu_tables.entry[table_id].mc_addr),
0102             NULL);
0103     smum_send_msg_to_smc_with_parameter(hwmgr,
0104             PPSMC_MSG_TransferTableDram2Smu,
0105             priv->smu_tables.entry[table_id].table_id,
0106             NULL);
0107 
0108     return 0;
0109 }
0110 
0111 int vega10_enable_smc_features(struct pp_hwmgr *hwmgr,
0112                    bool enable, uint32_t feature_mask)
0113 {
0114     int msg = enable ? PPSMC_MSG_EnableSmuFeatures :
0115             PPSMC_MSG_DisableSmuFeatures;
0116 
0117     /* VF has no permission to change smu feature due
0118      * to security concern even under pp one vf mode
0119      * it still can't do it. For vega10, the smu in
0120      * vbios will enable the appropriate features.
0121      * */
0122     if (!hwmgr->not_vf)
0123         return 0;
0124 
0125     return smum_send_msg_to_smc_with_parameter(hwmgr,
0126             msg, feature_mask, NULL);
0127 }
0128 
0129 int vega10_get_enabled_smc_features(struct pp_hwmgr *hwmgr,
0130                 uint64_t *features_enabled)
0131 {
0132     uint32_t enabled_features;
0133 
0134     if (features_enabled == NULL)
0135         return -EINVAL;
0136 
0137     smum_send_msg_to_smc(hwmgr,
0138             PPSMC_MSG_GetEnabledSmuFeatures,
0139             &enabled_features);
0140     *features_enabled = enabled_features;
0141 
0142     return 0;
0143 }
0144 
0145 static bool vega10_is_dpm_running(struct pp_hwmgr *hwmgr)
0146 {
0147     uint64_t features_enabled = 0;
0148 
0149     vega10_get_enabled_smc_features(hwmgr, &features_enabled);
0150 
0151     if (features_enabled & SMC_DPM_FEATURES)
0152         return true;
0153     else
0154         return false;
0155 }
0156 
0157 static int vega10_set_tools_address(struct pp_hwmgr *hwmgr)
0158 {
0159     struct vega10_smumgr *priv = hwmgr->smu_backend;
0160 
0161     if (priv->smu_tables.entry[TOOLSTABLE].mc_addr) {
0162         smum_send_msg_to_smc_with_parameter(hwmgr,
0163                 PPSMC_MSG_SetToolsDramAddrHigh,
0164                 upper_32_bits(priv->smu_tables.entry[TOOLSTABLE].mc_addr),
0165                 NULL);
0166         smum_send_msg_to_smc_with_parameter(hwmgr,
0167                 PPSMC_MSG_SetToolsDramAddrLow,
0168                 lower_32_bits(priv->smu_tables.entry[TOOLSTABLE].mc_addr),
0169                 NULL);
0170     }
0171     return 0;
0172 }
0173 
0174 static int vega10_verify_smc_interface(struct pp_hwmgr *hwmgr)
0175 {
0176     uint32_t smc_driver_if_version;
0177     struct amdgpu_device *adev = hwmgr->adev;
0178     uint32_t dev_id;
0179     uint32_t rev_id;
0180 
0181     PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(hwmgr,
0182             PPSMC_MSG_GetDriverIfVersion,
0183             &smc_driver_if_version),
0184             "Attempt to get SMC IF Version Number Failed!",
0185             return -EINVAL);
0186 
0187     dev_id = adev->pdev->device;
0188     rev_id = adev->pdev->revision;
0189 
0190     if (!((dev_id == 0x687f) &&
0191         ((rev_id == 0xc0) ||
0192         (rev_id == 0xc1) ||
0193         (rev_id == 0xc3)))) {
0194         if (smc_driver_if_version != SMU9_DRIVER_IF_VERSION) {
0195             pr_err("Your firmware(0x%x) doesn't match SMU9_DRIVER_IF_VERSION(0x%x). Please update your firmware!\n",
0196                    smc_driver_if_version, SMU9_DRIVER_IF_VERSION);
0197             return -EINVAL;
0198         }
0199     }
0200 
0201     return 0;
0202 }
0203 
0204 static int vega10_smu_init(struct pp_hwmgr *hwmgr)
0205 {
0206     struct vega10_smumgr *priv;
0207     unsigned long tools_size;
0208     int ret;
0209     struct cgs_firmware_info info = {0};
0210 
0211     ret = cgs_get_firmware_info(hwmgr->device,
0212                     CGS_UCODE_ID_SMU,
0213                     &info);
0214     if (ret || !info.kptr)
0215         return -EINVAL;
0216 
0217     priv = kzalloc(sizeof(struct vega10_smumgr), GFP_KERNEL);
0218 
0219     if (!priv)
0220         return -ENOMEM;
0221 
0222     hwmgr->smu_backend = priv;
0223 
0224     /* allocate space for pptable */
0225     ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
0226             sizeof(PPTable_t),
0227             PAGE_SIZE,
0228             AMDGPU_GEM_DOMAIN_VRAM,
0229             &priv->smu_tables.entry[PPTABLE].handle,
0230             &priv->smu_tables.entry[PPTABLE].mc_addr,
0231             &priv->smu_tables.entry[PPTABLE].table);
0232     if (ret)
0233         goto free_backend;
0234 
0235     priv->smu_tables.entry[PPTABLE].version = 0x01;
0236     priv->smu_tables.entry[PPTABLE].size = sizeof(PPTable_t);
0237     priv->smu_tables.entry[PPTABLE].table_id = TABLE_PPTABLE;
0238 
0239     /* allocate space for watermarks table */
0240     ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
0241             sizeof(Watermarks_t),
0242             PAGE_SIZE,
0243             AMDGPU_GEM_DOMAIN_VRAM,
0244             &priv->smu_tables.entry[WMTABLE].handle,
0245             &priv->smu_tables.entry[WMTABLE].mc_addr,
0246             &priv->smu_tables.entry[WMTABLE].table);
0247 
0248     if (ret)
0249         goto err0;
0250 
0251     priv->smu_tables.entry[WMTABLE].version = 0x01;
0252     priv->smu_tables.entry[WMTABLE].size = sizeof(Watermarks_t);
0253     priv->smu_tables.entry[WMTABLE].table_id = TABLE_WATERMARKS;
0254 
0255     /* allocate space for AVFS table */
0256     ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
0257             sizeof(AvfsTable_t),
0258             PAGE_SIZE,
0259             AMDGPU_GEM_DOMAIN_VRAM,
0260             &priv->smu_tables.entry[AVFSTABLE].handle,
0261             &priv->smu_tables.entry[AVFSTABLE].mc_addr,
0262             &priv->smu_tables.entry[AVFSTABLE].table);
0263 
0264     if (ret)
0265         goto err1;
0266 
0267     priv->smu_tables.entry[AVFSTABLE].version = 0x01;
0268     priv->smu_tables.entry[AVFSTABLE].size = sizeof(AvfsTable_t);
0269     priv->smu_tables.entry[AVFSTABLE].table_id = TABLE_AVFS;
0270 
0271     tools_size = 0x19000;
0272     if (tools_size) {
0273         ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
0274                 tools_size,
0275                 PAGE_SIZE,
0276                 AMDGPU_GEM_DOMAIN_VRAM,
0277                 &priv->smu_tables.entry[TOOLSTABLE].handle,
0278                 &priv->smu_tables.entry[TOOLSTABLE].mc_addr,
0279                 &priv->smu_tables.entry[TOOLSTABLE].table);
0280         if (ret)
0281             goto err2;
0282         priv->smu_tables.entry[TOOLSTABLE].version = 0x01;
0283         priv->smu_tables.entry[TOOLSTABLE].size = tools_size;
0284         priv->smu_tables.entry[TOOLSTABLE].table_id = TABLE_PMSTATUSLOG;
0285     }
0286 
0287     /* allocate space for AVFS Fuse table */
0288     ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
0289             sizeof(AvfsFuseOverride_t),
0290             PAGE_SIZE,
0291             AMDGPU_GEM_DOMAIN_VRAM,
0292             &priv->smu_tables.entry[AVFSFUSETABLE].handle,
0293             &priv->smu_tables.entry[AVFSFUSETABLE].mc_addr,
0294             &priv->smu_tables.entry[AVFSFUSETABLE].table);
0295     if (ret)
0296         goto err3;
0297 
0298     priv->smu_tables.entry[AVFSFUSETABLE].version = 0x01;
0299     priv->smu_tables.entry[AVFSFUSETABLE].size = sizeof(AvfsFuseOverride_t);
0300     priv->smu_tables.entry[AVFSFUSETABLE].table_id = TABLE_AVFS_FUSE_OVERRIDE;
0301 
0302 
0303     return 0;
0304 
0305 err3:
0306     if (priv->smu_tables.entry[TOOLSTABLE].table)
0307         amdgpu_bo_free_kernel(&priv->smu_tables.entry[TOOLSTABLE].handle,
0308                 &priv->smu_tables.entry[TOOLSTABLE].mc_addr,
0309                 &priv->smu_tables.entry[TOOLSTABLE].table);
0310 err2:
0311     amdgpu_bo_free_kernel(&priv->smu_tables.entry[AVFSTABLE].handle,
0312                 &priv->smu_tables.entry[AVFSTABLE].mc_addr,
0313                 &priv->smu_tables.entry[AVFSTABLE].table);
0314 err1:
0315     amdgpu_bo_free_kernel(&priv->smu_tables.entry[WMTABLE].handle,
0316                 &priv->smu_tables.entry[WMTABLE].mc_addr,
0317                 &priv->smu_tables.entry[WMTABLE].table);
0318 err0:
0319     amdgpu_bo_free_kernel(&priv->smu_tables.entry[PPTABLE].handle,
0320             &priv->smu_tables.entry[PPTABLE].mc_addr,
0321             &priv->smu_tables.entry[PPTABLE].table);
0322 free_backend:
0323     kfree(hwmgr->smu_backend);
0324 
0325     return -EINVAL;
0326 }
0327 
0328 static int vega10_smu_fini(struct pp_hwmgr *hwmgr)
0329 {
0330     struct vega10_smumgr *priv = hwmgr->smu_backend;
0331 
0332     if (priv) {
0333         amdgpu_bo_free_kernel(&priv->smu_tables.entry[PPTABLE].handle,
0334                 &priv->smu_tables.entry[PPTABLE].mc_addr,
0335                 &priv->smu_tables.entry[PPTABLE].table);
0336         amdgpu_bo_free_kernel(&priv->smu_tables.entry[WMTABLE].handle,
0337                     &priv->smu_tables.entry[WMTABLE].mc_addr,
0338                     &priv->smu_tables.entry[WMTABLE].table);
0339         amdgpu_bo_free_kernel(&priv->smu_tables.entry[AVFSTABLE].handle,
0340                     &priv->smu_tables.entry[AVFSTABLE].mc_addr,
0341                     &priv->smu_tables.entry[AVFSTABLE].table);
0342         if (priv->smu_tables.entry[TOOLSTABLE].table)
0343             amdgpu_bo_free_kernel(&priv->smu_tables.entry[TOOLSTABLE].handle,
0344                     &priv->smu_tables.entry[TOOLSTABLE].mc_addr,
0345                     &priv->smu_tables.entry[TOOLSTABLE].table);
0346         amdgpu_bo_free_kernel(&priv->smu_tables.entry[AVFSFUSETABLE].handle,
0347                     &priv->smu_tables.entry[AVFSFUSETABLE].mc_addr,
0348                     &priv->smu_tables.entry[AVFSFUSETABLE].table);
0349         kfree(hwmgr->smu_backend);
0350         hwmgr->smu_backend = NULL;
0351     }
0352     return 0;
0353 }
0354 
0355 static int vega10_start_smu(struct pp_hwmgr *hwmgr)
0356 {
0357     if (!smu9_is_smc_ram_running(hwmgr))
0358         return -EINVAL;
0359 
0360     PP_ASSERT_WITH_CODE(!vega10_verify_smc_interface(hwmgr),
0361             "Failed to verify SMC interface!",
0362             return -EINVAL);
0363 
0364     vega10_set_tools_address(hwmgr);
0365 
0366     return 0;
0367 }
0368 
0369 static int vega10_smc_table_manager(struct pp_hwmgr *hwmgr, uint8_t *table,
0370                     uint16_t table_id, bool rw)
0371 {
0372     int ret;
0373 
0374     if (rw)
0375         ret = vega10_copy_table_from_smc(hwmgr, table, table_id);
0376     else
0377         ret = vega10_copy_table_to_smc(hwmgr, table, table_id);
0378 
0379     return ret;
0380 }
0381 
0382 const struct pp_smumgr_func vega10_smu_funcs = {
0383     .name = "vega10_smu",
0384     .smu_init = &vega10_smu_init,
0385     .smu_fini = &vega10_smu_fini,
0386     .start_smu = &vega10_start_smu,
0387     .request_smu_load_specific_fw = NULL,
0388     .send_msg_to_smc = &smu9_send_msg_to_smc,
0389     .send_msg_to_smc_with_parameter = &smu9_send_msg_to_smc_with_parameter,
0390     .download_pptable_settings = NULL,
0391     .upload_pptable_settings = NULL,
0392     .is_dpm_running = vega10_is_dpm_running,
0393     .get_argument = smu9_get_argument,
0394     .smc_table_manager = vega10_smc_table_manager,
0395 };