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

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

DEFINITIONS

This source file includes following definitions.
  1. amdgpu_atomfirmware_gpu_supports_virtualization
  2. amdgpu_atomfirmware_scratch_regs_init
  3. amdgpu_atomfirmware_allocate_fb_scratch
  4. amdgpu_atomfirmware_get_vram_width
  5. convert_atom_mem_type_to_vram_type
  6. amdgpu_atomfirmware_get_vram_type
  7. amdgpu_atomfirmware_mem_ecc_supported
  8. amdgpu_atomfirmware_sram_ecc_supported
  9. amdgpu_atomfirmware_get_clock_info
  10. amdgpu_atomfirmware_get_gfx_info

   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 <drm/amdgpu_drm.h>
  25 #include "amdgpu.h"
  26 #include "atomfirmware.h"
  27 #include "amdgpu_atomfirmware.h"
  28 #include "atom.h"
  29 #include "atombios.h"
  30 
  31 bool amdgpu_atomfirmware_gpu_supports_virtualization(struct amdgpu_device *adev)
  32 {
  33         int index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
  34                                                 firmwareinfo);
  35         uint16_t data_offset;
  36 
  37         if (amdgpu_atom_parse_data_header(adev->mode_info.atom_context, index, NULL,
  38                                           NULL, NULL, &data_offset)) {
  39                 struct atom_firmware_info_v3_1 *firmware_info =
  40                         (struct atom_firmware_info_v3_1 *)(adev->mode_info.atom_context->bios +
  41                                                            data_offset);
  42 
  43                 if (le32_to_cpu(firmware_info->firmware_capability) &
  44                     ATOM_FIRMWARE_CAP_GPU_VIRTUALIZATION)
  45                         return true;
  46         }
  47         return false;
  48 }
  49 
  50 void amdgpu_atomfirmware_scratch_regs_init(struct amdgpu_device *adev)
  51 {
  52         int index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
  53                                                 firmwareinfo);
  54         uint16_t data_offset;
  55 
  56         if (amdgpu_atom_parse_data_header(adev->mode_info.atom_context, index, NULL,
  57                                           NULL, NULL, &data_offset)) {
  58                 struct atom_firmware_info_v3_1 *firmware_info =
  59                         (struct atom_firmware_info_v3_1 *)(adev->mode_info.atom_context->bios +
  60                                                            data_offset);
  61 
  62                 adev->bios_scratch_reg_offset =
  63                         le32_to_cpu(firmware_info->bios_scratch_reg_startaddr);
  64         }
  65 }
  66 
  67 int amdgpu_atomfirmware_allocate_fb_scratch(struct amdgpu_device *adev)
  68 {
  69         struct atom_context *ctx = adev->mode_info.atom_context;
  70         int index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
  71                                                 vram_usagebyfirmware);
  72         struct vram_usagebyfirmware_v2_1 *      firmware_usage;
  73         uint32_t start_addr, size;
  74         uint16_t data_offset;
  75         int usage_bytes = 0;
  76 
  77         if (amdgpu_atom_parse_data_header(ctx, index, NULL, NULL, NULL, &data_offset)) {
  78                 firmware_usage = (struct vram_usagebyfirmware_v2_1 *)(ctx->bios + data_offset);
  79                 DRM_DEBUG("atom firmware requested %08x %dkb fw %dkb drv\n",
  80                           le32_to_cpu(firmware_usage->start_address_in_kb),
  81                           le16_to_cpu(firmware_usage->used_by_firmware_in_kb),
  82                           le16_to_cpu(firmware_usage->used_by_driver_in_kb));
  83 
  84                 start_addr = le32_to_cpu(firmware_usage->start_address_in_kb);
  85                 size = le16_to_cpu(firmware_usage->used_by_firmware_in_kb);
  86 
  87                 if ((uint32_t)(start_addr & ATOM_VRAM_OPERATION_FLAGS_MASK) ==
  88                         (uint32_t)(ATOM_VRAM_BLOCK_SRIOV_MSG_SHARE_RESERVATION <<
  89                         ATOM_VRAM_OPERATION_FLAGS_SHIFT)) {
  90                         /* Firmware request VRAM reservation for SR-IOV */
  91                         adev->fw_vram_usage.start_offset = (start_addr &
  92                                 (~ATOM_VRAM_OPERATION_FLAGS_MASK)) << 10;
  93                         adev->fw_vram_usage.size = size << 10;
  94                         /* Use the default scratch size */
  95                         usage_bytes = 0;
  96                 } else {
  97                         usage_bytes = le16_to_cpu(firmware_usage->used_by_driver_in_kb) << 10;
  98                 }
  99         }
 100         ctx->scratch_size_bytes = 0;
 101         if (usage_bytes == 0)
 102                 usage_bytes = 20 * 1024;
 103         /* allocate some scratch memory */
 104         ctx->scratch = kzalloc(usage_bytes, GFP_KERNEL);
 105         if (!ctx->scratch)
 106                 return -ENOMEM;
 107         ctx->scratch_size_bytes = usage_bytes;
 108         return 0;
 109 }
 110 
 111 union igp_info {
 112         struct atom_integrated_system_info_v1_11 v11;
 113 };
 114 
 115 union umc_info {
 116         struct atom_umc_info_v3_1 v31;
 117 };
 118 
 119 union vram_info {
 120         struct atom_vram_info_header_v2_3 v23;
 121         struct atom_vram_info_header_v2_4 v24;
 122 };
 123 /*
 124  * Return vram width from integrated system info table, if available,
 125  * or 0 if not.
 126  */
 127 int amdgpu_atomfirmware_get_vram_width(struct amdgpu_device *adev)
 128 {
 129         struct amdgpu_mode_info *mode_info = &adev->mode_info;
 130         int index;
 131         u16 data_offset, size;
 132         union igp_info *igp_info;
 133         union vram_info *vram_info;
 134         u32 mem_channel_number;
 135         u32 mem_channel_width;
 136         u8 frev, crev;
 137 
 138         if (adev->flags & AMD_IS_APU)
 139                 index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
 140                                                     integratedsysteminfo);
 141         else
 142                 index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
 143                                                     vram_info);
 144 
 145         /* get any igp specific overrides */
 146         if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, &size,
 147                                    &frev, &crev, &data_offset)) {
 148                 if (adev->flags & AMD_IS_APU) {
 149                         igp_info = (union igp_info *)
 150                                 (mode_info->atom_context->bios + data_offset);
 151                         switch (crev) {
 152                         case 11:
 153                                 mem_channel_number = igp_info->v11.umachannelnumber;
 154                                 /* channel width is 64 */
 155                                 return mem_channel_number * 64;
 156                         default:
 157                                 return 0;
 158                         }
 159                 } else {
 160                         vram_info = (union vram_info *)
 161                                 (mode_info->atom_context->bios + data_offset);
 162                         switch (crev) {
 163                         case 3:
 164                                 mem_channel_number = vram_info->v23.vram_module[0].channel_num;
 165                                 mem_channel_width = vram_info->v23.vram_module[0].channel_width;
 166                                 return mem_channel_number * (1 << mem_channel_width);
 167                         case 4:
 168                                 mem_channel_number = vram_info->v24.vram_module[0].channel_num;
 169                                 mem_channel_width = vram_info->v24.vram_module[0].channel_width;
 170                                 return mem_channel_number * (1 << mem_channel_width);
 171                         default:
 172                                 return 0;
 173                         }
 174                 }
 175         }
 176 
 177         return 0;
 178 }
 179 
 180 static int convert_atom_mem_type_to_vram_type (struct amdgpu_device *adev,
 181                                                int atom_mem_type)
 182 {
 183         int vram_type;
 184 
 185         if (adev->flags & AMD_IS_APU) {
 186                 switch (atom_mem_type) {
 187                 case Ddr2MemType:
 188                 case LpDdr2MemType:
 189                         vram_type = AMDGPU_VRAM_TYPE_DDR2;
 190                         break;
 191                 case Ddr3MemType:
 192                 case LpDdr3MemType:
 193                         vram_type = AMDGPU_VRAM_TYPE_DDR3;
 194                         break;
 195                 case Ddr4MemType:
 196                 case LpDdr4MemType:
 197                         vram_type = AMDGPU_VRAM_TYPE_DDR4;
 198                         break;
 199                 default:
 200                         vram_type = AMDGPU_VRAM_TYPE_UNKNOWN;
 201                         break;
 202                 }
 203         } else {
 204                 switch (atom_mem_type) {
 205                 case ATOM_DGPU_VRAM_TYPE_GDDR5:
 206                         vram_type = AMDGPU_VRAM_TYPE_GDDR5;
 207                         break;
 208                 case ATOM_DGPU_VRAM_TYPE_HBM2:
 209                         vram_type = AMDGPU_VRAM_TYPE_HBM;
 210                         break;
 211                 case ATOM_DGPU_VRAM_TYPE_GDDR6:
 212                         vram_type = AMDGPU_VRAM_TYPE_GDDR6;
 213                         break;
 214                 default:
 215                         vram_type = AMDGPU_VRAM_TYPE_UNKNOWN;
 216                         break;
 217                 }
 218         }
 219 
 220         return vram_type;
 221 }
 222 /*
 223  * Return vram type from either integrated system info table
 224  * or umc info table, if available, or 0 (TYPE_UNKNOWN) if not
 225  */
 226 int amdgpu_atomfirmware_get_vram_type(struct amdgpu_device *adev)
 227 {
 228         struct amdgpu_mode_info *mode_info = &adev->mode_info;
 229         int index;
 230         u16 data_offset, size;
 231         union igp_info *igp_info;
 232         union vram_info *vram_info;
 233         u8 frev, crev;
 234         u8 mem_type;
 235 
 236         if (adev->flags & AMD_IS_APU)
 237                 index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
 238                                                     integratedsysteminfo);
 239         else
 240                 index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
 241                                                     vram_info);
 242         if (amdgpu_atom_parse_data_header(mode_info->atom_context,
 243                                           index, &size,
 244                                           &frev, &crev, &data_offset)) {
 245                 if (adev->flags & AMD_IS_APU) {
 246                         igp_info = (union igp_info *)
 247                                 (mode_info->atom_context->bios + data_offset);
 248                         switch (crev) {
 249                         case 11:
 250                                 mem_type = igp_info->v11.memorytype;
 251                                 return convert_atom_mem_type_to_vram_type(adev, mem_type);
 252                         default:
 253                                 return 0;
 254                         }
 255                 } else {
 256                         vram_info = (union vram_info *)
 257                                 (mode_info->atom_context->bios + data_offset);
 258                         switch (crev) {
 259                         case 3:
 260                                 mem_type = vram_info->v23.vram_module[0].memory_type;
 261                                 return convert_atom_mem_type_to_vram_type(adev, mem_type);
 262                         case 4:
 263                                 mem_type = vram_info->v24.vram_module[0].memory_type;
 264                                 return convert_atom_mem_type_to_vram_type(adev, mem_type);
 265                         default:
 266                                 return 0;
 267                         }
 268                 }
 269         }
 270 
 271         return 0;
 272 }
 273 
 274 /*
 275  * Return true if vbios enabled ecc by default, if umc info table is available
 276  * or false if ecc is not enabled or umc info table is not available
 277  */
 278 bool amdgpu_atomfirmware_mem_ecc_supported(struct amdgpu_device *adev)
 279 {
 280         struct amdgpu_mode_info *mode_info = &adev->mode_info;
 281         int index;
 282         u16 data_offset, size;
 283         union umc_info *umc_info;
 284         u8 frev, crev;
 285         bool ecc_default_enabled = false;
 286 
 287         index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
 288                         umc_info);
 289 
 290         if (amdgpu_atom_parse_data_header(mode_info->atom_context,
 291                                 index, &size, &frev, &crev, &data_offset)) {
 292                 /* support umc_info 3.1+ */
 293                 if ((frev == 3 && crev >= 1) || (frev > 3)) {
 294                         umc_info = (union umc_info *)
 295                                 (mode_info->atom_context->bios + data_offset);
 296                         ecc_default_enabled =
 297                                 (le32_to_cpu(umc_info->v31.umc_config) &
 298                                  UMC_CONFIG__DEFAULT_MEM_ECC_ENABLE) ? true : false;
 299                 }
 300         }
 301 
 302         return ecc_default_enabled;
 303 }
 304 
 305 union firmware_info {
 306         struct atom_firmware_info_v3_1 v31;
 307 };
 308 
 309 /*
 310  * Return true if vbios supports sram ecc or false if not
 311  */
 312 bool amdgpu_atomfirmware_sram_ecc_supported(struct amdgpu_device *adev)
 313 {
 314         struct amdgpu_mode_info *mode_info = &adev->mode_info;
 315         int index;
 316         u16 data_offset, size;
 317         union firmware_info *firmware_info;
 318         u8 frev, crev;
 319         bool sram_ecc_supported = false;
 320 
 321         index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
 322                         firmwareinfo);
 323 
 324         if (amdgpu_atom_parse_data_header(adev->mode_info.atom_context,
 325                                 index, &size, &frev, &crev, &data_offset)) {
 326                 /* support firmware_info 3.1 + */
 327                 if ((frev == 3 && crev >=1) || (frev > 3)) {
 328                         firmware_info = (union firmware_info *)
 329                                 (mode_info->atom_context->bios + data_offset);
 330                         sram_ecc_supported =
 331                                 (le32_to_cpu(firmware_info->v31.firmware_capability) &
 332                                  ATOM_FIRMWARE_CAP_SRAM_ECC) ? true : false;
 333                 }
 334         }
 335 
 336         return sram_ecc_supported;
 337 }
 338 
 339 union smu_info {
 340         struct atom_smu_info_v3_1 v31;
 341 };
 342 
 343 int amdgpu_atomfirmware_get_clock_info(struct amdgpu_device *adev)
 344 {
 345         struct amdgpu_mode_info *mode_info = &adev->mode_info;
 346         struct amdgpu_pll *spll = &adev->clock.spll;
 347         struct amdgpu_pll *mpll = &adev->clock.mpll;
 348         uint8_t frev, crev;
 349         uint16_t data_offset;
 350         int ret = -EINVAL, index;
 351 
 352         index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
 353                                             firmwareinfo);
 354         if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,
 355                                    &frev, &crev, &data_offset)) {
 356                 union firmware_info *firmware_info =
 357                         (union firmware_info *)(mode_info->atom_context->bios +
 358                                                 data_offset);
 359 
 360                 adev->clock.default_sclk =
 361                         le32_to_cpu(firmware_info->v31.bootup_sclk_in10khz);
 362                 adev->clock.default_mclk =
 363                         le32_to_cpu(firmware_info->v31.bootup_mclk_in10khz);
 364 
 365                 adev->pm.current_sclk = adev->clock.default_sclk;
 366                 adev->pm.current_mclk = adev->clock.default_mclk;
 367 
 368                 /* not technically a clock, but... */
 369                 adev->mode_info.firmware_flags =
 370                         le32_to_cpu(firmware_info->v31.firmware_capability);
 371 
 372                 ret = 0;
 373         }
 374 
 375         index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
 376                                             smu_info);
 377         if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,
 378                                    &frev, &crev, &data_offset)) {
 379                 union smu_info *smu_info =
 380                         (union smu_info *)(mode_info->atom_context->bios +
 381                                            data_offset);
 382 
 383                 /* system clock */
 384                 spll->reference_freq = le32_to_cpu(smu_info->v31.core_refclk_10khz);
 385 
 386                 spll->reference_div = 0;
 387                 spll->min_post_div = 1;
 388                 spll->max_post_div = 1;
 389                 spll->min_ref_div = 2;
 390                 spll->max_ref_div = 0xff;
 391                 spll->min_feedback_div = 4;
 392                 spll->max_feedback_div = 0xff;
 393                 spll->best_vco = 0;
 394 
 395                 ret = 0;
 396         }
 397 
 398         index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
 399                                             umc_info);
 400         if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,
 401                                    &frev, &crev, &data_offset)) {
 402                 union umc_info *umc_info =
 403                         (union umc_info *)(mode_info->atom_context->bios +
 404                                            data_offset);
 405 
 406                 /* memory clock */
 407                 mpll->reference_freq = le32_to_cpu(umc_info->v31.mem_refclk_10khz);
 408 
 409                 mpll->reference_div = 0;
 410                 mpll->min_post_div = 1;
 411                 mpll->max_post_div = 1;
 412                 mpll->min_ref_div = 2;
 413                 mpll->max_ref_div = 0xff;
 414                 mpll->min_feedback_div = 4;
 415                 mpll->max_feedback_div = 0xff;
 416                 mpll->best_vco = 0;
 417 
 418                 ret = 0;
 419         }
 420 
 421         return ret;
 422 }
 423 
 424 union gfx_info {
 425         struct  atom_gfx_info_v2_4 v24;
 426 };
 427 
 428 int amdgpu_atomfirmware_get_gfx_info(struct amdgpu_device *adev)
 429 {
 430         struct amdgpu_mode_info *mode_info = &adev->mode_info;
 431         int index;
 432         uint8_t frev, crev;
 433         uint16_t data_offset;
 434 
 435         index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
 436                                             gfx_info);
 437         if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,
 438                                    &frev, &crev, &data_offset)) {
 439                 union gfx_info *gfx_info = (union gfx_info *)
 440                         (mode_info->atom_context->bios + data_offset);
 441                 switch (crev) {
 442                 case 4:
 443                         adev->gfx.config.max_shader_engines = gfx_info->v24.max_shader_engines;
 444                         adev->gfx.config.max_cu_per_sh = gfx_info->v24.max_cu_per_sh;
 445                         adev->gfx.config.max_sh_per_se = gfx_info->v24.max_sh_per_se;
 446                         adev->gfx.config.max_backends_per_se = gfx_info->v24.max_backends_per_se;
 447                         adev->gfx.config.max_texture_channel_caches = gfx_info->v24.max_texture_channel_caches;
 448                         adev->gfx.config.max_gprs = le16_to_cpu(gfx_info->v24.gc_num_gprs);
 449                         adev->gfx.config.max_gs_threads = gfx_info->v24.gc_num_max_gs_thds;
 450                         adev->gfx.config.gs_vgt_table_depth = gfx_info->v24.gc_gs_table_depth;
 451                         adev->gfx.config.gs_prim_buffer_depth =
 452                                 le16_to_cpu(gfx_info->v24.gc_gsprim_buff_depth);
 453                         adev->gfx.config.double_offchip_lds_buf =
 454                                 gfx_info->v24.gc_double_offchip_lds_buffer;
 455                         adev->gfx.cu_info.wave_front_size = le16_to_cpu(gfx_info->v24.gc_wave_size);
 456                         adev->gfx.cu_info.max_waves_per_simd = le16_to_cpu(gfx_info->v24.gc_max_waves_per_simd);
 457                         adev->gfx.cu_info.max_scratch_slots_per_cu = gfx_info->v24.gc_max_scratch_slots_per_cu;
 458                         adev->gfx.cu_info.lds_size = le16_to_cpu(gfx_info->v24.gc_lds_size);
 459                         return 0;
 460                 default:
 461                         return -EINVAL;
 462                 }
 463 
 464         }
 465         return -EINVAL;
 466 }

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