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

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

DEFINITIONS

This source file includes following definitions.
  1. smu10_wait_for_response
  2. smu10_send_msg_to_smc_without_waiting
  3. smu10_read_arg_from_smc
  4. smu10_send_msg_to_smc
  5. smu10_send_msg_to_smc_with_parameter
  6. smu10_copy_table_from_smc
  7. smu10_copy_table_to_smc
  8. smu10_verify_smc_interface
  9. smu10_smu_fini
  10. smu10_start_smu
  11. smu10_smu_init
  12. smu10_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 "smu10_inc.h"
  28 #include "soc15_common.h"
  29 #include "smu10_smumgr.h"
  30 #include "ppatomctrl.h"
  31 #include "rv_ppsmc.h"
  32 #include "smu10_driver_if.h"
  33 #include "smu10.h"
  34 #include "pp_debug.h"
  35 
  36 
  37 #define BUFFER_SIZE                 80000
  38 #define MAX_STRING_SIZE             15
  39 #define BUFFER_SIZETWO              131072
  40 
  41 #define MP0_Public                  0x03800000
  42 #define MP0_SRAM                    0x03900000
  43 #define MP1_Public                  0x03b00000
  44 #define MP1_SRAM                    0x03c00004
  45 
  46 #define smnMP1_FIRMWARE_FLAGS       0x3010028
  47 
  48 
  49 static uint32_t smu10_wait_for_response(struct pp_hwmgr *hwmgr)
  50 {
  51         struct amdgpu_device *adev = hwmgr->adev;
  52         uint32_t reg;
  53 
  54         reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_SMN_C2PMSG_90);
  55 
  56         phm_wait_for_register_unequal(hwmgr, reg,
  57                         0, MP1_C2PMSG_90__CONTENT_MASK);
  58 
  59         return RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90);
  60 }
  61 
  62 static int smu10_send_msg_to_smc_without_waiting(struct pp_hwmgr *hwmgr,
  63                 uint16_t msg)
  64 {
  65         struct amdgpu_device *adev = hwmgr->adev;
  66 
  67         WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_66, msg);
  68 
  69         return 0;
  70 }
  71 
  72 static uint32_t smu10_read_arg_from_smc(struct pp_hwmgr *hwmgr)
  73 {
  74         struct amdgpu_device *adev = hwmgr->adev;
  75 
  76         return RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_82);
  77 }
  78 
  79 static int smu10_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg)
  80 {
  81         struct amdgpu_device *adev = hwmgr->adev;
  82 
  83         smu10_wait_for_response(hwmgr);
  84 
  85         WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90, 0);
  86 
  87         smu10_send_msg_to_smc_without_waiting(hwmgr, msg);
  88 
  89         if (smu10_wait_for_response(hwmgr) == 0)
  90                 printk("Failed to send Message %x.\n", msg);
  91 
  92         return 0;
  93 }
  94 
  95 
  96 static int smu10_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr,
  97                 uint16_t msg, uint32_t parameter)
  98 {
  99         struct amdgpu_device *adev = hwmgr->adev;
 100 
 101         smu10_wait_for_response(hwmgr);
 102 
 103         WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90, 0);
 104 
 105         WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_82, parameter);
 106 
 107         smu10_send_msg_to_smc_without_waiting(hwmgr, msg);
 108 
 109 
 110         if (smu10_wait_for_response(hwmgr) == 0)
 111                 printk("Failed to send Message %x.\n", msg);
 112 
 113         return 0;
 114 }
 115 
 116 static int smu10_copy_table_from_smc(struct pp_hwmgr *hwmgr,
 117                 uint8_t *table, int16_t table_id)
 118 {
 119         struct smu10_smumgr *priv =
 120                         (struct smu10_smumgr *)(hwmgr->smu_backend);
 121         struct amdgpu_device *adev = hwmgr->adev;
 122 
 123         PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE,
 124                         "Invalid SMU Table ID!", return -EINVAL;);
 125         PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
 126                         "Invalid SMU Table version!", return -EINVAL;);
 127         PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
 128                         "Invalid SMU Table Length!", return -EINVAL;);
 129         smu10_send_msg_to_smc_with_parameter(hwmgr,
 130                         PPSMC_MSG_SetDriverDramAddrHigh,
 131                         upper_32_bits(priv->smu_tables.entry[table_id].mc_addr));
 132         smu10_send_msg_to_smc_with_parameter(hwmgr,
 133                         PPSMC_MSG_SetDriverDramAddrLow,
 134                         lower_32_bits(priv->smu_tables.entry[table_id].mc_addr));
 135         smu10_send_msg_to_smc_with_parameter(hwmgr,
 136                         PPSMC_MSG_TransferTableSmu2Dram,
 137                         priv->smu_tables.entry[table_id].table_id);
 138 
 139         /* flush hdp cache */
 140         adev->nbio_funcs->hdp_flush(adev, NULL);
 141 
 142         memcpy(table, (uint8_t *)priv->smu_tables.entry[table_id].table,
 143                         priv->smu_tables.entry[table_id].size);
 144 
 145         return 0;
 146 }
 147 
 148 static int smu10_copy_table_to_smc(struct pp_hwmgr *hwmgr,
 149                 uint8_t *table, int16_t table_id)
 150 {
 151         struct smu10_smumgr *priv =
 152                         (struct smu10_smumgr *)(hwmgr->smu_backend);
 153 
 154         PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE,
 155                         "Invalid SMU Table ID!", return -EINVAL;);
 156         PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
 157                         "Invalid SMU Table version!", return -EINVAL;);
 158         PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
 159                         "Invalid SMU Table Length!", return -EINVAL;);
 160 
 161         memcpy(priv->smu_tables.entry[table_id].table, table,
 162                         priv->smu_tables.entry[table_id].size);
 163 
 164         smu10_send_msg_to_smc_with_parameter(hwmgr,
 165                         PPSMC_MSG_SetDriverDramAddrHigh,
 166                         upper_32_bits(priv->smu_tables.entry[table_id].mc_addr));
 167         smu10_send_msg_to_smc_with_parameter(hwmgr,
 168                         PPSMC_MSG_SetDriverDramAddrLow,
 169                         lower_32_bits(priv->smu_tables.entry[table_id].mc_addr));
 170         smu10_send_msg_to_smc_with_parameter(hwmgr,
 171                         PPSMC_MSG_TransferTableDram2Smu,
 172                         priv->smu_tables.entry[table_id].table_id);
 173 
 174         return 0;
 175 }
 176 
 177 static int smu10_verify_smc_interface(struct pp_hwmgr *hwmgr)
 178 {
 179         uint32_t smc_driver_if_version;
 180 
 181         smu10_send_msg_to_smc(hwmgr,
 182                         PPSMC_MSG_GetDriverIfVersion);
 183         smc_driver_if_version = smu10_read_arg_from_smc(hwmgr);
 184 
 185         if ((smc_driver_if_version != SMU10_DRIVER_IF_VERSION) &&
 186             (smc_driver_if_version != SMU10_DRIVER_IF_VERSION + 1)) {
 187                 pr_err("Attempt to read SMC IF Version Number Failed!\n");
 188                 return -EINVAL;
 189         }
 190 
 191         return 0;
 192 }
 193 
 194 static int smu10_smu_fini(struct pp_hwmgr *hwmgr)
 195 {
 196         struct smu10_smumgr *priv =
 197                         (struct smu10_smumgr *)(hwmgr->smu_backend);
 198 
 199         if (priv) {
 200                 amdgpu_bo_free_kernel(&priv->smu_tables.entry[SMU10_WMTABLE].handle,
 201                                         &priv->smu_tables.entry[SMU10_WMTABLE].mc_addr,
 202                                         &priv->smu_tables.entry[SMU10_WMTABLE].table);
 203                 amdgpu_bo_free_kernel(&priv->smu_tables.entry[SMU10_CLOCKTABLE].handle,
 204                                         &priv->smu_tables.entry[SMU10_CLOCKTABLE].mc_addr,
 205                                         &priv->smu_tables.entry[SMU10_CLOCKTABLE].table);
 206                 kfree(hwmgr->smu_backend);
 207                 hwmgr->smu_backend = NULL;
 208         }
 209 
 210         return 0;
 211 }
 212 
 213 static int smu10_start_smu(struct pp_hwmgr *hwmgr)
 214 {
 215         struct amdgpu_device *adev = hwmgr->adev;
 216 
 217         smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetSmuVersion);
 218         hwmgr->smu_version = smu10_read_arg_from_smc(hwmgr);
 219         adev->pm.fw_version = hwmgr->smu_version >> 8;
 220 
 221         if (adev->rev_id < 0x8 && adev->pdev->device != 0x15d8 &&
 222             adev->pm.fw_version < 0x1e45)
 223                 adev->pm.pp_feature &= ~PP_GFXOFF_MASK;
 224 
 225         if (smu10_verify_smc_interface(hwmgr))
 226                 return -EINVAL;
 227 
 228         return 0;
 229 }
 230 
 231 static int smu10_smu_init(struct pp_hwmgr *hwmgr)
 232 {
 233         struct smu10_smumgr *priv;
 234         int r;
 235 
 236         priv = kzalloc(sizeof(struct smu10_smumgr), GFP_KERNEL);
 237 
 238         if (!priv)
 239                 return -ENOMEM;
 240 
 241         hwmgr->smu_backend = priv;
 242 
 243         /* allocate space for watermarks table */
 244         r = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
 245                         sizeof(Watermarks_t),
 246                         PAGE_SIZE,
 247                         AMDGPU_GEM_DOMAIN_VRAM,
 248                         &priv->smu_tables.entry[SMU10_WMTABLE].handle,
 249                         &priv->smu_tables.entry[SMU10_WMTABLE].mc_addr,
 250                         &priv->smu_tables.entry[SMU10_WMTABLE].table);
 251 
 252         if (r)
 253                 goto err0;
 254 
 255         priv->smu_tables.entry[SMU10_WMTABLE].version = 0x01;
 256         priv->smu_tables.entry[SMU10_WMTABLE].size = sizeof(Watermarks_t);
 257         priv->smu_tables.entry[SMU10_WMTABLE].table_id = TABLE_WATERMARKS;
 258 
 259         /* allocate space for watermarks table */
 260         r = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
 261                         sizeof(DpmClocks_t),
 262                         PAGE_SIZE,
 263                         AMDGPU_GEM_DOMAIN_VRAM,
 264                         &priv->smu_tables.entry[SMU10_CLOCKTABLE].handle,
 265                         &priv->smu_tables.entry[SMU10_CLOCKTABLE].mc_addr,
 266                         &priv->smu_tables.entry[SMU10_CLOCKTABLE].table);
 267 
 268         if (r)
 269                 goto err1;
 270 
 271         priv->smu_tables.entry[SMU10_CLOCKTABLE].version = 0x01;
 272         priv->smu_tables.entry[SMU10_CLOCKTABLE].size = sizeof(DpmClocks_t);
 273         priv->smu_tables.entry[SMU10_CLOCKTABLE].table_id = TABLE_DPMCLOCKS;
 274 
 275         return 0;
 276 
 277 err1:
 278         amdgpu_bo_free_kernel(&priv->smu_tables.entry[SMU10_WMTABLE].handle,
 279                                 &priv->smu_tables.entry[SMU10_WMTABLE].mc_addr,
 280                                 &priv->smu_tables.entry[SMU10_WMTABLE].table);
 281 err0:
 282         kfree(priv);
 283         return -EINVAL;
 284 }
 285 
 286 static int smu10_smc_table_manager(struct pp_hwmgr *hwmgr, uint8_t *table, uint16_t table_id, bool rw)
 287 {
 288         int ret;
 289 
 290         if (rw)
 291                 ret = smu10_copy_table_from_smc(hwmgr, table, table_id);
 292         else
 293                 ret = smu10_copy_table_to_smc(hwmgr, table, table_id);
 294 
 295         return ret;
 296 }
 297 
 298 
 299 const struct pp_smumgr_func smu10_smu_funcs = {
 300         .name = "smu10_smu",
 301         .smu_init = &smu10_smu_init,
 302         .smu_fini = &smu10_smu_fini,
 303         .start_smu = &smu10_start_smu,
 304         .request_smu_load_specific_fw = NULL,
 305         .send_msg_to_smc = &smu10_send_msg_to_smc,
 306         .send_msg_to_smc_with_parameter = &smu10_send_msg_to_smc_with_parameter,
 307         .download_pptable_settings = NULL,
 308         .upload_pptable_settings = NULL,
 309         .get_argument = smu10_read_arg_from_smc,
 310         .smc_table_manager = smu10_smc_table_manager,
 311 };
 312 
 313 

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