drm/msm/adreno: Define a list of firmware files to load per target

The number and type of firmware files required differs for each
target. Instead of using a fixed struct member for each possible
firmware file use a generic list of files that should be loaded
on boot.  Use some semi-target specific enums to help each target
find the appropriate firmware(s) that it needs to load.

Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
This commit is contained in:
Jordan Crouse 2018-02-01 12:15:16 -07:00 committed by Rob Clark
parent f306953fdb
commit c5e3548c29
8 changed files with 80 additions and 72 deletions

View file

@ -256,8 +256,8 @@ static int a3xx_hw_init(struct msm_gpu *gpu)
*/
/* Load PM4: */
ptr = (uint32_t *)(adreno_gpu->pm4->data);
len = adreno_gpu->pm4->size / 4;
ptr = (uint32_t *)(adreno_gpu->fw[ADRENO_FW_PM4]->data);
len = adreno_gpu->fw[ADRENO_FW_PM4]->size / 4;
DBG("loading PM4 ucode version: %x", ptr[1]);
gpu_write(gpu, REG_AXXX_CP_DEBUG,
@ -268,8 +268,8 @@ static int a3xx_hw_init(struct msm_gpu *gpu)
gpu_write(gpu, REG_AXXX_CP_ME_RAM_DATA, ptr[i]);
/* Load PFP: */
ptr = (uint32_t *)(adreno_gpu->pfp->data);
len = adreno_gpu->pfp->size / 4;
ptr = (uint32_t *)(adreno_gpu->fw[ADRENO_FW_PFP]->data);
len = adreno_gpu->fw[ADRENO_FW_PFP]->size / 4;
DBG("loading PFP ucode version: %x", ptr[5]);
gpu_write(gpu, REG_A3XX_CP_PFP_UCODE_ADDR, 0);

View file

@ -274,16 +274,16 @@ static int a4xx_hw_init(struct msm_gpu *gpu)
return ret;
/* Load PM4: */
ptr = (uint32_t *)(adreno_gpu->pm4->data);
len = adreno_gpu->pm4->size / 4;
ptr = (uint32_t *)(adreno_gpu->fw[ADRENO_FW_PM4]->data);
len = adreno_gpu->fw[ADRENO_FW_PM4]->size / 4;
DBG("loading PM4 ucode version: %u", ptr[0]);
gpu_write(gpu, REG_A4XX_CP_ME_RAM_WADDR, 0);
for (i = 1; i < len; i++)
gpu_write(gpu, REG_A4XX_CP_ME_RAM_DATA, ptr[i]);
/* Load PFP: */
ptr = (uint32_t *)(adreno_gpu->pfp->data);
len = adreno_gpu->pfp->size / 4;
ptr = (uint32_t *)(adreno_gpu->fw[ADRENO_FW_PFP]->data);
len = adreno_gpu->fw[ADRENO_FW_PFP]->size / 4;
DBG("loading PFP ucode version: %u", ptr[0]);
gpu_write(gpu, REG_A4XX_CP_PFP_UCODE_ADDR, 0);

View file

@ -123,15 +123,12 @@ reset_set(void *data, u64 val)
mutex_lock(&dev->struct_mutex);
if (adreno_gpu->pm4) {
release_firmware(adreno_gpu->pm4);
adreno_gpu->pm4 = NULL;
}
release_firmware(adreno_gpu->fw[ADRENO_FW_PM4]);
adreno_gpu->fw[ADRENO_FW_PM4] = NULL;
release_firmware(adreno_gpu->fw[ADRENO_FW_PFP]);
adreno_gpu->fw[ADRENO_FW_PFP] = NULL;
if (adreno_gpu->pfp) {
release_firmware(adreno_gpu->pfp);
adreno_gpu->pfp = NULL;
}
if (a5xx_gpu->pm4_bo) {
if (a5xx_gpu->pm4_iova)
msm_gem_put_iova(a5xx_gpu->pm4_bo, gpu->aspace);

View file

@ -523,8 +523,8 @@ static int a5xx_ucode_init(struct msm_gpu *gpu)
int ret;
if (!a5xx_gpu->pm4_bo) {
a5xx_gpu->pm4_bo = a5xx_ucode_load_bo(gpu, adreno_gpu->pm4,
&a5xx_gpu->pm4_iova);
a5xx_gpu->pm4_bo = a5xx_ucode_load_bo(gpu,
adreno_gpu->fw[ADRENO_FW_PM4], &a5xx_gpu->pm4_iova);
if (IS_ERR(a5xx_gpu->pm4_bo)) {
ret = PTR_ERR(a5xx_gpu->pm4_bo);
@ -536,8 +536,8 @@ static int a5xx_ucode_init(struct msm_gpu *gpu)
}
if (!a5xx_gpu->pfp_bo) {
a5xx_gpu->pfp_bo = a5xx_ucode_load_bo(gpu, adreno_gpu->pfp,
&a5xx_gpu->pfp_iova);
a5xx_gpu->pfp_bo = a5xx_ucode_load_bo(gpu,
adreno_gpu->fw[ADRENO_FW_PFP], &a5xx_gpu->pfp_iova);
if (IS_ERR(a5xx_gpu->pfp_bo)) {
ret = PTR_ERR(a5xx_gpu->pfp_bo);

View file

@ -261,7 +261,6 @@ void a5xx_gpmu_ucode_init(struct msm_gpu *gpu)
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu);
struct drm_device *drm = gpu->dev;
const struct firmware *fw;
uint32_t dwords = 0, offset = 0, bosize;
unsigned int *data, *ptr, *cmds;
unsigned int cmds_size;
@ -269,15 +268,7 @@ void a5xx_gpmu_ucode_init(struct msm_gpu *gpu)
if (a5xx_gpu->gpmu_bo)
return;
/* Get the firmware */
fw = adreno_request_fw(adreno_gpu, adreno_gpu->info->powerfw);
if (IS_ERR(fw)) {
DRM_ERROR("%s: Could not get GPMU firmware. GPMU will not be active\n",
gpu->name);
return;
}
data = (unsigned int *) fw->data;
data = (unsigned int *) adreno_gpu->fw[ADRENO_FW_GPMU]->data;
/*
* The first dword is the size of the remaining data in dwords. Use it
@ -285,12 +276,14 @@ void a5xx_gpmu_ucode_init(struct msm_gpu *gpu)
* the firmware that we read
*/
if (fw->size < 8 || (data[0] < 2) || (data[0] >= (fw->size >> 2)))
goto out;
if (adreno_gpu->fw[ADRENO_FW_GPMU]->size < 8 ||
(data[0] < 2) || (data[0] >=
(adreno_gpu->fw[ADRENO_FW_GPMU]->size >> 2)))
return;
/* The second dword is an ID - look for 2 (GPMU_FIRMWARE_ID) */
if (data[1] != 2)
goto out;
return;
cmds = data + data[2] + 3;
cmds_size = data[0] - data[2] - 2;
@ -325,8 +318,7 @@ void a5xx_gpmu_ucode_init(struct msm_gpu *gpu)
msm_gem_put_vaddr(a5xx_gpu->gpmu_bo);
a5xx_gpu->gpmu_dwords = dwords;
goto out;
return;
err:
if (a5xx_gpu->gpmu_iova)
msm_gem_put_iova(a5xx_gpu->gpmu_bo, gpu->aspace);
@ -336,8 +328,4 @@ void a5xx_gpmu_ucode_init(struct msm_gpu *gpu)
a5xx_gpu->gpmu_bo = NULL;
a5xx_gpu->gpmu_iova = 0;
a5xx_gpu->gpmu_dwords = 0;
out:
/* No need to keep that firmware laying around anymore */
release_firmware(fw);
}

View file

@ -30,61 +30,75 @@ static const struct adreno_info gpulist[] = {
.rev = ADRENO_REV(3, 0, 5, ANY_ID),
.revn = 305,
.name = "A305",
.pm4fw = "a300_pm4.fw",
.pfpfw = "a300_pfp.fw",
.fw = {
[ADRENO_FW_PM4] = "a300_pm4.fw",
[ADRENO_FW_PFP] = "a300_pfp.fw",
},
.gmem = SZ_256K,
.init = a3xx_gpu_init,
}, {
.rev = ADRENO_REV(3, 0, 6, 0),
.revn = 307, /* because a305c is revn==306 */
.name = "A306",
.pm4fw = "a300_pm4.fw",
.pfpfw = "a300_pfp.fw",
.fw = {
[ADRENO_FW_PM4] = "a300_pm4.fw",
[ADRENO_FW_PFP] = "a300_pfp.fw",
},
.gmem = SZ_128K,
.init = a3xx_gpu_init,
}, {
.rev = ADRENO_REV(3, 2, ANY_ID, ANY_ID),
.revn = 320,
.name = "A320",
.pm4fw = "a300_pm4.fw",
.pfpfw = "a300_pfp.fw",
.fw = {
[ADRENO_FW_PM4] = "a300_pm4.fw",
[ADRENO_FW_PFP] = "a300_pfp.fw",
},
.gmem = SZ_512K,
.init = a3xx_gpu_init,
}, {
.rev = ADRENO_REV(3, 3, 0, ANY_ID),
.revn = 330,
.name = "A330",
.pm4fw = "a330_pm4.fw",
.pfpfw = "a330_pfp.fw",
.fw = {
[ADRENO_FW_PM4] = "a330_pm4.fw",
[ADRENO_FW_PFP] = "a330_pfp.fw",
},
.gmem = SZ_1M,
.init = a3xx_gpu_init,
}, {
.rev = ADRENO_REV(4, 2, 0, ANY_ID),
.revn = 420,
.name = "A420",
.pm4fw = "a420_pm4.fw",
.pfpfw = "a420_pfp.fw",
.fw = {
[ADRENO_FW_PM4] = "a420_pm4.fw",
[ADRENO_FW_PFP] = "a420_pfp.fw",
},
.gmem = (SZ_1M + SZ_512K),
.init = a4xx_gpu_init,
}, {
.rev = ADRENO_REV(4, 3, 0, ANY_ID),
.revn = 430,
.name = "A430",
.pm4fw = "a420_pm4.fw",
.pfpfw = "a420_pfp.fw",
.fw = {
[ADRENO_FW_PM4] = "a420_pm4.fw",
[ADRENO_FW_PFP] = "a420_pfp.fw",
},
.gmem = (SZ_1M + SZ_512K),
.init = a4xx_gpu_init,
}, {
.rev = ADRENO_REV(5, 3, 0, 2),
.revn = 530,
.name = "A530",
.pm4fw = "a530_pm4.fw",
.pfpfw = "a530_pfp.fw",
.fw = {
[ADRENO_FW_PM4] = "a530_pm4.fw",
[ADRENO_FW_PFP] = "a530_pfp.fw",
[ADRENO_FW_GPMU] = "a530v3_gpmu.fw2",
},
.gmem = SZ_1M,
.quirks = ADRENO_QUIRK_TWO_PASS_USE_WFI |
ADRENO_QUIRK_FAULT_DETECT_MASK,
.init = a5xx_gpu_init,
.powerfw = "a530v3_gpmu.fw2",
.zapfw = "a530_zap.mdt",
},
};

View file

@ -140,23 +140,24 @@ adreno_request_fw(struct adreno_gpu *adreno_gpu, const char *fwname)
static int adreno_load_fw(struct adreno_gpu *adreno_gpu)
{
const struct firmware *fw;
int i;
if (adreno_gpu->pm4)
return 0;
for (i = 0; i < ARRAY_SIZE(adreno_gpu->info->fw); i++) {
const struct firmware *fw;
fw = adreno_request_fw(adreno_gpu, adreno_gpu->info->pm4fw);
if (IS_ERR(fw))
return PTR_ERR(fw);
adreno_gpu->pm4 = fw;
if (!adreno_gpu->info->fw[i])
continue;
fw = adreno_request_fw(adreno_gpu, adreno_gpu->info->pfpfw);
if (IS_ERR(fw)) {
release_firmware(adreno_gpu->pm4);
adreno_gpu->pm4 = NULL;
return PTR_ERR(fw);
/* Skip if the firmware has already been loaded */
if (adreno_gpu->fw[i])
continue;
fw = adreno_request_fw(adreno_gpu, adreno_gpu->info->fw[i]);
if (IS_ERR(fw))
return PTR_ERR(fw);
adreno_gpu->fw[i] = fw;
}
adreno_gpu->pfp = fw;
return 0;
}
@ -569,8 +570,10 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
void adreno_gpu_cleanup(struct adreno_gpu *adreno_gpu)
{
release_firmware(adreno_gpu->pm4);
release_firmware(adreno_gpu->pfp);
unsigned int i;
for (i = 0; i < ARRAY_SIZE(adreno_gpu->info->fw); i++)
release_firmware(adreno_gpu->fw[i]);
msm_gpu_cleanup(&adreno_gpu->base);
}

View file

@ -48,6 +48,13 @@ enum adreno_regs {
REG_ADRENO_REGISTER_MAX,
};
enum {
ADRENO_FW_PM4 = 0,
ADRENO_FW_PFP = 1,
ADRENO_FW_GPMU = 2,
ADRENO_FW_MAX,
};
enum adreno_quirks {
ADRENO_QUIRK_TWO_PASS_USE_WFI = 1,
ADRENO_QUIRK_FAULT_DETECT_MASK = 2,
@ -72,8 +79,7 @@ struct adreno_info {
struct adreno_rev rev;
uint32_t revn;
const char *name;
const char *pm4fw, *pfpfw;
const char *powerfw;
const char *fw[ADRENO_FW_MAX];
uint32_t gmem;
enum adreno_quirks quirks;
struct msm_gpu *(*init)(struct drm_device *dev);
@ -115,7 +121,7 @@ struct adreno_gpu {
} fwloc;
/* firmware: */
const struct firmware *pm4, *pfp;
const struct firmware *fw[ADRENO_FW_MAX];
/*
* Register offsets are different between some GPUs.