root/drivers/gpu/drm/amd/powerplay/smumgr/vega12_smumgr.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. vega12_copy_table_from_smc
  2. vega12_copy_table_to_smc
  3. vega12_enable_smc_features
  4. vega12_get_enabled_smc_features
  5. vega12_is_dpm_running
  6. vega12_set_tools_address
  7. vega12_smu_init
  8. vega12_smu_fini
  9. vega12_start_smu
  10. vega12_smc_table_manager

   1 /*
   2  * Copyright 2017 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 "smumgr.h"
  25 #include "vega12_inc.h"
  26 #include "soc15_common.h"
  27 #include "smu9_smumgr.h"
  28 #include "vega12_smumgr.h"
  29 #include "vega12_ppsmc.h"
  30 #include "vega12/smu9_driver_if.h"
  31 #include "ppatomctrl.h"
  32 #include "pp_debug.h"
  33 
  34 
  35 /*
  36  * Copy table from SMC into driver FB
  37  * @param   hwmgr    the address of the HW manager
  38  * @param   table_id    the driver's table ID to copy from
  39  */
  40 static int vega12_copy_table_from_smc(struct pp_hwmgr *hwmgr,
  41                                       uint8_t *table, int16_t table_id)
  42 {
  43         struct vega12_smumgr *priv =
  44                         (struct vega12_smumgr *)(hwmgr->smu_backend);
  45         struct amdgpu_device *adev = hwmgr->adev;
  46 
  47         PP_ASSERT_WITH_CODE(table_id < TABLE_COUNT,
  48                         "Invalid SMU Table ID!", return -EINVAL);
  49         PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
  50                         "Invalid SMU Table version!", return -EINVAL);
  51         PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
  52                         "Invalid SMU Table Length!", return -EINVAL);
  53         PP_ASSERT_WITH_CODE(smu9_send_msg_to_smc_with_parameter(hwmgr,
  54                         PPSMC_MSG_SetDriverDramAddrHigh,
  55                         upper_32_bits(priv->smu_tables.entry[table_id].mc_addr)) == 0,
  56                         "[CopyTableFromSMC] Attempt to Set Dram Addr High Failed!", return -EINVAL);
  57         PP_ASSERT_WITH_CODE(smu9_send_msg_to_smc_with_parameter(hwmgr,
  58                         PPSMC_MSG_SetDriverDramAddrLow,
  59                         lower_32_bits(priv->smu_tables.entry[table_id].mc_addr)) == 0,
  60                         "[CopyTableFromSMC] Attempt to Set Dram Addr Low Failed!",
  61                         return -EINVAL);
  62         PP_ASSERT_WITH_CODE(smu9_send_msg_to_smc_with_parameter(hwmgr,
  63                         PPSMC_MSG_TransferTableSmu2Dram,
  64                         table_id) == 0,
  65                         "[CopyTableFromSMC] Attempt to Transfer Table From SMU Failed!",
  66                         return -EINVAL);
  67 
  68         /* flush hdp cache */
  69         adev->nbio_funcs->hdp_flush(adev, NULL);
  70 
  71         memcpy(table, priv->smu_tables.entry[table_id].table,
  72                         priv->smu_tables.entry[table_id].size);
  73 
  74         return 0;
  75 }
  76 
  77 /*
  78  * Copy table from Driver FB into SMC
  79  * @param   hwmgr    the address of the HW manager
  80  * @param   table_id    the table to copy from
  81  */
  82 static int vega12_copy_table_to_smc(struct pp_hwmgr *hwmgr,
  83                                     uint8_t *table, int16_t table_id)
  84 {
  85         struct vega12_smumgr *priv =
  86                         (struct vega12_smumgr *)(hwmgr->smu_backend);
  87 
  88         PP_ASSERT_WITH_CODE(table_id < TABLE_COUNT,
  89                         "Invalid SMU Table ID!", return -EINVAL);
  90         PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
  91                         "Invalid SMU Table version!", return -EINVAL);
  92         PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
  93                         "Invalid SMU Table Length!", return -EINVAL);
  94 
  95         memcpy(priv->smu_tables.entry[table_id].table, table,
  96                         priv->smu_tables.entry[table_id].size);
  97 
  98         PP_ASSERT_WITH_CODE(smu9_send_msg_to_smc_with_parameter(hwmgr,
  99                         PPSMC_MSG_SetDriverDramAddrHigh,
 100                         upper_32_bits(priv->smu_tables.entry[table_id].mc_addr)) == 0,
 101                         "[CopyTableToSMC] Attempt to Set Dram Addr High Failed!",
 102                         return -EINVAL;);
 103         PP_ASSERT_WITH_CODE(smu9_send_msg_to_smc_with_parameter(hwmgr,
 104                         PPSMC_MSG_SetDriverDramAddrLow,
 105                         lower_32_bits(priv->smu_tables.entry[table_id].mc_addr)) == 0,
 106                         "[CopyTableToSMC] Attempt to Set Dram Addr Low Failed!",
 107                         return -EINVAL);
 108         PP_ASSERT_WITH_CODE(smu9_send_msg_to_smc_with_parameter(hwmgr,
 109                         PPSMC_MSG_TransferTableDram2Smu,
 110                         table_id) == 0,
 111                         "[CopyTableToSMC] Attempt to Transfer Table To SMU Failed!",
 112                         return -EINVAL);
 113 
 114         return 0;
 115 }
 116 
 117 int vega12_enable_smc_features(struct pp_hwmgr *hwmgr,
 118                 bool enable, uint64_t feature_mask)
 119 {
 120         uint32_t smu_features_low, smu_features_high;
 121 
 122         smu_features_low = (uint32_t)((feature_mask & SMU_FEATURES_LOW_MASK) >> SMU_FEATURES_LOW_SHIFT);
 123         smu_features_high = (uint32_t)((feature_mask & SMU_FEATURES_HIGH_MASK) >> SMU_FEATURES_HIGH_SHIFT);
 124 
 125         if (enable) {
 126                 PP_ASSERT_WITH_CODE(smu9_send_msg_to_smc_with_parameter(hwmgr,
 127                                 PPSMC_MSG_EnableSmuFeaturesLow, smu_features_low) == 0,
 128                                 "[EnableDisableSMCFeatures] Attemp to enable SMU features Low failed!",
 129                                 return -EINVAL);
 130                 PP_ASSERT_WITH_CODE(smu9_send_msg_to_smc_with_parameter(hwmgr,
 131                                 PPSMC_MSG_EnableSmuFeaturesHigh, smu_features_high) == 0,
 132                                 "[EnableDisableSMCFeatures] Attemp to enable SMU features High failed!",
 133                                 return -EINVAL);
 134         } else {
 135                 PP_ASSERT_WITH_CODE(smu9_send_msg_to_smc_with_parameter(hwmgr,
 136                                 PPSMC_MSG_DisableSmuFeaturesLow, smu_features_low) == 0,
 137                                 "[EnableDisableSMCFeatures] Attemp to disable SMU features Low failed!",
 138                                 return -EINVAL);
 139                 PP_ASSERT_WITH_CODE(smu9_send_msg_to_smc_with_parameter(hwmgr,
 140                                 PPSMC_MSG_DisableSmuFeaturesHigh, smu_features_high) == 0,
 141                                 "[EnableDisableSMCFeatures] Attemp to disable SMU features High failed!",
 142                                 return -EINVAL);
 143         }
 144 
 145         return 0;
 146 }
 147 
 148 int vega12_get_enabled_smc_features(struct pp_hwmgr *hwmgr,
 149                 uint64_t *features_enabled)
 150 {
 151         uint32_t smc_features_low, smc_features_high;
 152 
 153         if (features_enabled == NULL)
 154                 return -EINVAL;
 155 
 156         PP_ASSERT_WITH_CODE(smu9_send_msg_to_smc(hwmgr,
 157                         PPSMC_MSG_GetEnabledSmuFeaturesLow) == 0,
 158                         "[GetEnabledSMCFeatures] Attemp to get SMU features Low failed!",
 159                         return -EINVAL);
 160         smc_features_low = smu9_get_argument(hwmgr);
 161 
 162         PP_ASSERT_WITH_CODE(smu9_send_msg_to_smc(hwmgr,
 163                         PPSMC_MSG_GetEnabledSmuFeaturesHigh) == 0,
 164                         "[GetEnabledSMCFeatures] Attemp to get SMU features High failed!",
 165                         return -EINVAL);
 166         smc_features_high = smu9_get_argument(hwmgr);
 167 
 168         *features_enabled = ((((uint64_t)smc_features_low << SMU_FEATURES_LOW_SHIFT) & SMU_FEATURES_LOW_MASK) |
 169                         (((uint64_t)smc_features_high << SMU_FEATURES_HIGH_SHIFT) & SMU_FEATURES_HIGH_MASK));
 170 
 171         return 0;
 172 }
 173 
 174 static bool vega12_is_dpm_running(struct pp_hwmgr *hwmgr)
 175 {
 176         uint64_t features_enabled = 0;
 177 
 178         vega12_get_enabled_smc_features(hwmgr, &features_enabled);
 179 
 180         if (features_enabled & SMC_DPM_FEATURES)
 181                 return true;
 182         else
 183                 return false;
 184 }
 185 
 186 static int vega12_set_tools_address(struct pp_hwmgr *hwmgr)
 187 {
 188         struct vega12_smumgr *priv =
 189                         (struct vega12_smumgr *)(hwmgr->smu_backend);
 190 
 191         if (priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr) {
 192                 if (!smu9_send_msg_to_smc_with_parameter(hwmgr,
 193                                 PPSMC_MSG_SetToolsDramAddrHigh,
 194                                 upper_32_bits(priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr)))
 195                         smu9_send_msg_to_smc_with_parameter(hwmgr,
 196                                         PPSMC_MSG_SetToolsDramAddrLow,
 197                                         lower_32_bits(priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr));
 198         }
 199         return 0;
 200 }
 201 
 202 static int vega12_smu_init(struct pp_hwmgr *hwmgr)
 203 {
 204         struct vega12_smumgr *priv;
 205         unsigned long tools_size;
 206         struct cgs_firmware_info info = {0};
 207         int ret;
 208 
 209         ret = cgs_get_firmware_info(hwmgr->device, CGS_UCODE_ID_SMU,
 210                                 &info);
 211         if (ret || !info.kptr)
 212                 return -EINVAL;
 213 
 214         priv = kzalloc(sizeof(struct vega12_smumgr), GFP_KERNEL);
 215         if (!priv)
 216                 return -ENOMEM;
 217 
 218         hwmgr->smu_backend = priv;
 219 
 220         /* allocate space for pptable */
 221         ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
 222                         sizeof(PPTable_t),
 223                         PAGE_SIZE,
 224                         AMDGPU_GEM_DOMAIN_VRAM,
 225                         &priv->smu_tables.entry[TABLE_PPTABLE].handle,
 226                         &priv->smu_tables.entry[TABLE_PPTABLE].mc_addr,
 227                         &priv->smu_tables.entry[TABLE_PPTABLE].table);
 228         if (ret)
 229                 goto free_backend;
 230 
 231         priv->smu_tables.entry[TABLE_PPTABLE].version = 0x01;
 232         priv->smu_tables.entry[TABLE_PPTABLE].size = sizeof(PPTable_t);
 233 
 234         /* allocate space for watermarks table */
 235         ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
 236                                       sizeof(Watermarks_t),
 237                                       PAGE_SIZE,
 238                                       AMDGPU_GEM_DOMAIN_VRAM,
 239                                       &priv->smu_tables.entry[TABLE_WATERMARKS].handle,
 240                                       &priv->smu_tables.entry[TABLE_WATERMARKS].mc_addr,
 241                                       &priv->smu_tables.entry[TABLE_WATERMARKS].table);
 242 
 243         if (ret)
 244                 goto err0;
 245 
 246         priv->smu_tables.entry[TABLE_WATERMARKS].version = 0x01;
 247         priv->smu_tables.entry[TABLE_WATERMARKS].size = sizeof(Watermarks_t);
 248 
 249         tools_size = 0x19000;
 250         if (tools_size) {
 251                 ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
 252                                               tools_size,
 253                                               PAGE_SIZE,
 254                                               AMDGPU_GEM_DOMAIN_VRAM,
 255                                               &priv->smu_tables.entry[TABLE_PMSTATUSLOG].handle,
 256                                               &priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr,
 257                                               &priv->smu_tables.entry[TABLE_PMSTATUSLOG].table);
 258                 if (ret)
 259                         goto err1;
 260 
 261                 priv->smu_tables.entry[TABLE_PMSTATUSLOG].version = 0x01;
 262                 priv->smu_tables.entry[TABLE_PMSTATUSLOG].size = tools_size;
 263         }
 264 
 265         /* allocate space for AVFS Fuse table */
 266         ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
 267                                       sizeof(AvfsFuseOverride_t),
 268                                       PAGE_SIZE,
 269                                       AMDGPU_GEM_DOMAIN_VRAM,
 270                                       &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].handle,
 271                                       &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].mc_addr,
 272                                       &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].table);
 273 
 274         if (ret)
 275                 goto err2;
 276 
 277         priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].version = 0x01;
 278         priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].size = sizeof(AvfsFuseOverride_t);
 279 
 280         /* allocate space for OverDrive table */
 281         ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
 282                                       sizeof(OverDriveTable_t),
 283                                       PAGE_SIZE,
 284                                       AMDGPU_GEM_DOMAIN_VRAM,
 285                                       &priv->smu_tables.entry[TABLE_OVERDRIVE].handle,
 286                                       &priv->smu_tables.entry[TABLE_OVERDRIVE].mc_addr,
 287                                       &priv->smu_tables.entry[TABLE_OVERDRIVE].table);
 288         if (ret)
 289                 goto err3;
 290 
 291         priv->smu_tables.entry[TABLE_OVERDRIVE].version = 0x01;
 292         priv->smu_tables.entry[TABLE_OVERDRIVE].size = sizeof(OverDriveTable_t);
 293 
 294         /* allocate space for SMU_METRICS table */
 295         ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
 296                                       sizeof(SmuMetrics_t),
 297                                       PAGE_SIZE,
 298                                       AMDGPU_GEM_DOMAIN_VRAM,
 299                                       &priv->smu_tables.entry[TABLE_SMU_METRICS].handle,
 300                                       &priv->smu_tables.entry[TABLE_SMU_METRICS].mc_addr,
 301                                       &priv->smu_tables.entry[TABLE_SMU_METRICS].table);
 302         if (ret)
 303                 goto err4;
 304 
 305         priv->smu_tables.entry[TABLE_SMU_METRICS].version = 0x01;
 306         priv->smu_tables.entry[TABLE_SMU_METRICS].size = sizeof(SmuMetrics_t);
 307 
 308         return 0;
 309 
 310 err4:
 311         amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_OVERDRIVE].handle,
 312                                 &priv->smu_tables.entry[TABLE_OVERDRIVE].mc_addr,
 313                                 &priv->smu_tables.entry[TABLE_OVERDRIVE].table);
 314 err3:
 315         amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].handle,
 316                                 &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].mc_addr,
 317                                 &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].table);
 318 err2:
 319         if (priv->smu_tables.entry[TABLE_PMSTATUSLOG].table)
 320                 amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PMSTATUSLOG].handle,
 321                                 &priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr,
 322                                 &priv->smu_tables.entry[TABLE_PMSTATUSLOG].table);
 323 err1:
 324         amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_WATERMARKS].handle,
 325                                 &priv->smu_tables.entry[TABLE_WATERMARKS].mc_addr,
 326                                 &priv->smu_tables.entry[TABLE_WATERMARKS].table);
 327 err0:
 328         amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PPTABLE].handle,
 329                         &priv->smu_tables.entry[TABLE_PPTABLE].mc_addr,
 330                         &priv->smu_tables.entry[TABLE_PPTABLE].table);
 331 free_backend:
 332         kfree(hwmgr->smu_backend);
 333 
 334         return -EINVAL;
 335 }
 336 
 337 static int vega12_smu_fini(struct pp_hwmgr *hwmgr)
 338 {
 339         struct vega12_smumgr *priv =
 340                         (struct vega12_smumgr *)(hwmgr->smu_backend);
 341 
 342         if (priv) {
 343                 amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PPTABLE].handle,
 344                                       &priv->smu_tables.entry[TABLE_PPTABLE].mc_addr,
 345                                       &priv->smu_tables.entry[TABLE_PPTABLE].table);
 346                 amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_WATERMARKS].handle,
 347                                       &priv->smu_tables.entry[TABLE_WATERMARKS].mc_addr,
 348                                       &priv->smu_tables.entry[TABLE_WATERMARKS].table);
 349                 if (priv->smu_tables.entry[TABLE_PMSTATUSLOG].table)
 350                         amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PMSTATUSLOG].handle,
 351                                               &priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr,
 352                                               &priv->smu_tables.entry[TABLE_PMSTATUSLOG].table);
 353                 amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].handle,
 354                                       &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].mc_addr,
 355                                       &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].table);
 356                 amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_OVERDRIVE].handle,
 357                                       &priv->smu_tables.entry[TABLE_OVERDRIVE].mc_addr,
 358                                       &priv->smu_tables.entry[TABLE_OVERDRIVE].table);
 359                 amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_SMU_METRICS].handle,
 360                                       &priv->smu_tables.entry[TABLE_SMU_METRICS].mc_addr,
 361                                       &priv->smu_tables.entry[TABLE_SMU_METRICS].table);
 362                 kfree(hwmgr->smu_backend);
 363                 hwmgr->smu_backend = NULL;
 364         }
 365         return 0;
 366 }
 367 
 368 static int vega12_start_smu(struct pp_hwmgr *hwmgr)
 369 {
 370         PP_ASSERT_WITH_CODE(smu9_is_smc_ram_running(hwmgr),
 371                         "SMC is not running!",
 372                         return -EINVAL);
 373 
 374         vega12_set_tools_address(hwmgr);
 375 
 376         return 0;
 377 }
 378 
 379 static int vega12_smc_table_manager(struct pp_hwmgr *hwmgr, uint8_t *table,
 380                                     uint16_t table_id, bool rw)
 381 {
 382         int ret;
 383 
 384         if (rw)
 385                 ret = vega12_copy_table_from_smc(hwmgr, table, table_id);
 386         else
 387                 ret = vega12_copy_table_to_smc(hwmgr, table, table_id);
 388 
 389         return ret;
 390 }
 391 
 392 const struct pp_smumgr_func vega12_smu_funcs = {
 393         .name = "vega12_smu",
 394         .smu_init = &vega12_smu_init,
 395         .smu_fini = &vega12_smu_fini,
 396         .start_smu = &vega12_start_smu,
 397         .request_smu_load_specific_fw = NULL,
 398         .send_msg_to_smc = &smu9_send_msg_to_smc,
 399         .send_msg_to_smc_with_parameter = &smu9_send_msg_to_smc_with_parameter,
 400         .download_pptable_settings = NULL,
 401         .upload_pptable_settings = NULL,
 402         .is_dpm_running = vega12_is_dpm_running,
 403         .get_argument = smu9_get_argument,
 404         .smc_table_manager = vega12_smc_table_manager,
 405 };

/* [<][>][^][v][top][bottom][index][help] */