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

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

DEFINITIONS

This source file includes following definitions.
  1. vega10_copy_table_from_smc
  2. vega10_copy_table_to_smc
  3. vega10_enable_smc_features
  4. vega10_get_enabled_smc_features
  5. vega10_is_dpm_running
  6. vega10_set_tools_address
  7. vega10_verify_smc_interface
  8. vega10_smu_init
  9. vega10_smu_fini
  10. vega10_start_smu
  11. vega10_smc_table_manager

   1 /*
   2  * Copyright 2016 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 <linux/pci.h>
  25 
  26 #include "smumgr.h"
  27 #include "vega10_inc.h"
  28 #include "soc15_common.h"
  29 #include "vega10_smumgr.h"
  30 #include "vega10_hwmgr.h"
  31 #include "vega10_ppsmc.h"
  32 #include "smu9_driver_if.h"
  33 #include "smu9_smumgr.h"
  34 #include "ppatomctrl.h"
  35 #include "pp_debug.h"
  36 
  37 
  38 static int vega10_copy_table_from_smc(struct pp_hwmgr *hwmgr,
  39                 uint8_t *table, int16_t table_id)
  40 {
  41         struct vega10_smumgr *priv = hwmgr->smu_backend;
  42         struct amdgpu_device *adev = hwmgr->adev;
  43 
  44         PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE,
  45                         "Invalid SMU Table ID!", return -EINVAL);
  46         PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
  47                         "Invalid SMU Table version!", return -EINVAL);
  48         PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
  49                         "Invalid SMU Table Length!", return -EINVAL);
  50         smu9_send_msg_to_smc_with_parameter(hwmgr,
  51                         PPSMC_MSG_SetDriverDramAddrHigh,
  52                         upper_32_bits(priv->smu_tables.entry[table_id].mc_addr));
  53         smu9_send_msg_to_smc_with_parameter(hwmgr,
  54                         PPSMC_MSG_SetDriverDramAddrLow,
  55                         lower_32_bits(priv->smu_tables.entry[table_id].mc_addr));
  56         smu9_send_msg_to_smc_with_parameter(hwmgr,
  57                         PPSMC_MSG_TransferTableSmu2Dram,
  58                         priv->smu_tables.entry[table_id].table_id);
  59 
  60         /* flush hdp cache */
  61         adev->nbio_funcs->hdp_flush(adev, NULL);
  62 
  63         memcpy(table, priv->smu_tables.entry[table_id].table,
  64                         priv->smu_tables.entry[table_id].size);
  65 
  66         return 0;
  67 }
  68 
  69 static int vega10_copy_table_to_smc(struct pp_hwmgr *hwmgr,
  70                 uint8_t *table, int16_t table_id)
  71 {
  72         struct vega10_smumgr *priv = hwmgr->smu_backend;
  73 
  74         PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE,
  75                         "Invalid SMU Table ID!", return -EINVAL);
  76         PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
  77                         "Invalid SMU Table version!", return -EINVAL);
  78         PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
  79                         "Invalid SMU Table Length!", return -EINVAL);
  80 
  81         memcpy(priv->smu_tables.entry[table_id].table, table,
  82                         priv->smu_tables.entry[table_id].size);
  83 
  84         smu9_send_msg_to_smc_with_parameter(hwmgr,
  85                         PPSMC_MSG_SetDriverDramAddrHigh,
  86                         upper_32_bits(priv->smu_tables.entry[table_id].mc_addr));
  87         smu9_send_msg_to_smc_with_parameter(hwmgr,
  88                         PPSMC_MSG_SetDriverDramAddrLow,
  89                         lower_32_bits(priv->smu_tables.entry[table_id].mc_addr));
  90         smu9_send_msg_to_smc_with_parameter(hwmgr,
  91                         PPSMC_MSG_TransferTableDram2Smu,
  92                         priv->smu_tables.entry[table_id].table_id);
  93 
  94         return 0;
  95 }
  96 
  97 int vega10_enable_smc_features(struct pp_hwmgr *hwmgr,
  98                                bool enable, uint32_t feature_mask)
  99 {
 100         int msg = enable ? PPSMC_MSG_EnableSmuFeatures :
 101                         PPSMC_MSG_DisableSmuFeatures;
 102 
 103         return smum_send_msg_to_smc_with_parameter(hwmgr,
 104                         msg, feature_mask);
 105 }
 106 
 107 int vega10_get_enabled_smc_features(struct pp_hwmgr *hwmgr,
 108                             uint64_t *features_enabled)
 109 {
 110         if (features_enabled == NULL)
 111                 return -EINVAL;
 112 
 113         smu9_send_msg_to_smc(hwmgr, PPSMC_MSG_GetEnabledSmuFeatures);
 114         *features_enabled = smu9_get_argument(hwmgr);
 115 
 116         return 0;
 117 }
 118 
 119 static bool vega10_is_dpm_running(struct pp_hwmgr *hwmgr)
 120 {
 121         uint64_t features_enabled = 0;
 122 
 123         vega10_get_enabled_smc_features(hwmgr, &features_enabled);
 124 
 125         if (features_enabled & SMC_DPM_FEATURES)
 126                 return true;
 127         else
 128                 return false;
 129 }
 130 
 131 static int vega10_set_tools_address(struct pp_hwmgr *hwmgr)
 132 {
 133         struct vega10_smumgr *priv = hwmgr->smu_backend;
 134 
 135         if (priv->smu_tables.entry[TOOLSTABLE].mc_addr) {
 136                 smu9_send_msg_to_smc_with_parameter(hwmgr,
 137                                 PPSMC_MSG_SetToolsDramAddrHigh,
 138                                 upper_32_bits(priv->smu_tables.entry[TOOLSTABLE].mc_addr));
 139                 smu9_send_msg_to_smc_with_parameter(hwmgr,
 140                                 PPSMC_MSG_SetToolsDramAddrLow,
 141                                 lower_32_bits(priv->smu_tables.entry[TOOLSTABLE].mc_addr));
 142         }
 143         return 0;
 144 }
 145 
 146 static int vega10_verify_smc_interface(struct pp_hwmgr *hwmgr)
 147 {
 148         uint32_t smc_driver_if_version;
 149         struct amdgpu_device *adev = hwmgr->adev;
 150         uint32_t dev_id;
 151         uint32_t rev_id;
 152 
 153         PP_ASSERT_WITH_CODE(!smu9_send_msg_to_smc(hwmgr,
 154                         PPSMC_MSG_GetDriverIfVersion),
 155                         "Attempt to get SMC IF Version Number Failed!",
 156                         return -EINVAL);
 157         smc_driver_if_version = smu9_get_argument(hwmgr);
 158 
 159         dev_id = adev->pdev->device;
 160         rev_id = adev->pdev->revision;
 161 
 162         if (!((dev_id == 0x687f) &&
 163                 ((rev_id == 0xc0) ||
 164                 (rev_id == 0xc1) ||
 165                 (rev_id == 0xc3)))) {
 166                 if (smc_driver_if_version != SMU9_DRIVER_IF_VERSION) {
 167                         pr_err("Your firmware(0x%x) doesn't match SMU9_DRIVER_IF_VERSION(0x%x). Please update your firmware!\n",
 168                                smc_driver_if_version, SMU9_DRIVER_IF_VERSION);
 169                         return -EINVAL;
 170                 }
 171         }
 172 
 173         return 0;
 174 }
 175 
 176 static int vega10_smu_init(struct pp_hwmgr *hwmgr)
 177 {
 178         struct vega10_smumgr *priv;
 179         unsigned long tools_size;
 180         int ret;
 181         struct cgs_firmware_info info = {0};
 182 
 183         ret = cgs_get_firmware_info(hwmgr->device,
 184                                     CGS_UCODE_ID_SMU,
 185                                     &info);
 186         if (ret || !info.kptr)
 187                 return -EINVAL;
 188 
 189         priv = kzalloc(sizeof(struct vega10_smumgr), GFP_KERNEL);
 190 
 191         if (!priv)
 192                 return -ENOMEM;
 193 
 194         hwmgr->smu_backend = priv;
 195 
 196         /* allocate space for pptable */
 197         ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
 198                         sizeof(PPTable_t),
 199                         PAGE_SIZE,
 200                         AMDGPU_GEM_DOMAIN_VRAM,
 201                         &priv->smu_tables.entry[PPTABLE].handle,
 202                         &priv->smu_tables.entry[PPTABLE].mc_addr,
 203                         &priv->smu_tables.entry[PPTABLE].table);
 204         if (ret)
 205                 goto free_backend;
 206 
 207         priv->smu_tables.entry[PPTABLE].version = 0x01;
 208         priv->smu_tables.entry[PPTABLE].size = sizeof(PPTable_t);
 209         priv->smu_tables.entry[PPTABLE].table_id = TABLE_PPTABLE;
 210 
 211         /* allocate space for watermarks table */
 212         ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
 213                         sizeof(Watermarks_t),
 214                         PAGE_SIZE,
 215                         AMDGPU_GEM_DOMAIN_VRAM,
 216                         &priv->smu_tables.entry[WMTABLE].handle,
 217                         &priv->smu_tables.entry[WMTABLE].mc_addr,
 218                         &priv->smu_tables.entry[WMTABLE].table);
 219 
 220         if (ret)
 221                 goto err0;
 222 
 223         priv->smu_tables.entry[WMTABLE].version = 0x01;
 224         priv->smu_tables.entry[WMTABLE].size = sizeof(Watermarks_t);
 225         priv->smu_tables.entry[WMTABLE].table_id = TABLE_WATERMARKS;
 226 
 227         /* allocate space for AVFS table */
 228         ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
 229                         sizeof(AvfsTable_t),
 230                         PAGE_SIZE,
 231                         AMDGPU_GEM_DOMAIN_VRAM,
 232                         &priv->smu_tables.entry[AVFSTABLE].handle,
 233                         &priv->smu_tables.entry[AVFSTABLE].mc_addr,
 234                         &priv->smu_tables.entry[AVFSTABLE].table);
 235 
 236         if (ret)
 237                 goto err1;
 238 
 239         priv->smu_tables.entry[AVFSTABLE].version = 0x01;
 240         priv->smu_tables.entry[AVFSTABLE].size = sizeof(AvfsTable_t);
 241         priv->smu_tables.entry[AVFSTABLE].table_id = TABLE_AVFS;
 242 
 243         tools_size = 0x19000;
 244         if (tools_size) {
 245                 ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
 246                                 tools_size,
 247                                 PAGE_SIZE,
 248                                 AMDGPU_GEM_DOMAIN_VRAM,
 249                                 &priv->smu_tables.entry[TOOLSTABLE].handle,
 250                                 &priv->smu_tables.entry[TOOLSTABLE].mc_addr,
 251                                 &priv->smu_tables.entry[TOOLSTABLE].table);
 252                 if (ret)
 253                         goto err2;
 254                 priv->smu_tables.entry[TOOLSTABLE].version = 0x01;
 255                 priv->smu_tables.entry[TOOLSTABLE].size = tools_size;
 256                 priv->smu_tables.entry[TOOLSTABLE].table_id = TABLE_PMSTATUSLOG;
 257         }
 258 
 259         /* allocate space for AVFS Fuse table */
 260         ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
 261                         sizeof(AvfsFuseOverride_t),
 262                         PAGE_SIZE,
 263                         AMDGPU_GEM_DOMAIN_VRAM,
 264                         &priv->smu_tables.entry[AVFSFUSETABLE].handle,
 265                         &priv->smu_tables.entry[AVFSFUSETABLE].mc_addr,
 266                         &priv->smu_tables.entry[AVFSFUSETABLE].table);
 267         if (ret)
 268                 goto err3;
 269 
 270         priv->smu_tables.entry[AVFSFUSETABLE].version = 0x01;
 271         priv->smu_tables.entry[AVFSFUSETABLE].size = sizeof(AvfsFuseOverride_t);
 272         priv->smu_tables.entry[AVFSFUSETABLE].table_id = TABLE_AVFS_FUSE_OVERRIDE;
 273 
 274 
 275         return 0;
 276 
 277 err3:
 278         if (priv->smu_tables.entry[TOOLSTABLE].table)
 279                 amdgpu_bo_free_kernel(&priv->smu_tables.entry[TOOLSTABLE].handle,
 280                                 &priv->smu_tables.entry[TOOLSTABLE].mc_addr,
 281                                 &priv->smu_tables.entry[TOOLSTABLE].table);
 282 err2:
 283         amdgpu_bo_free_kernel(&priv->smu_tables.entry[AVFSTABLE].handle,
 284                                 &priv->smu_tables.entry[AVFSTABLE].mc_addr,
 285                                 &priv->smu_tables.entry[AVFSTABLE].table);
 286 err1:
 287         amdgpu_bo_free_kernel(&priv->smu_tables.entry[WMTABLE].handle,
 288                                 &priv->smu_tables.entry[WMTABLE].mc_addr,
 289                                 &priv->smu_tables.entry[WMTABLE].table);
 290 err0:
 291         amdgpu_bo_free_kernel(&priv->smu_tables.entry[PPTABLE].handle,
 292                         &priv->smu_tables.entry[PPTABLE].mc_addr,
 293                         &priv->smu_tables.entry[PPTABLE].table);
 294 free_backend:
 295         kfree(hwmgr->smu_backend);
 296 
 297         return -EINVAL;
 298 }
 299 
 300 static int vega10_smu_fini(struct pp_hwmgr *hwmgr)
 301 {
 302         struct vega10_smumgr *priv = hwmgr->smu_backend;
 303 
 304         if (priv) {
 305                 amdgpu_bo_free_kernel(&priv->smu_tables.entry[PPTABLE].handle,
 306                                 &priv->smu_tables.entry[PPTABLE].mc_addr,
 307                                 &priv->smu_tables.entry[PPTABLE].table);
 308                 amdgpu_bo_free_kernel(&priv->smu_tables.entry[WMTABLE].handle,
 309                                         &priv->smu_tables.entry[WMTABLE].mc_addr,
 310                                         &priv->smu_tables.entry[WMTABLE].table);
 311                 amdgpu_bo_free_kernel(&priv->smu_tables.entry[AVFSTABLE].handle,
 312                                         &priv->smu_tables.entry[AVFSTABLE].mc_addr,
 313                                         &priv->smu_tables.entry[AVFSTABLE].table);
 314                 if (priv->smu_tables.entry[TOOLSTABLE].table)
 315                         amdgpu_bo_free_kernel(&priv->smu_tables.entry[TOOLSTABLE].handle,
 316                                         &priv->smu_tables.entry[TOOLSTABLE].mc_addr,
 317                                         &priv->smu_tables.entry[TOOLSTABLE].table);
 318                 amdgpu_bo_free_kernel(&priv->smu_tables.entry[AVFSFUSETABLE].handle,
 319                                         &priv->smu_tables.entry[AVFSFUSETABLE].mc_addr,
 320                                         &priv->smu_tables.entry[AVFSFUSETABLE].table);
 321                 kfree(hwmgr->smu_backend);
 322                 hwmgr->smu_backend = NULL;
 323         }
 324         return 0;
 325 }
 326 
 327 static int vega10_start_smu(struct pp_hwmgr *hwmgr)
 328 {
 329         if (!smu9_is_smc_ram_running(hwmgr))
 330                 return -EINVAL;
 331 
 332         PP_ASSERT_WITH_CODE(!vega10_verify_smc_interface(hwmgr),
 333                         "Failed to verify SMC interface!",
 334                         return -EINVAL);
 335 
 336         vega10_set_tools_address(hwmgr);
 337 
 338         return 0;
 339 }
 340 
 341 static int vega10_smc_table_manager(struct pp_hwmgr *hwmgr, uint8_t *table,
 342                                     uint16_t table_id, bool rw)
 343 {
 344         int ret;
 345 
 346         if (rw)
 347                 ret = vega10_copy_table_from_smc(hwmgr, table, table_id);
 348         else
 349                 ret = vega10_copy_table_to_smc(hwmgr, table, table_id);
 350 
 351         return ret;
 352 }
 353 
 354 const struct pp_smumgr_func vega10_smu_funcs = {
 355         .name = "vega10_smu",
 356         .smu_init = &vega10_smu_init,
 357         .smu_fini = &vega10_smu_fini,
 358         .start_smu = &vega10_start_smu,
 359         .request_smu_load_specific_fw = NULL,
 360         .send_msg_to_smc = &smu9_send_msg_to_smc,
 361         .send_msg_to_smc_with_parameter = &smu9_send_msg_to_smc_with_parameter,
 362         .download_pptable_settings = NULL,
 363         .upload_pptable_settings = NULL,
 364         .is_dpm_running = vega10_is_dpm_running,
 365         .get_argument = smu9_get_argument,
 366         .smc_table_manager = vega10_smc_table_manager,
 367 };

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