1fb4d8502Sjsg /*
2fb4d8502Sjsg * Copyright 2016 Advanced Micro Devices, Inc.
3fb4d8502Sjsg *
4fb4d8502Sjsg * Permission is hereby granted, free of charge, to any person obtaining a
5fb4d8502Sjsg * copy of this software and associated documentation files (the "Software"),
6fb4d8502Sjsg * to deal in the Software without restriction, including without limitation
7fb4d8502Sjsg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8fb4d8502Sjsg * and/or sell copies of the Software, and to permit persons to whom the
9fb4d8502Sjsg * Software is furnished to do so, subject to the following conditions:
10fb4d8502Sjsg *
11fb4d8502Sjsg * The above copyright notice and this permission notice shall be included in
12fb4d8502Sjsg * all copies or substantial portions of the Software.
13fb4d8502Sjsg *
14fb4d8502Sjsg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15fb4d8502Sjsg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16fb4d8502Sjsg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17fb4d8502Sjsg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18fb4d8502Sjsg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19fb4d8502Sjsg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20fb4d8502Sjsg * OTHER DEALINGS IN THE SOFTWARE.
21fb4d8502Sjsg *
22fb4d8502Sjsg */
23c349dbc7Sjsg
24fb4d8502Sjsg #include <drm/amdgpu_drm.h>
25fb4d8502Sjsg #include "amdgpu.h"
26fb4d8502Sjsg #include "atomfirmware.h"
27fb4d8502Sjsg #include "amdgpu_atomfirmware.h"
28fb4d8502Sjsg #include "atom.h"
29fb4d8502Sjsg #include "atombios.h"
30c349dbc7Sjsg #include "soc15_hw_ip.h"
31fb4d8502Sjsg
325ca02815Sjsg union firmware_info {
335ca02815Sjsg struct atom_firmware_info_v3_1 v31;
345ca02815Sjsg struct atom_firmware_info_v3_2 v32;
355ca02815Sjsg struct atom_firmware_info_v3_3 v33;
365ca02815Sjsg struct atom_firmware_info_v3_4 v34;
375ca02815Sjsg };
385ca02815Sjsg
395ca02815Sjsg /*
405ca02815Sjsg * Helper function to query firmware capability
415ca02815Sjsg *
425ca02815Sjsg * @adev: amdgpu_device pointer
435ca02815Sjsg *
445ca02815Sjsg * Return firmware_capability in firmwareinfo table on success or 0 if not
455ca02815Sjsg */
amdgpu_atomfirmware_query_firmware_capability(struct amdgpu_device * adev)465ca02815Sjsg uint32_t amdgpu_atomfirmware_query_firmware_capability(struct amdgpu_device *adev)
47fb4d8502Sjsg {
485ca02815Sjsg struct amdgpu_mode_info *mode_info = &adev->mode_info;
495ca02815Sjsg int index;
505ca02815Sjsg u16 data_offset, size;
515ca02815Sjsg union firmware_info *firmware_info;
525ca02815Sjsg u8 frev, crev;
535ca02815Sjsg u32 fw_cap = 0;
545ca02815Sjsg
555ca02815Sjsg index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
56fb4d8502Sjsg firmwareinfo);
57fb4d8502Sjsg
585ca02815Sjsg if (amdgpu_atom_parse_data_header(adev->mode_info.atom_context,
595ca02815Sjsg index, &size, &frev, &crev, &data_offset)) {
605ca02815Sjsg /* support firmware_info 3.1 + */
615ca02815Sjsg if ((frev == 3 && crev >= 1) || (frev > 3)) {
625ca02815Sjsg firmware_info = (union firmware_info *)
635ca02815Sjsg (mode_info->atom_context->bios + data_offset);
645ca02815Sjsg fw_cap = le32_to_cpu(firmware_info->v31.firmware_capability);
65fb4d8502Sjsg }
665ca02815Sjsg }
675ca02815Sjsg
685ca02815Sjsg return fw_cap;
695ca02815Sjsg }
705ca02815Sjsg
715ca02815Sjsg /*
725ca02815Sjsg * Helper function to query gpu virtualizaiton capability
735ca02815Sjsg *
745ca02815Sjsg * @adev: amdgpu_device pointer
755ca02815Sjsg *
765ca02815Sjsg * Return true if gpu virtualization is supported or false if not
775ca02815Sjsg */
amdgpu_atomfirmware_gpu_virtualization_supported(struct amdgpu_device * adev)785ca02815Sjsg bool amdgpu_atomfirmware_gpu_virtualization_supported(struct amdgpu_device *adev)
795ca02815Sjsg {
805ca02815Sjsg u32 fw_cap;
815ca02815Sjsg
825ca02815Sjsg fw_cap = adev->mode_info.firmware_flags;
835ca02815Sjsg
845ca02815Sjsg return (fw_cap & ATOM_FIRMWARE_CAP_GPU_VIRTUALIZATION) ? true : false;
85fb4d8502Sjsg }
86fb4d8502Sjsg
amdgpu_atomfirmware_scratch_regs_init(struct amdgpu_device * adev)87fb4d8502Sjsg void amdgpu_atomfirmware_scratch_regs_init(struct amdgpu_device *adev)
88fb4d8502Sjsg {
89fb4d8502Sjsg int index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
90fb4d8502Sjsg firmwareinfo);
91fb4d8502Sjsg uint16_t data_offset;
92fb4d8502Sjsg
93fb4d8502Sjsg if (amdgpu_atom_parse_data_header(adev->mode_info.atom_context, index, NULL,
94fb4d8502Sjsg NULL, NULL, &data_offset)) {
95fb4d8502Sjsg struct atom_firmware_info_v3_1 *firmware_info =
96fb4d8502Sjsg (struct atom_firmware_info_v3_1 *)(adev->mode_info.atom_context->bios +
97fb4d8502Sjsg data_offset);
98fb4d8502Sjsg
99fb4d8502Sjsg adev->bios_scratch_reg_offset =
100fb4d8502Sjsg le32_to_cpu(firmware_info->bios_scratch_reg_startaddr);
101fb4d8502Sjsg }
102fb4d8502Sjsg }
103fb4d8502Sjsg
amdgpu_atomfirmware_allocate_fb_v2_1(struct amdgpu_device * adev,struct vram_usagebyfirmware_v2_1 * fw_usage,int * usage_bytes)1040b078e87Sjsg static int amdgpu_atomfirmware_allocate_fb_v2_1(struct amdgpu_device *adev,
1050b078e87Sjsg struct vram_usagebyfirmware_v2_1 *fw_usage, int *usage_bytes)
106fb4d8502Sjsg {
107f005ef32Sjsg u32 start_addr, fw_size, drv_size;
108fb4d8502Sjsg
1090b078e87Sjsg start_addr = le32_to_cpu(fw_usage->start_address_in_kb);
1100b078e87Sjsg fw_size = le16_to_cpu(fw_usage->used_by_firmware_in_kb);
1110b078e87Sjsg drv_size = le16_to_cpu(fw_usage->used_by_driver_in_kb);
112fb4d8502Sjsg
1130b078e87Sjsg DRM_DEBUG("atom firmware v2_1 requested %08x %dkb fw %dkb drv\n",
1140b078e87Sjsg start_addr,
1150b078e87Sjsg fw_size,
1160b078e87Sjsg drv_size);
117fb4d8502Sjsg
1180b078e87Sjsg if ((start_addr & ATOM_VRAM_OPERATION_FLAGS_MASK) ==
119f005ef32Sjsg (u32)(ATOM_VRAM_BLOCK_SRIOV_MSG_SHARE_RESERVATION <<
120fb4d8502Sjsg ATOM_VRAM_OPERATION_FLAGS_SHIFT)) {
121fb4d8502Sjsg /* Firmware request VRAM reservation for SR-IOV */
122ad8b1aafSjsg adev->mman.fw_vram_usage_start_offset = (start_addr &
123fb4d8502Sjsg (~ATOM_VRAM_OPERATION_FLAGS_MASK)) << 10;
1240b078e87Sjsg adev->mman.fw_vram_usage_size = fw_size << 10;
125fb4d8502Sjsg /* Use the default scratch size */
1260b078e87Sjsg *usage_bytes = 0;
127fb4d8502Sjsg } else {
1280b078e87Sjsg *usage_bytes = drv_size << 10;
1290b078e87Sjsg }
1300b078e87Sjsg return 0;
1310b078e87Sjsg }
1320b078e87Sjsg
amdgpu_atomfirmware_allocate_fb_v2_2(struct amdgpu_device * adev,struct vram_usagebyfirmware_v2_2 * fw_usage,int * usage_bytes)1330b078e87Sjsg static int amdgpu_atomfirmware_allocate_fb_v2_2(struct amdgpu_device *adev,
1340b078e87Sjsg struct vram_usagebyfirmware_v2_2 *fw_usage, int *usage_bytes)
1350b078e87Sjsg {
136f005ef32Sjsg u32 fw_start_addr, fw_size, drv_start_addr, drv_size;
1370b078e87Sjsg
1380b078e87Sjsg fw_start_addr = le32_to_cpu(fw_usage->fw_region_start_address_in_kb);
1390b078e87Sjsg fw_size = le16_to_cpu(fw_usage->used_by_firmware_in_kb);
1400b078e87Sjsg
1410b078e87Sjsg drv_start_addr = le32_to_cpu(fw_usage->driver_region0_start_address_in_kb);
1420b078e87Sjsg drv_size = le32_to_cpu(fw_usage->used_by_driver_region0_in_kb);
1430b078e87Sjsg
1440b078e87Sjsg DRM_DEBUG("atom requested fw start at %08x %dkb and drv start at %08x %dkb\n",
1450b078e87Sjsg fw_start_addr,
1460b078e87Sjsg fw_size,
1470b078e87Sjsg drv_start_addr,
1480b078e87Sjsg drv_size);
1490b078e87Sjsg
150f005ef32Sjsg if (amdgpu_sriov_vf(adev) &&
151f005ef32Sjsg ((fw_start_addr & (ATOM_VRAM_BLOCK_NEEDS_NO_RESERVATION <<
152f005ef32Sjsg ATOM_VRAM_OPERATION_FLAGS_SHIFT)) == 0)) {
1530b078e87Sjsg /* Firmware request VRAM reservation for SR-IOV */
1540b078e87Sjsg adev->mman.fw_vram_usage_start_offset = (fw_start_addr &
1550b078e87Sjsg (~ATOM_VRAM_OPERATION_FLAGS_MASK)) << 10;
1560b078e87Sjsg adev->mman.fw_vram_usage_size = fw_size << 10;
1570b078e87Sjsg }
1580b078e87Sjsg
159f005ef32Sjsg if (amdgpu_sriov_vf(adev) &&
160f005ef32Sjsg ((drv_start_addr & (ATOM_VRAM_BLOCK_NEEDS_NO_RESERVATION <<
161f005ef32Sjsg ATOM_VRAM_OPERATION_FLAGS_SHIFT)) == 0)) {
1620b078e87Sjsg /* driver request VRAM reservation for SR-IOV */
1630b078e87Sjsg adev->mman.drv_vram_usage_start_offset = (drv_start_addr &
1640b078e87Sjsg (~ATOM_VRAM_OPERATION_FLAGS_MASK)) << 10;
1650b078e87Sjsg adev->mman.drv_vram_usage_size = drv_size << 10;
1660b078e87Sjsg }
1670b078e87Sjsg
1680b078e87Sjsg *usage_bytes = 0;
1690b078e87Sjsg return 0;
1700b078e87Sjsg }
1710b078e87Sjsg
amdgpu_atomfirmware_allocate_fb_scratch(struct amdgpu_device * adev)1720b078e87Sjsg int amdgpu_atomfirmware_allocate_fb_scratch(struct amdgpu_device *adev)
1730b078e87Sjsg {
1740b078e87Sjsg struct atom_context *ctx = adev->mode_info.atom_context;
1750b078e87Sjsg int index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
1760b078e87Sjsg vram_usagebyfirmware);
1770b078e87Sjsg struct vram_usagebyfirmware_v2_1 *fw_usage_v2_1;
1780b078e87Sjsg struct vram_usagebyfirmware_v2_2 *fw_usage_v2_2;
179f005ef32Sjsg u16 data_offset;
180f005ef32Sjsg u8 frev, crev;
1810b078e87Sjsg int usage_bytes = 0;
1820b078e87Sjsg
1830b078e87Sjsg if (amdgpu_atom_parse_data_header(ctx, index, NULL, &frev, &crev, &data_offset)) {
1840b078e87Sjsg if (frev == 2 && crev == 1) {
1850b078e87Sjsg fw_usage_v2_1 =
1860b078e87Sjsg (struct vram_usagebyfirmware_v2_1 *)(ctx->bios + data_offset);
1870b078e87Sjsg amdgpu_atomfirmware_allocate_fb_v2_1(adev,
1880b078e87Sjsg fw_usage_v2_1,
1890b078e87Sjsg &usage_bytes);
1900b078e87Sjsg } else if (frev >= 2 && crev >= 2) {
1910b078e87Sjsg fw_usage_v2_2 =
1920b078e87Sjsg (struct vram_usagebyfirmware_v2_2 *)(ctx->bios + data_offset);
1930b078e87Sjsg amdgpu_atomfirmware_allocate_fb_v2_2(adev,
1940b078e87Sjsg fw_usage_v2_2,
1950b078e87Sjsg &usage_bytes);
196fb4d8502Sjsg }
197fb4d8502Sjsg }
1980b078e87Sjsg
199fb4d8502Sjsg ctx->scratch_size_bytes = 0;
200fb4d8502Sjsg if (usage_bytes == 0)
201fb4d8502Sjsg usage_bytes = 20 * 1024;
202fb4d8502Sjsg /* allocate some scratch memory */
203fb4d8502Sjsg ctx->scratch = kzalloc(usage_bytes, GFP_KERNEL);
204fb4d8502Sjsg if (!ctx->scratch)
205fb4d8502Sjsg return -ENOMEM;
206fb4d8502Sjsg ctx->scratch_size_bytes = usage_bytes;
207fb4d8502Sjsg return 0;
208fb4d8502Sjsg }
209fb4d8502Sjsg
210fb4d8502Sjsg union igp_info {
211fb4d8502Sjsg struct atom_integrated_system_info_v1_11 v11;
212ad8b1aafSjsg struct atom_integrated_system_info_v1_12 v12;
2135ca02815Sjsg struct atom_integrated_system_info_v2_1 v21;
214c5a8dd44Sjsg struct atom_integrated_system_info_v2_3 v23;
215fb4d8502Sjsg };
216fb4d8502Sjsg
217fb4d8502Sjsg union umc_info {
218fb4d8502Sjsg struct atom_umc_info_v3_1 v31;
2195ca02815Sjsg struct atom_umc_info_v3_2 v32;
2205ca02815Sjsg struct atom_umc_info_v3_3 v33;
221f005ef32Sjsg struct atom_umc_info_v4_0 v40;
222fb4d8502Sjsg };
223fb4d8502Sjsg
224c349dbc7Sjsg union vram_info {
225c349dbc7Sjsg struct atom_vram_info_header_v2_3 v23;
226c349dbc7Sjsg struct atom_vram_info_header_v2_4 v24;
227ad8b1aafSjsg struct atom_vram_info_header_v2_5 v25;
2285ca02815Sjsg struct atom_vram_info_header_v2_6 v26;
2291bb76ff1Sjsg struct atom_vram_info_header_v3_0 v30;
230c349dbc7Sjsg };
231fb4d8502Sjsg
232c349dbc7Sjsg union vram_module {
233c349dbc7Sjsg struct atom_vram_module_v9 v9;
234c349dbc7Sjsg struct atom_vram_module_v10 v10;
235ad8b1aafSjsg struct atom_vram_module_v11 v11;
2361bb76ff1Sjsg struct atom_vram_module_v3_0 v30;
237c349dbc7Sjsg };
238fb4d8502Sjsg
convert_atom_mem_type_to_vram_type(struct amdgpu_device * adev,int atom_mem_type)239fb4d8502Sjsg static int convert_atom_mem_type_to_vram_type(struct amdgpu_device *adev,
240fb4d8502Sjsg int atom_mem_type)
241fb4d8502Sjsg {
242fb4d8502Sjsg int vram_type;
243fb4d8502Sjsg
244fb4d8502Sjsg if (adev->flags & AMD_IS_APU) {
245fb4d8502Sjsg switch (atom_mem_type) {
246fb4d8502Sjsg case Ddr2MemType:
247fb4d8502Sjsg case LpDdr2MemType:
248fb4d8502Sjsg vram_type = AMDGPU_VRAM_TYPE_DDR2;
249fb4d8502Sjsg break;
250fb4d8502Sjsg case Ddr3MemType:
251fb4d8502Sjsg case LpDdr3MemType:
252fb4d8502Sjsg vram_type = AMDGPU_VRAM_TYPE_DDR3;
253fb4d8502Sjsg break;
254fb4d8502Sjsg case Ddr4MemType:
255fb4d8502Sjsg vram_type = AMDGPU_VRAM_TYPE_DDR4;
256fb4d8502Sjsg break;
2571bb76ff1Sjsg case LpDdr4MemType:
2581bb76ff1Sjsg vram_type = AMDGPU_VRAM_TYPE_LPDDR4;
2591bb76ff1Sjsg break;
2605ca02815Sjsg case Ddr5MemType:
2615ca02815Sjsg vram_type = AMDGPU_VRAM_TYPE_DDR5;
2625ca02815Sjsg break;
2631bb76ff1Sjsg case LpDdr5MemType:
2641bb76ff1Sjsg vram_type = AMDGPU_VRAM_TYPE_LPDDR5;
2651bb76ff1Sjsg break;
266fb4d8502Sjsg default:
267fb4d8502Sjsg vram_type = AMDGPU_VRAM_TYPE_UNKNOWN;
268fb4d8502Sjsg break;
269fb4d8502Sjsg }
270fb4d8502Sjsg } else {
271fb4d8502Sjsg switch (atom_mem_type) {
272fb4d8502Sjsg case ATOM_DGPU_VRAM_TYPE_GDDR5:
273fb4d8502Sjsg vram_type = AMDGPU_VRAM_TYPE_GDDR5;
274fb4d8502Sjsg break;
275c349dbc7Sjsg case ATOM_DGPU_VRAM_TYPE_HBM2:
2765ca02815Sjsg case ATOM_DGPU_VRAM_TYPE_HBM2E:
277f005ef32Sjsg case ATOM_DGPU_VRAM_TYPE_HBM3:
278fb4d8502Sjsg vram_type = AMDGPU_VRAM_TYPE_HBM;
279fb4d8502Sjsg break;
280c349dbc7Sjsg case ATOM_DGPU_VRAM_TYPE_GDDR6:
281c349dbc7Sjsg vram_type = AMDGPU_VRAM_TYPE_GDDR6;
282c349dbc7Sjsg break;
283fb4d8502Sjsg default:
284fb4d8502Sjsg vram_type = AMDGPU_VRAM_TYPE_UNKNOWN;
285fb4d8502Sjsg break;
286fb4d8502Sjsg }
287fb4d8502Sjsg }
288fb4d8502Sjsg
289fb4d8502Sjsg return vram_type;
290fb4d8502Sjsg }
291c349dbc7Sjsg
292c349dbc7Sjsg
293c349dbc7Sjsg int
amdgpu_atomfirmware_get_vram_info(struct amdgpu_device * adev,int * vram_width,int * vram_type,int * vram_vendor)294c349dbc7Sjsg amdgpu_atomfirmware_get_vram_info(struct amdgpu_device *adev,
295c349dbc7Sjsg int *vram_width, int *vram_type,
296c349dbc7Sjsg int *vram_vendor)
297fb4d8502Sjsg {
298fb4d8502Sjsg struct amdgpu_mode_info *mode_info = &adev->mode_info;
299c349dbc7Sjsg int index, i = 0;
300fb4d8502Sjsg u16 data_offset, size;
301fb4d8502Sjsg union igp_info *igp_info;
302c349dbc7Sjsg union vram_info *vram_info;
303c349dbc7Sjsg union vram_module *vram_module;
304fb4d8502Sjsg u8 frev, crev;
305fb4d8502Sjsg u8 mem_type;
306c349dbc7Sjsg u8 mem_vendor;
307c349dbc7Sjsg u32 mem_channel_number;
308c349dbc7Sjsg u32 mem_channel_width;
309c349dbc7Sjsg u32 module_id;
310fb4d8502Sjsg
311fb4d8502Sjsg if (adev->flags & AMD_IS_APU)
312fb4d8502Sjsg index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
313fb4d8502Sjsg integratedsysteminfo);
314fb4d8502Sjsg else
315fb4d8502Sjsg index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
316c349dbc7Sjsg vram_info);
317c349dbc7Sjsg
318fb4d8502Sjsg if (amdgpu_atom_parse_data_header(mode_info->atom_context,
319fb4d8502Sjsg index, &size,
320fb4d8502Sjsg &frev, &crev, &data_offset)) {
321fb4d8502Sjsg if (adev->flags & AMD_IS_APU) {
322fb4d8502Sjsg igp_info = (union igp_info *)
323fb4d8502Sjsg (mode_info->atom_context->bios + data_offset);
3245ca02815Sjsg switch (frev) {
3255ca02815Sjsg case 1:
326fb4d8502Sjsg switch (crev) {
327fb4d8502Sjsg case 11:
3285ca02815Sjsg case 12:
329c349dbc7Sjsg mem_channel_number = igp_info->v11.umachannelnumber;
3305ca02815Sjsg if (!mem_channel_number)
3315ca02815Sjsg mem_channel_number = 1;
332fb4d8502Sjsg mem_type = igp_info->v11.memorytype;
333f005ef32Sjsg if (mem_type == LpDdr5MemType)
334f005ef32Sjsg mem_channel_width = 32;
335f005ef32Sjsg else
336f005ef32Sjsg mem_channel_width = 64;
337f005ef32Sjsg if (vram_width)
338f005ef32Sjsg *vram_width = mem_channel_number * mem_channel_width;
339c349dbc7Sjsg if (vram_type)
340c349dbc7Sjsg *vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
341c349dbc7Sjsg break;
3425ca02815Sjsg default:
3435ca02815Sjsg return -EINVAL;
3445ca02815Sjsg }
3455ca02815Sjsg break;
3465ca02815Sjsg case 2:
3475ca02815Sjsg switch (crev) {
3485ca02815Sjsg case 1:
3495ca02815Sjsg case 2:
3505ca02815Sjsg mem_channel_number = igp_info->v21.umachannelnumber;
3515ca02815Sjsg if (!mem_channel_number)
3525ca02815Sjsg mem_channel_number = 1;
3535ca02815Sjsg mem_type = igp_info->v21.memorytype;
354f005ef32Sjsg if (mem_type == LpDdr5MemType)
355f005ef32Sjsg mem_channel_width = 32;
356f005ef32Sjsg else
357f005ef32Sjsg mem_channel_width = 64;
358f005ef32Sjsg if (vram_width)
359f005ef32Sjsg *vram_width = mem_channel_number * mem_channel_width;
360ad8b1aafSjsg if (vram_type)
361ad8b1aafSjsg *vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
362ad8b1aafSjsg break;
363c5a8dd44Sjsg case 3:
364c5a8dd44Sjsg mem_channel_number = igp_info->v23.umachannelnumber;
365c5a8dd44Sjsg if (!mem_channel_number)
366c5a8dd44Sjsg mem_channel_number = 1;
367c5a8dd44Sjsg mem_type = igp_info->v23.memorytype;
368c5a8dd44Sjsg if (mem_type == LpDdr5MemType)
369c5a8dd44Sjsg mem_channel_width = 32;
370c5a8dd44Sjsg else
371c5a8dd44Sjsg mem_channel_width = 64;
372c5a8dd44Sjsg if (vram_width)
373c5a8dd44Sjsg *vram_width = mem_channel_number * mem_channel_width;
374c5a8dd44Sjsg if (vram_type)
375c5a8dd44Sjsg *vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
376c5a8dd44Sjsg break;
377fb4d8502Sjsg default:
378c349dbc7Sjsg return -EINVAL;
379fb4d8502Sjsg }
3805ca02815Sjsg break;
3815ca02815Sjsg default:
3825ca02815Sjsg return -EINVAL;
3835ca02815Sjsg }
384fb4d8502Sjsg } else {
385c349dbc7Sjsg vram_info = (union vram_info *)
386fb4d8502Sjsg (mode_info->atom_context->bios + data_offset);
387c349dbc7Sjsg module_id = (RREG32(adev->bios_scratch_reg_offset + 4) & 0x00ff0000) >> 16;
3881bb76ff1Sjsg if (frev == 3) {
389fb4d8502Sjsg switch (crev) {
3901bb76ff1Sjsg /* v30 */
3911bb76ff1Sjsg case 0:
3921bb76ff1Sjsg vram_module = (union vram_module *)vram_info->v30.vram_module;
3931bb76ff1Sjsg mem_vendor = (vram_module->v30.dram_vendor_id) & 0xF;
3941bb76ff1Sjsg if (vram_vendor)
3951bb76ff1Sjsg *vram_vendor = mem_vendor;
3961bb76ff1Sjsg mem_type = vram_info->v30.memory_type;
3971bb76ff1Sjsg if (vram_type)
3981bb76ff1Sjsg *vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
3991bb76ff1Sjsg mem_channel_number = vram_info->v30.channel_num;
4001bb76ff1Sjsg mem_channel_width = vram_info->v30.channel_width;
4011bb76ff1Sjsg if (vram_width)
402*bbf6c1fcSjsg *vram_width = mem_channel_number * 16;
4031bb76ff1Sjsg break;
4041bb76ff1Sjsg default:
4051bb76ff1Sjsg return -EINVAL;
4061bb76ff1Sjsg }
4071bb76ff1Sjsg } else if (frev == 2) {
4081bb76ff1Sjsg switch (crev) {
4091bb76ff1Sjsg /* v23 */
410c349dbc7Sjsg case 3:
411c349dbc7Sjsg if (module_id > vram_info->v23.vram_module_num)
412c349dbc7Sjsg module_id = 0;
413c349dbc7Sjsg vram_module = (union vram_module *)vram_info->v23.vram_module;
414c349dbc7Sjsg while (i < module_id) {
415c349dbc7Sjsg vram_module = (union vram_module *)
416c349dbc7Sjsg ((u8 *)vram_module + vram_module->v9.vram_module_size);
417c349dbc7Sjsg i++;
418fb4d8502Sjsg }
419c349dbc7Sjsg mem_type = vram_module->v9.memory_type;
420c349dbc7Sjsg if (vram_type)
421c349dbc7Sjsg *vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
422c349dbc7Sjsg mem_channel_number = vram_module->v9.channel_num;
423c349dbc7Sjsg mem_channel_width = vram_module->v9.channel_width;
424c349dbc7Sjsg if (vram_width)
425c349dbc7Sjsg *vram_width = mem_channel_number * (1 << mem_channel_width);
426c349dbc7Sjsg mem_vendor = (vram_module->v9.vender_rev_id) & 0xF;
427c349dbc7Sjsg if (vram_vendor)
428c349dbc7Sjsg *vram_vendor = mem_vendor;
429c349dbc7Sjsg break;
4301bb76ff1Sjsg /* v24 */
431c349dbc7Sjsg case 4:
432c349dbc7Sjsg if (module_id > vram_info->v24.vram_module_num)
433c349dbc7Sjsg module_id = 0;
434c349dbc7Sjsg vram_module = (union vram_module *)vram_info->v24.vram_module;
435c349dbc7Sjsg while (i < module_id) {
436c349dbc7Sjsg vram_module = (union vram_module *)
437c349dbc7Sjsg ((u8 *)vram_module + vram_module->v10.vram_module_size);
438c349dbc7Sjsg i++;
439c349dbc7Sjsg }
440c349dbc7Sjsg mem_type = vram_module->v10.memory_type;
441c349dbc7Sjsg if (vram_type)
442c349dbc7Sjsg *vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
443c349dbc7Sjsg mem_channel_number = vram_module->v10.channel_num;
444c349dbc7Sjsg mem_channel_width = vram_module->v10.channel_width;
445c349dbc7Sjsg if (vram_width)
446c349dbc7Sjsg *vram_width = mem_channel_number * (1 << mem_channel_width);
447c349dbc7Sjsg mem_vendor = (vram_module->v10.vender_rev_id) & 0xF;
448c349dbc7Sjsg if (vram_vendor)
449c349dbc7Sjsg *vram_vendor = mem_vendor;
450c349dbc7Sjsg break;
4511bb76ff1Sjsg /* v25 */
452ad8b1aafSjsg case 5:
453ad8b1aafSjsg if (module_id > vram_info->v25.vram_module_num)
454ad8b1aafSjsg module_id = 0;
455ad8b1aafSjsg vram_module = (union vram_module *)vram_info->v25.vram_module;
456ad8b1aafSjsg while (i < module_id) {
457ad8b1aafSjsg vram_module = (union vram_module *)
458ad8b1aafSjsg ((u8 *)vram_module + vram_module->v11.vram_module_size);
459ad8b1aafSjsg i++;
460ad8b1aafSjsg }
461ad8b1aafSjsg mem_type = vram_module->v11.memory_type;
462ad8b1aafSjsg if (vram_type)
463ad8b1aafSjsg *vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
464ad8b1aafSjsg mem_channel_number = vram_module->v11.channel_num;
465ad8b1aafSjsg mem_channel_width = vram_module->v11.channel_width;
466ad8b1aafSjsg if (vram_width)
467ad8b1aafSjsg *vram_width = mem_channel_number * (1 << mem_channel_width);
468ad8b1aafSjsg mem_vendor = (vram_module->v11.vender_rev_id) & 0xF;
469ad8b1aafSjsg if (vram_vendor)
470ad8b1aafSjsg *vram_vendor = mem_vendor;
471ad8b1aafSjsg break;
4721bb76ff1Sjsg /* v26 */
4735ca02815Sjsg case 6:
4745ca02815Sjsg if (module_id > vram_info->v26.vram_module_num)
4755ca02815Sjsg module_id = 0;
4765ca02815Sjsg vram_module = (union vram_module *)vram_info->v26.vram_module;
4775ca02815Sjsg while (i < module_id) {
4785ca02815Sjsg vram_module = (union vram_module *)
4795ca02815Sjsg ((u8 *)vram_module + vram_module->v9.vram_module_size);
4805ca02815Sjsg i++;
4815ca02815Sjsg }
4825ca02815Sjsg mem_type = vram_module->v9.memory_type;
4835ca02815Sjsg if (vram_type)
4845ca02815Sjsg *vram_type = convert_atom_mem_type_to_vram_type(adev, mem_type);
4855ca02815Sjsg mem_channel_number = vram_module->v9.channel_num;
4865ca02815Sjsg mem_channel_width = vram_module->v9.channel_width;
4875ca02815Sjsg if (vram_width)
4885ca02815Sjsg *vram_width = mem_channel_number * (1 << mem_channel_width);
4895ca02815Sjsg mem_vendor = (vram_module->v9.vender_rev_id) & 0xF;
4905ca02815Sjsg if (vram_vendor)
4915ca02815Sjsg *vram_vendor = mem_vendor;
4925ca02815Sjsg break;
493c349dbc7Sjsg default:
494c349dbc7Sjsg return -EINVAL;
495fb4d8502Sjsg }
4961bb76ff1Sjsg } else {
4971bb76ff1Sjsg /* invalid frev */
4981bb76ff1Sjsg return -EINVAL;
4991bb76ff1Sjsg }
500fb4d8502Sjsg }
501fb4d8502Sjsg
502c349dbc7Sjsg }
503c349dbc7Sjsg
504fb4d8502Sjsg return 0;
505fb4d8502Sjsg }
506fb4d8502Sjsg
507c349dbc7Sjsg /*
508c349dbc7Sjsg * Return true if vbios enabled ecc by default, if umc info table is available
509c349dbc7Sjsg * or false if ecc is not enabled or umc info table is not available
510c349dbc7Sjsg */
amdgpu_atomfirmware_mem_ecc_supported(struct amdgpu_device * adev)511c349dbc7Sjsg bool amdgpu_atomfirmware_mem_ecc_supported(struct amdgpu_device *adev)
512c349dbc7Sjsg {
513c349dbc7Sjsg struct amdgpu_mode_info *mode_info = &adev->mode_info;
514c349dbc7Sjsg int index;
515c349dbc7Sjsg u16 data_offset, size;
516c349dbc7Sjsg union umc_info *umc_info;
517c349dbc7Sjsg u8 frev, crev;
518c349dbc7Sjsg bool ecc_default_enabled = false;
5195ca02815Sjsg u8 umc_config;
5205ca02815Sjsg u32 umc_config1;
521c349dbc7Sjsg
522c349dbc7Sjsg index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
523c349dbc7Sjsg umc_info);
524c349dbc7Sjsg
525c349dbc7Sjsg if (amdgpu_atom_parse_data_header(mode_info->atom_context,
526c349dbc7Sjsg index, &size, &frev, &crev, &data_offset)) {
527f005ef32Sjsg umc_info = (union umc_info *)(mode_info->atom_context->bios + data_offset);
5285ca02815Sjsg if (frev == 3) {
5295ca02815Sjsg switch (crev) {
5305ca02815Sjsg case 1:
5315ca02815Sjsg umc_config = le32_to_cpu(umc_info->v31.umc_config);
532c349dbc7Sjsg ecc_default_enabled =
5335ca02815Sjsg (umc_config & UMC_CONFIG__DEFAULT_MEM_ECC_ENABLE) ? true : false;
5345ca02815Sjsg break;
5355ca02815Sjsg case 2:
5365ca02815Sjsg umc_config = le32_to_cpu(umc_info->v32.umc_config);
5375ca02815Sjsg ecc_default_enabled =
5385ca02815Sjsg (umc_config & UMC_CONFIG__DEFAULT_MEM_ECC_ENABLE) ? true : false;
5395ca02815Sjsg break;
5405ca02815Sjsg case 3:
5415ca02815Sjsg umc_config = le32_to_cpu(umc_info->v33.umc_config);
5425ca02815Sjsg umc_config1 = le32_to_cpu(umc_info->v33.umc_config1);
5435ca02815Sjsg ecc_default_enabled =
5445ca02815Sjsg ((umc_config & UMC_CONFIG__DEFAULT_MEM_ECC_ENABLE) ||
5455ca02815Sjsg (umc_config1 & UMC_CONFIG1__ENABLE_ECC_CAPABLE)) ? true : false;
5465ca02815Sjsg break;
5475ca02815Sjsg default:
5485ca02815Sjsg /* unsupported crev */
5495ca02815Sjsg return false;
5505ca02815Sjsg }
551f005ef32Sjsg } else if (frev == 4) {
552f005ef32Sjsg switch (crev) {
553f005ef32Sjsg case 0:
554f005ef32Sjsg umc_config1 = le32_to_cpu(umc_info->v40.umc_config1);
555f005ef32Sjsg ecc_default_enabled =
556f005ef32Sjsg (umc_config1 & UMC_CONFIG1__ENABLE_ECC_CAPABLE) ? true : false;
557f005ef32Sjsg break;
558f005ef32Sjsg default:
559f005ef32Sjsg /* unsupported crev */
560f005ef32Sjsg return false;
561f005ef32Sjsg }
562f005ef32Sjsg } else {
563f005ef32Sjsg /* unsupported frev */
564f005ef32Sjsg return false;
565c349dbc7Sjsg }
566c349dbc7Sjsg }
567c349dbc7Sjsg
568c349dbc7Sjsg return ecc_default_enabled;
569c349dbc7Sjsg }
570c349dbc7Sjsg
571c349dbc7Sjsg /*
5725ca02815Sjsg * Helper function to query sram ecc capablity
5735ca02815Sjsg *
5745ca02815Sjsg * @adev: amdgpu_device pointer
5755ca02815Sjsg *
576c349dbc7Sjsg * Return true if vbios supports sram ecc or false if not
577c349dbc7Sjsg */
amdgpu_atomfirmware_sram_ecc_supported(struct amdgpu_device * adev)578c349dbc7Sjsg bool amdgpu_atomfirmware_sram_ecc_supported(struct amdgpu_device *adev)
579c349dbc7Sjsg {
5805ca02815Sjsg u32 fw_cap;
5815ca02815Sjsg
5825ca02815Sjsg fw_cap = adev->mode_info.firmware_flags;
5835ca02815Sjsg
5845ca02815Sjsg return (fw_cap & ATOM_FIRMWARE_CAP_SRAM_ECC) ? true : false;
5855ca02815Sjsg }
5865ca02815Sjsg
5875ca02815Sjsg /*
5885ca02815Sjsg * Helper function to query dynamic boot config capability
5895ca02815Sjsg *
5905ca02815Sjsg * @adev: amdgpu_device pointer
5915ca02815Sjsg *
5925ca02815Sjsg * Return true if vbios supports dynamic boot config or false if not
5935ca02815Sjsg */
amdgpu_atomfirmware_dynamic_boot_config_supported(struct amdgpu_device * adev)5945ca02815Sjsg bool amdgpu_atomfirmware_dynamic_boot_config_supported(struct amdgpu_device *adev)
5955ca02815Sjsg {
5965ca02815Sjsg u32 fw_cap;
5975ca02815Sjsg
5985ca02815Sjsg fw_cap = adev->mode_info.firmware_flags;
5995ca02815Sjsg
6005ca02815Sjsg return (fw_cap & ATOM_FIRMWARE_CAP_DYNAMIC_BOOT_CFG_ENABLE) ? true : false;
6015ca02815Sjsg }
6025ca02815Sjsg
6035ca02815Sjsg /**
6045ca02815Sjsg * amdgpu_atomfirmware_ras_rom_addr -- Get the RAS EEPROM addr from VBIOS
6051bb76ff1Sjsg * @adev: amdgpu_device pointer
6061bb76ff1Sjsg * @i2c_address: pointer to u8; if not NULL, will contain
6075ca02815Sjsg * the RAS EEPROM address if the function returns true
6085ca02815Sjsg *
6095ca02815Sjsg * Return true if VBIOS supports RAS EEPROM address reporting,
6105ca02815Sjsg * else return false. If true and @i2c_address is not NULL,
6115ca02815Sjsg * will contain the RAS ROM address.
6125ca02815Sjsg */
amdgpu_atomfirmware_ras_rom_addr(struct amdgpu_device * adev,u8 * i2c_address)6135ca02815Sjsg bool amdgpu_atomfirmware_ras_rom_addr(struct amdgpu_device *adev,
6145ca02815Sjsg u8 *i2c_address)
6155ca02815Sjsg {
616c349dbc7Sjsg struct amdgpu_mode_info *mode_info = &adev->mode_info;
617c349dbc7Sjsg int index;
618c349dbc7Sjsg u16 data_offset, size;
619c349dbc7Sjsg union firmware_info *firmware_info;
620c349dbc7Sjsg u8 frev, crev;
621c349dbc7Sjsg
622c349dbc7Sjsg index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
623c349dbc7Sjsg firmwareinfo);
624c349dbc7Sjsg
625c349dbc7Sjsg if (amdgpu_atom_parse_data_header(adev->mode_info.atom_context,
6265ca02815Sjsg index, &size, &frev, &crev,
6275ca02815Sjsg &data_offset)) {
6285ca02815Sjsg /* support firmware_info 3.4 + */
6295ca02815Sjsg if ((frev == 3 && crev >= 4) || (frev > 3)) {
630c349dbc7Sjsg firmware_info = (union firmware_info *)
631c349dbc7Sjsg (mode_info->atom_context->bios + data_offset);
6325ca02815Sjsg /* The ras_rom_i2c_slave_addr should ideally
6335ca02815Sjsg * be a 19-bit EEPROM address, which would be
6345ca02815Sjsg * used as is by the driver; see top of
6355ca02815Sjsg * amdgpu_eeprom.c.
6365ca02815Sjsg *
6375ca02815Sjsg * When this is the case, 0 is of course a
6385ca02815Sjsg * valid RAS EEPROM address, in which case,
6395ca02815Sjsg * we'll drop the first "if (firm...)" and only
6405ca02815Sjsg * leave the check for the pointer.
6415ca02815Sjsg *
6425ca02815Sjsg * The reason this works right now is because
6435ca02815Sjsg * ras_rom_i2c_slave_addr contains the EEPROM
6445ca02815Sjsg * device type qualifier 1010b in the top 4
6455ca02815Sjsg * bits.
6465ca02815Sjsg */
6475ca02815Sjsg if (firmware_info->v34.ras_rom_i2c_slave_addr) {
6485ca02815Sjsg if (i2c_address)
6495ca02815Sjsg *i2c_address = firmware_info->v34.ras_rom_i2c_slave_addr;
6505ca02815Sjsg return true;
6515ca02815Sjsg }
652c349dbc7Sjsg }
653c349dbc7Sjsg }
654c349dbc7Sjsg
6555ca02815Sjsg return false;
656c349dbc7Sjsg }
657c349dbc7Sjsg
6585ca02815Sjsg
659fb4d8502Sjsg union smu_info {
660fb4d8502Sjsg struct atom_smu_info_v3_1 v31;
6611bb76ff1Sjsg struct atom_smu_info_v4_0 v40;
6621bb76ff1Sjsg };
6631bb76ff1Sjsg
6641bb76ff1Sjsg union gfx_info {
6651bb76ff1Sjsg struct atom_gfx_info_v2_2 v22;
6661bb76ff1Sjsg struct atom_gfx_info_v2_4 v24;
6671bb76ff1Sjsg struct atom_gfx_info_v2_7 v27;
6681bb76ff1Sjsg struct atom_gfx_info_v3_0 v30;
669fb4d8502Sjsg };
670fb4d8502Sjsg
amdgpu_atomfirmware_get_clock_info(struct amdgpu_device * adev)671fb4d8502Sjsg int amdgpu_atomfirmware_get_clock_info(struct amdgpu_device *adev)
672fb4d8502Sjsg {
673fb4d8502Sjsg struct amdgpu_mode_info *mode_info = &adev->mode_info;
674fb4d8502Sjsg struct amdgpu_pll *spll = &adev->clock.spll;
675fb4d8502Sjsg struct amdgpu_pll *mpll = &adev->clock.mpll;
676fb4d8502Sjsg uint8_t frev, crev;
677fb4d8502Sjsg uint16_t data_offset;
678fb4d8502Sjsg int ret = -EINVAL, index;
679fb4d8502Sjsg
680fb4d8502Sjsg index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
681fb4d8502Sjsg firmwareinfo);
682fb4d8502Sjsg if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,
683fb4d8502Sjsg &frev, &crev, &data_offset)) {
684fb4d8502Sjsg union firmware_info *firmware_info =
685fb4d8502Sjsg (union firmware_info *)(mode_info->atom_context->bios +
686fb4d8502Sjsg data_offset);
687fb4d8502Sjsg
688fb4d8502Sjsg adev->clock.default_sclk =
689fb4d8502Sjsg le32_to_cpu(firmware_info->v31.bootup_sclk_in10khz);
690fb4d8502Sjsg adev->clock.default_mclk =
691fb4d8502Sjsg le32_to_cpu(firmware_info->v31.bootup_mclk_in10khz);
692fb4d8502Sjsg
693fb4d8502Sjsg adev->pm.current_sclk = adev->clock.default_sclk;
694fb4d8502Sjsg adev->pm.current_mclk = adev->clock.default_mclk;
695fb4d8502Sjsg
696fb4d8502Sjsg ret = 0;
697fb4d8502Sjsg }
698fb4d8502Sjsg
699fb4d8502Sjsg index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
700fb4d8502Sjsg smu_info);
701fb4d8502Sjsg if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,
702fb4d8502Sjsg &frev, &crev, &data_offset)) {
703fb4d8502Sjsg union smu_info *smu_info =
704fb4d8502Sjsg (union smu_info *)(mode_info->atom_context->bios +
705fb4d8502Sjsg data_offset);
706fb4d8502Sjsg
707fb4d8502Sjsg /* system clock */
7081bb76ff1Sjsg if (frev == 3)
709fb4d8502Sjsg spll->reference_freq = le32_to_cpu(smu_info->v31.core_refclk_10khz);
7101bb76ff1Sjsg else if (frev == 4)
7111bb76ff1Sjsg spll->reference_freq = le32_to_cpu(smu_info->v40.core_refclk_10khz);
712fb4d8502Sjsg
713fb4d8502Sjsg spll->reference_div = 0;
714fb4d8502Sjsg spll->min_post_div = 1;
715fb4d8502Sjsg spll->max_post_div = 1;
716fb4d8502Sjsg spll->min_ref_div = 2;
717fb4d8502Sjsg spll->max_ref_div = 0xff;
718fb4d8502Sjsg spll->min_feedback_div = 4;
719fb4d8502Sjsg spll->max_feedback_div = 0xff;
720fb4d8502Sjsg spll->best_vco = 0;
721fb4d8502Sjsg
722fb4d8502Sjsg ret = 0;
723fb4d8502Sjsg }
724fb4d8502Sjsg
725fb4d8502Sjsg index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
726fb4d8502Sjsg umc_info);
727fb4d8502Sjsg if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,
728fb4d8502Sjsg &frev, &crev, &data_offset)) {
729fb4d8502Sjsg union umc_info *umc_info =
730fb4d8502Sjsg (union umc_info *)(mode_info->atom_context->bios +
731fb4d8502Sjsg data_offset);
732fb4d8502Sjsg
733fb4d8502Sjsg /* memory clock */
734fb4d8502Sjsg mpll->reference_freq = le32_to_cpu(umc_info->v31.mem_refclk_10khz);
735fb4d8502Sjsg
736fb4d8502Sjsg mpll->reference_div = 0;
737fb4d8502Sjsg mpll->min_post_div = 1;
738fb4d8502Sjsg mpll->max_post_div = 1;
739fb4d8502Sjsg mpll->min_ref_div = 2;
740fb4d8502Sjsg mpll->max_ref_div = 0xff;
741fb4d8502Sjsg mpll->min_feedback_div = 4;
742fb4d8502Sjsg mpll->max_feedback_div = 0xff;
743fb4d8502Sjsg mpll->best_vco = 0;
744fb4d8502Sjsg
745fb4d8502Sjsg ret = 0;
746fb4d8502Sjsg }
747fb4d8502Sjsg
7485ca02815Sjsg /* if asic is Navi+, the rlc reference clock is used for system clock
7495ca02815Sjsg * from vbios gfx_info table */
7505ca02815Sjsg if (adev->asic_type >= CHIP_NAVI10) {
7515ca02815Sjsg index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
7525ca02815Sjsg gfx_info);
7535ca02815Sjsg if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,
7545ca02815Sjsg &frev, &crev, &data_offset)) {
7551bb76ff1Sjsg union gfx_info *gfx_info = (union gfx_info *)
7565ca02815Sjsg (mode_info->atom_context->bios + data_offset);
7571bb76ff1Sjsg if ((frev == 3) ||
7581bb76ff1Sjsg (frev == 2 && crev == 6)) {
7591bb76ff1Sjsg spll->reference_freq = le32_to_cpu(gfx_info->v30.golden_tsc_count_lower_refclk);
7605ca02815Sjsg ret = 0;
7611bb76ff1Sjsg } else if ((frev == 2) &&
7621bb76ff1Sjsg (crev >= 2) &&
7631bb76ff1Sjsg (crev != 6)) {
7641bb76ff1Sjsg spll->reference_freq = le32_to_cpu(gfx_info->v22.rlc_gpu_timer_refclk);
7651bb76ff1Sjsg ret = 0;
7661bb76ff1Sjsg } else {
7671bb76ff1Sjsg BUG();
7681bb76ff1Sjsg }
7695ca02815Sjsg }
7705ca02815Sjsg }
7715ca02815Sjsg
772fb4d8502Sjsg return ret;
773fb4d8502Sjsg }
774fb4d8502Sjsg
amdgpu_atomfirmware_get_gfx_info(struct amdgpu_device * adev)775fb4d8502Sjsg int amdgpu_atomfirmware_get_gfx_info(struct amdgpu_device *adev)
776fb4d8502Sjsg {
777fb4d8502Sjsg struct amdgpu_mode_info *mode_info = &adev->mode_info;
778fb4d8502Sjsg int index;
779fb4d8502Sjsg uint8_t frev, crev;
780fb4d8502Sjsg uint16_t data_offset;
781fb4d8502Sjsg
782fb4d8502Sjsg index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
783fb4d8502Sjsg gfx_info);
784fb4d8502Sjsg if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,
785fb4d8502Sjsg &frev, &crev, &data_offset)) {
786fb4d8502Sjsg union gfx_info *gfx_info = (union gfx_info *)
787fb4d8502Sjsg (mode_info->atom_context->bios + data_offset);
7881bb76ff1Sjsg if (frev == 2) {
789fb4d8502Sjsg switch (crev) {
790fb4d8502Sjsg case 4:
791c349dbc7Sjsg adev->gfx.config.max_shader_engines = gfx_info->v24.max_shader_engines;
792c349dbc7Sjsg adev->gfx.config.max_cu_per_sh = gfx_info->v24.max_cu_per_sh;
793c349dbc7Sjsg adev->gfx.config.max_sh_per_se = gfx_info->v24.max_sh_per_se;
794c349dbc7Sjsg adev->gfx.config.max_backends_per_se = gfx_info->v24.max_backends_per_se;
795c349dbc7Sjsg adev->gfx.config.max_texture_channel_caches = gfx_info->v24.max_texture_channel_caches;
796fb4d8502Sjsg adev->gfx.config.max_gprs = le16_to_cpu(gfx_info->v24.gc_num_gprs);
797fb4d8502Sjsg adev->gfx.config.max_gs_threads = gfx_info->v24.gc_num_max_gs_thds;
798fb4d8502Sjsg adev->gfx.config.gs_vgt_table_depth = gfx_info->v24.gc_gs_table_depth;
799fb4d8502Sjsg adev->gfx.config.gs_prim_buffer_depth =
800fb4d8502Sjsg le16_to_cpu(gfx_info->v24.gc_gsprim_buff_depth);
801fb4d8502Sjsg adev->gfx.config.double_offchip_lds_buf =
802fb4d8502Sjsg gfx_info->v24.gc_double_offchip_lds_buffer;
803fb4d8502Sjsg adev->gfx.cu_info.wave_front_size = le16_to_cpu(gfx_info->v24.gc_wave_size);
804fb4d8502Sjsg adev->gfx.cu_info.max_waves_per_simd = le16_to_cpu(gfx_info->v24.gc_max_waves_per_simd);
805fb4d8502Sjsg adev->gfx.cu_info.max_scratch_slots_per_cu = gfx_info->v24.gc_max_scratch_slots_per_cu;
806fb4d8502Sjsg adev->gfx.cu_info.lds_size = le16_to_cpu(gfx_info->v24.gc_lds_size);
807fb4d8502Sjsg return 0;
8085ca02815Sjsg case 7:
8095ca02815Sjsg adev->gfx.config.max_shader_engines = gfx_info->v27.max_shader_engines;
8105ca02815Sjsg adev->gfx.config.max_cu_per_sh = gfx_info->v27.max_cu_per_sh;
8115ca02815Sjsg adev->gfx.config.max_sh_per_se = gfx_info->v27.max_sh_per_se;
8125ca02815Sjsg adev->gfx.config.max_backends_per_se = gfx_info->v27.max_backends_per_se;
8135ca02815Sjsg adev->gfx.config.max_texture_channel_caches = gfx_info->v27.max_texture_channel_caches;
8145ca02815Sjsg adev->gfx.config.max_gprs = le16_to_cpu(gfx_info->v27.gc_num_gprs);
8155ca02815Sjsg adev->gfx.config.max_gs_threads = gfx_info->v27.gc_num_max_gs_thds;
8165ca02815Sjsg adev->gfx.config.gs_vgt_table_depth = gfx_info->v27.gc_gs_table_depth;
8175ca02815Sjsg adev->gfx.config.gs_prim_buffer_depth = le16_to_cpu(gfx_info->v27.gc_gsprim_buff_depth);
8185ca02815Sjsg adev->gfx.config.double_offchip_lds_buf = gfx_info->v27.gc_double_offchip_lds_buffer;
8195ca02815Sjsg adev->gfx.cu_info.wave_front_size = le16_to_cpu(gfx_info->v27.gc_wave_size);
8205ca02815Sjsg adev->gfx.cu_info.max_waves_per_simd = le16_to_cpu(gfx_info->v27.gc_max_waves_per_simd);
8215ca02815Sjsg adev->gfx.cu_info.max_scratch_slots_per_cu = gfx_info->v27.gc_max_scratch_slots_per_cu;
8225ca02815Sjsg adev->gfx.cu_info.lds_size = le16_to_cpu(gfx_info->v27.gc_lds_size);
8235ca02815Sjsg return 0;
824fb4d8502Sjsg default:
825fb4d8502Sjsg return -EINVAL;
826fb4d8502Sjsg }
8271bb76ff1Sjsg } else if (frev == 3) {
8281bb76ff1Sjsg switch (crev) {
8291bb76ff1Sjsg case 0:
8301bb76ff1Sjsg adev->gfx.config.max_shader_engines = gfx_info->v30.max_shader_engines;
8311bb76ff1Sjsg adev->gfx.config.max_cu_per_sh = gfx_info->v30.max_cu_per_sh;
8321bb76ff1Sjsg adev->gfx.config.max_sh_per_se = gfx_info->v30.max_sh_per_se;
8331bb76ff1Sjsg adev->gfx.config.max_backends_per_se = gfx_info->v30.max_backends_per_se;
8341bb76ff1Sjsg adev->gfx.config.max_texture_channel_caches = gfx_info->v30.max_texture_channel_caches;
8351bb76ff1Sjsg return 0;
8361bb76ff1Sjsg default:
8371bb76ff1Sjsg return -EINVAL;
8381bb76ff1Sjsg }
8391bb76ff1Sjsg } else {
8401bb76ff1Sjsg return -EINVAL;
8411bb76ff1Sjsg }
842fb4d8502Sjsg
843fb4d8502Sjsg }
844fb4d8502Sjsg return -EINVAL;
845fb4d8502Sjsg }
846c349dbc7Sjsg
847c349dbc7Sjsg /*
8485ca02815Sjsg * Helper function to query two stage mem training capability
8495ca02815Sjsg *
8505ca02815Sjsg * @adev: amdgpu_device pointer
8515ca02815Sjsg *
8525ca02815Sjsg * Return true if two stage mem training is supported or false if not
853c349dbc7Sjsg */
amdgpu_atomfirmware_mem_training_supported(struct amdgpu_device * adev)8545ca02815Sjsg bool amdgpu_atomfirmware_mem_training_supported(struct amdgpu_device *adev)
855c349dbc7Sjsg {
8565ca02815Sjsg u32 fw_cap;
857c349dbc7Sjsg
8585ca02815Sjsg fw_cap = adev->mode_info.firmware_flags;
859c349dbc7Sjsg
8605ca02815Sjsg return (fw_cap & ATOM_FIRMWARE_CAP_ENABLE_2STAGE_BIST_TRAINING) ? true : false;
861c349dbc7Sjsg }
862c349dbc7Sjsg
amdgpu_atomfirmware_get_fw_reserved_fb_size(struct amdgpu_device * adev)863ad8b1aafSjsg int amdgpu_atomfirmware_get_fw_reserved_fb_size(struct amdgpu_device *adev)
864c349dbc7Sjsg {
865c349dbc7Sjsg struct atom_context *ctx = adev->mode_info.atom_context;
866ad8b1aafSjsg union firmware_info *firmware_info;
867c349dbc7Sjsg int index;
868ad8b1aafSjsg u16 data_offset, size;
869ad8b1aafSjsg u8 frev, crev;
870ad8b1aafSjsg int fw_reserved_fb_size;
871c349dbc7Sjsg
872c349dbc7Sjsg index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
873ad8b1aafSjsg firmwareinfo);
874c349dbc7Sjsg
875ad8b1aafSjsg if (!amdgpu_atom_parse_data_header(ctx, index, &size,
876ad8b1aafSjsg &frev, &crev, &data_offset))
877ad8b1aafSjsg /* fail to parse data_header */
878c349dbc7Sjsg return 0;
879ad8b1aafSjsg
880ad8b1aafSjsg firmware_info = (union firmware_info *)(ctx->bios + data_offset);
881ad8b1aafSjsg
882ad8b1aafSjsg if (frev != 3)
883ad8b1aafSjsg return -EINVAL;
884ad8b1aafSjsg
885ad8b1aafSjsg switch (crev) {
886ad8b1aafSjsg case 4:
887ad8b1aafSjsg fw_reserved_fb_size =
888ad8b1aafSjsg (firmware_info->v34.fw_reserved_size_in_kb << 10);
889ad8b1aafSjsg break;
890ad8b1aafSjsg default:
891ad8b1aafSjsg fw_reserved_fb_size = 0;
892ad8b1aafSjsg break;
893ad8b1aafSjsg }
894ad8b1aafSjsg
895ad8b1aafSjsg return fw_reserved_fb_size;
896c349dbc7Sjsg }
8971bb76ff1Sjsg
8981bb76ff1Sjsg /*
8991bb76ff1Sjsg * Helper function to execute asic_init table
9001bb76ff1Sjsg *
9011bb76ff1Sjsg * @adev: amdgpu_device pointer
9021bb76ff1Sjsg * @fb_reset: flag to indicate whether fb is reset or not
9031bb76ff1Sjsg *
9041bb76ff1Sjsg * Return 0 if succeed, otherwise failed
9051bb76ff1Sjsg */
amdgpu_atomfirmware_asic_init(struct amdgpu_device * adev,bool fb_reset)9061bb76ff1Sjsg int amdgpu_atomfirmware_asic_init(struct amdgpu_device *adev, bool fb_reset)
9071bb76ff1Sjsg {
9081bb76ff1Sjsg struct amdgpu_mode_info *mode_info = &adev->mode_info;
9091bb76ff1Sjsg struct atom_context *ctx;
9101bb76ff1Sjsg uint8_t frev, crev;
9111bb76ff1Sjsg uint16_t data_offset;
9121bb76ff1Sjsg uint32_t bootup_sclk_in10khz, bootup_mclk_in10khz;
9131bb76ff1Sjsg struct asic_init_ps_allocation_v2_1 asic_init_ps_v2_1;
9141bb76ff1Sjsg int index;
9151bb76ff1Sjsg
9161bb76ff1Sjsg if (!mode_info)
9171bb76ff1Sjsg return -EINVAL;
9181bb76ff1Sjsg
9191bb76ff1Sjsg ctx = mode_info->atom_context;
9201bb76ff1Sjsg if (!ctx)
9211bb76ff1Sjsg return -EINVAL;
9221bb76ff1Sjsg
9231bb76ff1Sjsg /* query bootup sclk/mclk from firmware_info table */
9241bb76ff1Sjsg index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
9251bb76ff1Sjsg firmwareinfo);
9261bb76ff1Sjsg if (amdgpu_atom_parse_data_header(ctx, index, NULL,
9271bb76ff1Sjsg &frev, &crev, &data_offset)) {
9281bb76ff1Sjsg union firmware_info *firmware_info =
9291bb76ff1Sjsg (union firmware_info *)(ctx->bios +
9301bb76ff1Sjsg data_offset);
9311bb76ff1Sjsg
9321bb76ff1Sjsg bootup_sclk_in10khz =
9331bb76ff1Sjsg le32_to_cpu(firmware_info->v31.bootup_sclk_in10khz);
9341bb76ff1Sjsg bootup_mclk_in10khz =
9351bb76ff1Sjsg le32_to_cpu(firmware_info->v31.bootup_mclk_in10khz);
9361bb76ff1Sjsg } else {
9371bb76ff1Sjsg return -EINVAL;
9381bb76ff1Sjsg }
9391bb76ff1Sjsg
9401bb76ff1Sjsg index = get_index_into_master_table(atom_master_list_of_command_functions_v2_1,
9411bb76ff1Sjsg asic_init);
9421bb76ff1Sjsg if (amdgpu_atom_parse_cmd_header(mode_info->atom_context, index, &frev, &crev)) {
9431bb76ff1Sjsg if (frev == 2 && crev >= 1) {
9441bb76ff1Sjsg memset(&asic_init_ps_v2_1, 0, sizeof(asic_init_ps_v2_1));
9451bb76ff1Sjsg asic_init_ps_v2_1.param.engineparam.sclkfreqin10khz = bootup_sclk_in10khz;
9461bb76ff1Sjsg asic_init_ps_v2_1.param.memparam.mclkfreqin10khz = bootup_mclk_in10khz;
9471bb76ff1Sjsg asic_init_ps_v2_1.param.engineparam.engineflag = b3NORMAL_ENGINE_INIT;
9481bb76ff1Sjsg if (!fb_reset)
9491bb76ff1Sjsg asic_init_ps_v2_1.param.memparam.memflag = b3DRAM_SELF_REFRESH_EXIT;
9501bb76ff1Sjsg else
9511bb76ff1Sjsg asic_init_ps_v2_1.param.memparam.memflag = 0;
9521bb76ff1Sjsg } else {
9531bb76ff1Sjsg return -EINVAL;
9541bb76ff1Sjsg }
9551bb76ff1Sjsg } else {
9561bb76ff1Sjsg return -EINVAL;
9571bb76ff1Sjsg }
9581bb76ff1Sjsg
9591bb76ff1Sjsg return amdgpu_atom_execute_table(ctx, ATOM_CMD_INIT, (uint32_t *)&asic_init_ps_v2_1);
9601bb76ff1Sjsg }
961