drm/amdgpu: add cgs_get_firmware_info interface v2
This new interface can be used by IP components to retrieve the firmware information from the core driver. v2: fix one typo Signed-off-by: Jammy Zhou <Jammy.Zhou@amd.com> Signed-off-by: Rex Zhu <Rex.Zhou@amd.com> Signed-off-by: Young Yang <Young.Yang@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
57ff96cf47
commit
bf3911b06f
2 changed files with 167 additions and 1 deletions
|
@ -25,10 +25,13 @@
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
#include <drm/drmP.h>
|
#include <drm/drmP.h>
|
||||||
|
#include <linux/firmware.h>
|
||||||
#include <drm/amdgpu_drm.h>
|
#include <drm/amdgpu_drm.h>
|
||||||
#include "amdgpu.h"
|
#include "amdgpu.h"
|
||||||
#include "cgs_linux.h"
|
#include "cgs_linux.h"
|
||||||
#include "atom.h"
|
#include "atom.h"
|
||||||
|
#include "amdgpu_ucode.h"
|
||||||
|
|
||||||
|
|
||||||
struct amdgpu_cgs_device {
|
struct amdgpu_cgs_device {
|
||||||
struct cgs_device base;
|
struct cgs_device base;
|
||||||
|
@ -611,6 +614,122 @@ static int amdgpu_cgs_irq_put(void *cgs_device, unsigned src_id, unsigned type)
|
||||||
return amdgpu_irq_put(adev, adev->irq.sources[src_id], type);
|
return amdgpu_irq_put(adev, adev->irq.sources[src_id], type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t fw_type_convert(void *cgs_device, uint32_t fw_type)
|
||||||
|
{
|
||||||
|
CGS_FUNC_ADEV;
|
||||||
|
enum AMDGPU_UCODE_ID result = AMDGPU_UCODE_ID_MAXIMUM;
|
||||||
|
|
||||||
|
switch (fw_type) {
|
||||||
|
case CGS_UCODE_ID_SDMA0:
|
||||||
|
result = AMDGPU_UCODE_ID_SDMA0;
|
||||||
|
break;
|
||||||
|
case CGS_UCODE_ID_SDMA1:
|
||||||
|
result = AMDGPU_UCODE_ID_SDMA1;
|
||||||
|
break;
|
||||||
|
case CGS_UCODE_ID_CP_CE:
|
||||||
|
result = AMDGPU_UCODE_ID_CP_CE;
|
||||||
|
break;
|
||||||
|
case CGS_UCODE_ID_CP_PFP:
|
||||||
|
result = AMDGPU_UCODE_ID_CP_PFP;
|
||||||
|
break;
|
||||||
|
case CGS_UCODE_ID_CP_ME:
|
||||||
|
result = AMDGPU_UCODE_ID_CP_ME;
|
||||||
|
break;
|
||||||
|
case CGS_UCODE_ID_CP_MEC:
|
||||||
|
case CGS_UCODE_ID_CP_MEC_JT1:
|
||||||
|
result = AMDGPU_UCODE_ID_CP_MEC1;
|
||||||
|
break;
|
||||||
|
case CGS_UCODE_ID_CP_MEC_JT2:
|
||||||
|
if (adev->asic_type == CHIP_TONGA)
|
||||||
|
result = AMDGPU_UCODE_ID_CP_MEC2;
|
||||||
|
else if (adev->asic_type == CHIP_CARRIZO)
|
||||||
|
result = AMDGPU_UCODE_ID_CP_MEC1;
|
||||||
|
break;
|
||||||
|
case CGS_UCODE_ID_RLC_G:
|
||||||
|
result = AMDGPU_UCODE_ID_RLC_G;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
DRM_ERROR("Firmware type not supported\n");
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int amdgpu_cgs_get_firmware_info(void *cgs_device,
|
||||||
|
enum cgs_ucode_id type,
|
||||||
|
struct cgs_firmware_info *info)
|
||||||
|
{
|
||||||
|
CGS_FUNC_ADEV;
|
||||||
|
|
||||||
|
if (CGS_UCODE_ID_SMU != type) {
|
||||||
|
uint64_t gpu_addr;
|
||||||
|
uint32_t data_size;
|
||||||
|
const struct gfx_firmware_header_v1_0 *header;
|
||||||
|
enum AMDGPU_UCODE_ID id;
|
||||||
|
struct amdgpu_firmware_info *ucode;
|
||||||
|
|
||||||
|
id = fw_type_convert(cgs_device, type);
|
||||||
|
ucode = &adev->firmware.ucode[id];
|
||||||
|
if (ucode->fw == NULL)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
gpu_addr = ucode->mc_addr;
|
||||||
|
header = (const struct gfx_firmware_header_v1_0 *)ucode->fw->data;
|
||||||
|
data_size = le32_to_cpu(header->header.ucode_size_bytes);
|
||||||
|
|
||||||
|
if ((type == CGS_UCODE_ID_CP_MEC_JT1) ||
|
||||||
|
(type == CGS_UCODE_ID_CP_MEC_JT2)) {
|
||||||
|
gpu_addr += le32_to_cpu(header->jt_offset) << 2;
|
||||||
|
data_size = le32_to_cpu(header->jt_size) << 2;
|
||||||
|
}
|
||||||
|
info->mc_addr = gpu_addr;
|
||||||
|
info->image_size = data_size;
|
||||||
|
info->version = (uint16_t)le32_to_cpu(header->header.ucode_version);
|
||||||
|
info->feature_version = (uint16_t)le32_to_cpu(header->ucode_feature_version);
|
||||||
|
} else {
|
||||||
|
char fw_name[30] = {0};
|
||||||
|
int err = 0;
|
||||||
|
uint32_t ucode_size;
|
||||||
|
uint32_t ucode_start_address;
|
||||||
|
const uint8_t *src;
|
||||||
|
const struct smc_firmware_header_v1_0 *hdr;
|
||||||
|
|
||||||
|
switch (adev->asic_type) {
|
||||||
|
case CHIP_TONGA:
|
||||||
|
strcpy(fw_name, "amdgpu/tonga_smc.bin");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
DRM_ERROR("SMC firmware not supported\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = request_firmware(&adev->pm.fw, fw_name, adev->dev);
|
||||||
|
if (err) {
|
||||||
|
DRM_ERROR("Failed to request firmware\n");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = amdgpu_ucode_validate(adev->pm.fw);
|
||||||
|
if (err) {
|
||||||
|
DRM_ERROR("Failed to load firmware \"%s\"", fw_name);
|
||||||
|
release_firmware(adev->pm.fw);
|
||||||
|
adev->pm.fw = NULL;
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
hdr = (const struct smc_firmware_header_v1_0 *) adev->pm.fw->data;
|
||||||
|
adev->pm.fw_version = le32_to_cpu(hdr->header.ucode_version);
|
||||||
|
ucode_size = le32_to_cpu(hdr->header.ucode_size_bytes);
|
||||||
|
ucode_start_address = le32_to_cpu(hdr->ucode_start_addr);
|
||||||
|
src = (const uint8_t *)(adev->pm.fw->data +
|
||||||
|
le32_to_cpu(hdr->header.ucode_array_offset_bytes));
|
||||||
|
|
||||||
|
info->version = adev->pm.fw_version;
|
||||||
|
info->image_size = ucode_size;
|
||||||
|
info->kptr = (void *)src;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct cgs_ops amdgpu_cgs_ops = {
|
static const struct cgs_ops amdgpu_cgs_ops = {
|
||||||
amdgpu_cgs_gpu_mem_info,
|
amdgpu_cgs_gpu_mem_info,
|
||||||
amdgpu_cgs_gmap_kmem,
|
amdgpu_cgs_gmap_kmem,
|
||||||
|
@ -640,7 +759,8 @@ static const struct cgs_ops amdgpu_cgs_ops = {
|
||||||
amdgpu_cgs_pm_request_clock,
|
amdgpu_cgs_pm_request_clock,
|
||||||
amdgpu_cgs_pm_request_engine,
|
amdgpu_cgs_pm_request_engine,
|
||||||
amdgpu_cgs_pm_query_clock_limits,
|
amdgpu_cgs_pm_query_clock_limits,
|
||||||
amdgpu_cgs_set_camera_voltages
|
amdgpu_cgs_set_camera_voltages,
|
||||||
|
amdgpu_cgs_get_firmware_info
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct cgs_os_ops amdgpu_cgs_os_ops = {
|
static const struct cgs_os_ops amdgpu_cgs_os_ops = {
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#ifndef _CGS_COMMON_H
|
#ifndef _CGS_COMMON_H
|
||||||
#define _CGS_COMMON_H
|
#define _CGS_COMMON_H
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* enum cgs_gpu_mem_type - GPU memory types
|
* enum cgs_gpu_mem_type - GPU memory types
|
||||||
*/
|
*/
|
||||||
|
@ -85,6 +86,24 @@ enum cgs_voltage_planes {
|
||||||
/* ... */
|
/* ... */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* enum cgs_ucode_id - Firmware types for different IPs
|
||||||
|
*/
|
||||||
|
enum cgs_ucode_id {
|
||||||
|
CGS_UCODE_ID_SMU = 0,
|
||||||
|
CGS_UCODE_ID_SDMA0,
|
||||||
|
CGS_UCODE_ID_SDMA1,
|
||||||
|
CGS_UCODE_ID_CP_CE,
|
||||||
|
CGS_UCODE_ID_CP_PFP,
|
||||||
|
CGS_UCODE_ID_CP_ME,
|
||||||
|
CGS_UCODE_ID_CP_MEC,
|
||||||
|
CGS_UCODE_ID_CP_MEC_JT1,
|
||||||
|
CGS_UCODE_ID_CP_MEC_JT2,
|
||||||
|
CGS_UCODE_ID_GMCON_RENG,
|
||||||
|
CGS_UCODE_ID_RLC_G,
|
||||||
|
CGS_UCODE_ID_MAXIMUM,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct cgs_clock_limits - Clock limits
|
* struct cgs_clock_limits - Clock limits
|
||||||
*
|
*
|
||||||
|
@ -96,6 +115,17 @@ struct cgs_clock_limits {
|
||||||
unsigned sustainable; /**< Thermally sustainable frequency */
|
unsigned sustainable; /**< Thermally sustainable frequency */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct cgs_firmware_info - Firmware information
|
||||||
|
*/
|
||||||
|
struct cgs_firmware_info {
|
||||||
|
uint16_t version;
|
||||||
|
uint16_t feature_version;
|
||||||
|
uint32_t image_size;
|
||||||
|
uint64_t mc_addr;
|
||||||
|
void *kptr;
|
||||||
|
};
|
||||||
|
|
||||||
typedef unsigned long cgs_handle_t;
|
typedef unsigned long cgs_handle_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -442,6 +472,18 @@ typedef int (*cgs_pm_query_clock_limits_t)(void *cgs_device,
|
||||||
*/
|
*/
|
||||||
typedef int (*cgs_set_camera_voltages_t)(void *cgs_device, uint32_t mask,
|
typedef int (*cgs_set_camera_voltages_t)(void *cgs_device, uint32_t mask,
|
||||||
const uint32_t *voltages);
|
const uint32_t *voltages);
|
||||||
|
/**
|
||||||
|
* cgs_get_firmware_info - Get the firmware information from core driver
|
||||||
|
* @cgs_device: opaque device handle
|
||||||
|
* @type: the firmware type
|
||||||
|
* @info: returend firmware information
|
||||||
|
*
|
||||||
|
* Return: 0 on success, -errno otherwise
|
||||||
|
*/
|
||||||
|
typedef int (*cgs_get_firmware_info)(void *cgs_device,
|
||||||
|
enum cgs_ucode_id type,
|
||||||
|
struct cgs_firmware_info *info);
|
||||||
|
|
||||||
|
|
||||||
struct cgs_ops {
|
struct cgs_ops {
|
||||||
/* memory management calls (similar to KFD interface) */
|
/* memory management calls (similar to KFD interface) */
|
||||||
|
@ -478,6 +520,8 @@ struct cgs_ops {
|
||||||
cgs_pm_request_engine_t pm_request_engine;
|
cgs_pm_request_engine_t pm_request_engine;
|
||||||
cgs_pm_query_clock_limits_t pm_query_clock_limits;
|
cgs_pm_query_clock_limits_t pm_query_clock_limits;
|
||||||
cgs_set_camera_voltages_t set_camera_voltages;
|
cgs_set_camera_voltages_t set_camera_voltages;
|
||||||
|
/* Firmware Info */
|
||||||
|
cgs_get_firmware_info get_firmware_info;
|
||||||
/* ACPI (TODO) */
|
/* ACPI (TODO) */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -559,5 +603,7 @@ struct cgs_device
|
||||||
CGS_CALL(pm_query_clock_limits,dev,clock,limits)
|
CGS_CALL(pm_query_clock_limits,dev,clock,limits)
|
||||||
#define cgs_set_camera_voltages(dev,mask,voltages) \
|
#define cgs_set_camera_voltages(dev,mask,voltages) \
|
||||||
CGS_CALL(set_camera_voltages,dev,mask,voltages)
|
CGS_CALL(set_camera_voltages,dev,mask,voltages)
|
||||||
|
#define cgs_get_firmware_info(dev, type, info) \
|
||||||
|
CGS_CALL(get_firmware_info, dev, type, info)
|
||||||
|
|
||||||
#endif /* _CGS_COMMON_H */
|
#endif /* _CGS_COMMON_H */
|
||||||
|
|
Loading…
Add table
Reference in a new issue