root/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c

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

DEFINITIONS

This source file includes following definitions.
  1. mes_v10_1_add_hw_queue
  2. mes_v10_1_remove_hw_queue
  3. mes_v10_1_suspend_gang
  4. mes_v10_1_resume_gang
  5. mes_v10_1_init_microcode
  6. mes_v10_1_free_microcode
  7. mes_v10_1_allocate_ucode_buffer
  8. mes_v10_1_allocate_ucode_data_buffer
  9. mes_v10_1_free_ucode_buffers
  10. mes_v10_1_enable
  11. mes_v10_1_load_microcode
  12. mes_v10_1_sw_init
  13. mes_v10_1_sw_fini
  14. mes_v10_1_hw_init
  15. mes_v10_1_hw_fini
  16. mes_v10_1_suspend
  17. mes_v10_1_resume

   1 /*
   2  * Copyright 2019 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/firmware.h>
  25 #include <linux/module.h>
  26 #include "amdgpu.h"
  27 #include "soc15_common.h"
  28 #include "nv.h"
  29 #include "gc/gc_10_1_0_offset.h"
  30 #include "gc/gc_10_1_0_sh_mask.h"
  31 
  32 MODULE_FIRMWARE("amdgpu/navi10_mes.bin");
  33 
  34 static int mes_v10_1_add_hw_queue(struct amdgpu_mes *mes,
  35                                   struct mes_add_queue_input *input)
  36 {
  37         return 0;
  38 }
  39 
  40 static int mes_v10_1_remove_hw_queue(struct amdgpu_mes *mes,
  41                                      struct mes_remove_queue_input *input)
  42 {
  43         return 0;
  44 }
  45 
  46 static int mes_v10_1_suspend_gang(struct amdgpu_mes *mes,
  47                                   struct mes_suspend_gang_input *input)
  48 {
  49         return 0;
  50 }
  51 
  52 static int mes_v10_1_resume_gang(struct amdgpu_mes *mes,
  53                                  struct mes_resume_gang_input *input)
  54 {
  55         return 0;
  56 }
  57 
  58 static const struct amdgpu_mes_funcs mes_v10_1_funcs = {
  59         .add_hw_queue = mes_v10_1_add_hw_queue,
  60         .remove_hw_queue = mes_v10_1_remove_hw_queue,
  61         .suspend_gang = mes_v10_1_suspend_gang,
  62         .resume_gang = mes_v10_1_resume_gang,
  63 };
  64 
  65 static int mes_v10_1_init_microcode(struct amdgpu_device *adev)
  66 {
  67         const char *chip_name;
  68         char fw_name[30];
  69         int err;
  70         const struct mes_firmware_header_v1_0 *mes_hdr;
  71 
  72         switch (adev->asic_type) {
  73         case CHIP_NAVI10:
  74                 chip_name = "navi10";
  75                 break;
  76         default:
  77                 BUG();
  78         }
  79 
  80         snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mes.bin", chip_name);
  81         err = request_firmware(&adev->mes.fw, fw_name, adev->dev);
  82         if (err)
  83                 return err;
  84 
  85         err = amdgpu_ucode_validate(adev->mes.fw);
  86         if (err) {
  87                 release_firmware(adev->mes.fw);
  88                 adev->mes.fw = NULL;
  89                 return err;
  90         }
  91 
  92         mes_hdr = (const struct mes_firmware_header_v1_0 *)adev->mes.fw->data;
  93         adev->mes.ucode_fw_version = le32_to_cpu(mes_hdr->mes_ucode_version);
  94         adev->mes.ucode_fw_version =
  95                 le32_to_cpu(mes_hdr->mes_ucode_data_version);
  96         adev->mes.uc_start_addr =
  97                 le32_to_cpu(mes_hdr->mes_uc_start_addr_lo) |
  98                 ((uint64_t)(le32_to_cpu(mes_hdr->mes_uc_start_addr_hi)) << 32);
  99         adev->mes.data_start_addr =
 100                 le32_to_cpu(mes_hdr->mes_data_start_addr_lo) |
 101                 ((uint64_t)(le32_to_cpu(mes_hdr->mes_data_start_addr_hi)) << 32);
 102 
 103         return 0;
 104 }
 105 
 106 static void mes_v10_1_free_microcode(struct amdgpu_device *adev)
 107 {
 108         release_firmware(adev->mes.fw);
 109         adev->mes.fw = NULL;
 110 }
 111 
 112 static int mes_v10_1_allocate_ucode_buffer(struct amdgpu_device *adev)
 113 {
 114         int r;
 115         const struct mes_firmware_header_v1_0 *mes_hdr;
 116         const __le32 *fw_data;
 117         unsigned fw_size;
 118 
 119         mes_hdr = (const struct mes_firmware_header_v1_0 *)
 120                 adev->mes.fw->data;
 121 
 122         fw_data = (const __le32 *)(adev->mes.fw->data +
 123                    le32_to_cpu(mes_hdr->mes_ucode_offset_bytes));
 124         fw_size = le32_to_cpu(mes_hdr->mes_ucode_size_bytes);
 125 
 126         r = amdgpu_bo_create_reserved(adev, fw_size,
 127                                       PAGE_SIZE, AMDGPU_GEM_DOMAIN_GTT,
 128                                       &adev->mes.ucode_fw_obj,
 129                                       &adev->mes.ucode_fw_gpu_addr,
 130                                       (void **)&adev->mes.ucode_fw_ptr);
 131         if (r) {
 132                 dev_err(adev->dev, "(%d) failed to create mes fw bo\n", r);
 133                 return r;
 134         }
 135 
 136         memcpy(adev->mes.ucode_fw_ptr, fw_data, fw_size);
 137 
 138         amdgpu_bo_kunmap(adev->mes.ucode_fw_obj);
 139         amdgpu_bo_unreserve(adev->mes.ucode_fw_obj);
 140 
 141         return 0;
 142 }
 143 
 144 static int mes_v10_1_allocate_ucode_data_buffer(struct amdgpu_device *adev)
 145 {
 146         int r;
 147         const struct mes_firmware_header_v1_0 *mes_hdr;
 148         const __le32 *fw_data;
 149         unsigned fw_size;
 150 
 151         mes_hdr = (const struct mes_firmware_header_v1_0 *)
 152                 adev->mes.fw->data;
 153 
 154         fw_data = (const __le32 *)(adev->mes.fw->data +
 155                    le32_to_cpu(mes_hdr->mes_ucode_data_offset_bytes));
 156         fw_size = le32_to_cpu(mes_hdr->mes_ucode_data_size_bytes);
 157 
 158         r = amdgpu_bo_create_reserved(adev, fw_size,
 159                                       64 * 1024, AMDGPU_GEM_DOMAIN_GTT,
 160                                       &adev->mes.data_fw_obj,
 161                                       &adev->mes.data_fw_gpu_addr,
 162                                       (void **)&adev->mes.data_fw_ptr);
 163         if (r) {
 164                 dev_err(adev->dev, "(%d) failed to create mes data fw bo\n", r);
 165                 return r;
 166         }
 167 
 168         memcpy(adev->mes.data_fw_ptr, fw_data, fw_size);
 169 
 170         amdgpu_bo_kunmap(adev->mes.data_fw_obj);
 171         amdgpu_bo_unreserve(adev->mes.data_fw_obj);
 172 
 173         return 0;
 174 }
 175 
 176 static void mes_v10_1_free_ucode_buffers(struct amdgpu_device *adev)
 177 {
 178         amdgpu_bo_free_kernel(&adev->mes.data_fw_obj,
 179                               &adev->mes.data_fw_gpu_addr,
 180                               (void **)&adev->mes.data_fw_ptr);
 181 
 182         amdgpu_bo_free_kernel(&adev->mes.ucode_fw_obj,
 183                               &adev->mes.ucode_fw_gpu_addr,
 184                               (void **)&adev->mes.ucode_fw_ptr);
 185 }
 186 
 187 static void mes_v10_1_enable(struct amdgpu_device *adev, bool enable)
 188 {
 189         uint32_t data = 0;
 190 
 191         if (enable) {
 192                 data = RREG32_SOC15(GC, 0, mmCP_MES_CNTL);
 193                 data = REG_SET_FIELD(data, CP_MES_CNTL, MES_PIPE0_RESET, 1);
 194                 WREG32_SOC15(GC, 0, mmCP_MES_CNTL, data);
 195 
 196                 /* set ucode start address */
 197                 WREG32_SOC15(GC, 0, mmCP_MES_PRGRM_CNTR_START,
 198                              (uint32_t)(adev->mes.uc_start_addr) >> 2);
 199 
 200                 /* clear BYPASS_UNCACHED to avoid hangs after interrupt. */
 201                 data = RREG32_SOC15(GC, 0, mmCP_MES_DC_OP_CNTL);
 202                 data = REG_SET_FIELD(data, CP_MES_DC_OP_CNTL,
 203                                      BYPASS_UNCACHED, 0);
 204                 WREG32_SOC15(GC, 0, mmCP_MES_DC_OP_CNTL, data);
 205 
 206                 /* unhalt MES and activate pipe0 */
 207                 data = REG_SET_FIELD(0, CP_MES_CNTL, MES_PIPE0_ACTIVE, 1);
 208                 WREG32_SOC15(GC, 0, mmCP_MES_CNTL, data);
 209         } else {
 210                 data = RREG32_SOC15(GC, 0, mmCP_MES_CNTL);
 211                 data = REG_SET_FIELD(data, CP_MES_CNTL, MES_PIPE0_ACTIVE, 0);
 212                 data = REG_SET_FIELD(data, CP_MES_CNTL,
 213                                      MES_INVALIDATE_ICACHE, 1);
 214                 data = REG_SET_FIELD(data, CP_MES_CNTL, MES_PIPE0_RESET, 1);
 215                 data = REG_SET_FIELD(data, CP_MES_CNTL, MES_HALT, 1);
 216                 WREG32_SOC15(GC, 0, mmCP_MES_CNTL, data);
 217         }
 218 }
 219 
 220 /* This function is for backdoor MES firmware */
 221 static int mes_v10_1_load_microcode(struct amdgpu_device *adev)
 222 {
 223         int r;
 224         uint32_t data;
 225 
 226         if (!adev->mes.fw)
 227                 return -EINVAL;
 228 
 229         r = mes_v10_1_allocate_ucode_buffer(adev);
 230         if (r)
 231                 return r;
 232 
 233         r = mes_v10_1_allocate_ucode_data_buffer(adev);
 234         if (r) {
 235                 mes_v10_1_free_ucode_buffers(adev);
 236                 return r;
 237         }
 238 
 239         mes_v10_1_enable(adev, false);
 240 
 241         WREG32_SOC15(GC, 0, mmCP_MES_IC_BASE_CNTL, 0);
 242 
 243         mutex_lock(&adev->srbm_mutex);
 244         /* me=3, pipe=0, queue=0 */
 245         nv_grbm_select(adev, 3, 0, 0, 0);
 246 
 247         /* set ucode start address */
 248         WREG32_SOC15(GC, 0, mmCP_MES_PRGRM_CNTR_START,
 249                      (uint32_t)(adev->mes.uc_start_addr) >> 2);
 250 
 251         /* set ucode fimrware address */
 252         WREG32_SOC15(GC, 0, mmCP_MES_IC_BASE_LO,
 253                      lower_32_bits(adev->mes.ucode_fw_gpu_addr));
 254         WREG32_SOC15(GC, 0, mmCP_MES_IC_BASE_HI,
 255                      upper_32_bits(adev->mes.ucode_fw_gpu_addr));
 256 
 257         /* set ucode instruction cache boundary to 2M-1 */
 258         WREG32_SOC15(GC, 0, mmCP_MES_MIBOUND_LO, 0x1FFFFF);
 259 
 260         /* set ucode data firmware address */
 261         WREG32_SOC15(GC, 0, mmCP_MES_MDBASE_LO,
 262                      lower_32_bits(adev->mes.data_fw_gpu_addr));
 263         WREG32_SOC15(GC, 0, mmCP_MES_MDBASE_HI,
 264                      upper_32_bits(adev->mes.data_fw_gpu_addr));
 265 
 266         /* Set 0x3FFFF (256K-1) to CP_MES_MDBOUND_LO */
 267         WREG32_SOC15(GC, 0, mmCP_MES_MDBOUND_LO, 0x3FFFF);
 268 
 269         /* invalidate ICACHE */
 270         data = RREG32_SOC15(GC, 0, mmCP_MES_IC_OP_CNTL);
 271         data = REG_SET_FIELD(data, CP_MES_IC_OP_CNTL, PRIME_ICACHE, 0);
 272         data = REG_SET_FIELD(data, CP_MES_IC_OP_CNTL, INVALIDATE_CACHE, 1);
 273         WREG32_SOC15(GC, 0, mmCP_MES_IC_OP_CNTL, data);
 274 
 275         /* prime the ICACHE. */
 276         data = RREG32_SOC15(GC, 0, mmCP_MES_IC_OP_CNTL);
 277         data = REG_SET_FIELD(data, CP_MES_IC_OP_CNTL, PRIME_ICACHE, 1);
 278         WREG32_SOC15(GC, 0, mmCP_MES_IC_OP_CNTL, data);
 279 
 280         nv_grbm_select(adev, 0, 0, 0, 0);
 281         mutex_unlock(&adev->srbm_mutex);
 282 
 283         return 0;
 284 }
 285 
 286 static int mes_v10_1_sw_init(void *handle)
 287 {
 288         int r;
 289         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 290 
 291         r = mes_v10_1_init_microcode(adev);
 292         if (r)
 293                 return r;
 294 
 295         return 0;
 296 }
 297 
 298 static int mes_v10_1_sw_fini(void *handle)
 299 {
 300         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 301 
 302         mes_v10_1_free_microcode(adev);
 303 
 304         return 0;
 305 }
 306 
 307 static int mes_v10_1_hw_init(void *handle)
 308 {
 309         int r;
 310         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 311 
 312         if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT) {
 313                 r = mes_v10_1_load_microcode(adev);
 314                 if (r) {
 315                         DRM_ERROR("failed to MES fw, r=%d\n", r);
 316                         return r;
 317                 }
 318         } else {
 319                 DRM_ERROR("only support direct fw loading on MES\n");
 320                 return -EINVAL;
 321         }
 322 
 323         mes_v10_1_enable(adev, true);
 324 
 325         return 0;
 326 }
 327 
 328 static int mes_v10_1_hw_fini(void *handle)
 329 {
 330         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 331 
 332         mes_v10_1_enable(adev, false);
 333 
 334         if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT)
 335                 mes_v10_1_free_ucode_buffers(adev);
 336 
 337         return 0;
 338 }
 339 
 340 static int mes_v10_1_suspend(void *handle)
 341 {
 342         return 0;
 343 }
 344 
 345 static int mes_v10_1_resume(void *handle)
 346 {
 347         return 0;
 348 }
 349 
 350 static const struct amd_ip_funcs mes_v10_1_ip_funcs = {
 351         .name = "mes_v10_1",
 352         .sw_init = mes_v10_1_sw_init,
 353         .sw_fini = mes_v10_1_sw_fini,
 354         .hw_init = mes_v10_1_hw_init,
 355         .hw_fini = mes_v10_1_hw_fini,
 356         .suspend = mes_v10_1_suspend,
 357         .resume = mes_v10_1_resume,
 358 };
 359 
 360 const struct amdgpu_ip_block_version mes_v10_1_ip_block = {
 361         .type = AMD_IP_BLOCK_TYPE_MES,
 362         .major = 10,
 363         .minor = 1,
 364         .rev = 0,
 365         .funcs = &mes_v10_1_ip_funcs,
 366 };

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