Commit e20c9284 authored by AngeloGioacchino Del Regno's avatar AngeloGioacchino Del Regno Committed by Rob Clark

drm/msm/adreno: Add support for Adreno 510 GPU

The Adreno 510 GPU is a stripped version of the Adreno 5xx,
found in low-end SoCs like 8x56 and 8x76, which has 256K of
GMEM, with no GPMU nor ZAP.
Also, since the Adreno 5xx part of this driver seems to be
developed with high-end Adreno GPUs in mind, and since this
is a lower end one, add a comment making clear which GPUs
which support is not implemented yet is not using the GPMU
related hw init code, so that future developers will not go
crazy with that.

By the way, the lower end Adreno GPUs with no GPMU are:
A505/A506/A510 (usually no ZAP firmware)
A508/A509/A512 (usually with ZAP firmware)
Signed-off-by: default avatarAngeloGioacchino Del Regno <kholk11@gmail.com>
Signed-off-by: default avatarRob Clark <robdclark@chromium.org>
parent 3f3c8aff
...@@ -353,6 +353,9 @@ static int a5xx_me_init(struct msm_gpu *gpu) ...@@ -353,6 +353,9 @@ static int a5xx_me_init(struct msm_gpu *gpu)
* 2D mode 3 draw * 2D mode 3 draw
*/ */
OUT_RING(ring, 0x0000000B); OUT_RING(ring, 0x0000000B);
} else if (adreno_is_a510(adreno_gpu)) {
/* Workaround for token and syncs */
OUT_RING(ring, 0x00000001);
} else { } else {
/* No workarounds enabled */ /* No workarounds enabled */
OUT_RING(ring, 0x00000000); OUT_RING(ring, 0x00000000);
...@@ -568,15 +571,24 @@ static int a5xx_hw_init(struct msm_gpu *gpu) ...@@ -568,15 +571,24 @@ static int a5xx_hw_init(struct msm_gpu *gpu)
0x00100000 + adreno_gpu->gmem - 1); 0x00100000 + adreno_gpu->gmem - 1);
gpu_write(gpu, REG_A5XX_UCHE_GMEM_RANGE_MAX_HI, 0x00000000); gpu_write(gpu, REG_A5XX_UCHE_GMEM_RANGE_MAX_HI, 0x00000000);
gpu_write(gpu, REG_A5XX_CP_MEQ_THRESHOLDS, 0x40); if (adreno_is_a510(adreno_gpu)) {
if (adreno_is_a530(adreno_gpu)) gpu_write(gpu, REG_A5XX_CP_MEQ_THRESHOLDS, 0x20);
gpu_write(gpu, REG_A5XX_CP_MERCIU_SIZE, 0x40); gpu_write(gpu, REG_A5XX_CP_MERCIU_SIZE, 0x20);
if (adreno_is_a540(adreno_gpu)) gpu_write(gpu, REG_A5XX_CP_ROQ_THRESHOLDS_2, 0x40000030);
gpu_write(gpu, REG_A5XX_CP_MERCIU_SIZE, 0x400); gpu_write(gpu, REG_A5XX_CP_ROQ_THRESHOLDS_1, 0x20100D0A);
gpu_write(gpu, REG_A5XX_CP_ROQ_THRESHOLDS_2, 0x80000060); gpu_write(gpu, REG_A5XX_PC_DBG_ECO_CNTL,
gpu_write(gpu, REG_A5XX_CP_ROQ_THRESHOLDS_1, 0x40201B16); (0x200 << 11 | 0x200 << 22));
} else {
gpu_write(gpu, REG_A5XX_PC_DBG_ECO_CNTL, (0x400 << 11 | 0x300 << 22)); gpu_write(gpu, REG_A5XX_CP_MEQ_THRESHOLDS, 0x40);
if (adreno_is_a530(adreno_gpu))
gpu_write(gpu, REG_A5XX_CP_MERCIU_SIZE, 0x40);
if (adreno_is_a540(adreno_gpu))
gpu_write(gpu, REG_A5XX_CP_MERCIU_SIZE, 0x400);
gpu_write(gpu, REG_A5XX_CP_ROQ_THRESHOLDS_2, 0x80000060);
gpu_write(gpu, REG_A5XX_CP_ROQ_THRESHOLDS_1, 0x40201B16);
gpu_write(gpu, REG_A5XX_PC_DBG_ECO_CNTL,
(0x400 << 11 | 0x300 << 22));
}
if (adreno_gpu->info->quirks & ADRENO_QUIRK_TWO_PASS_USE_WFI) if (adreno_gpu->info->quirks & ADRENO_QUIRK_TWO_PASS_USE_WFI)
gpu_rmw(gpu, REG_A5XX_PC_DBG_ECO_CNTL, 0, (1 << 8)); gpu_rmw(gpu, REG_A5XX_PC_DBG_ECO_CNTL, 0, (1 << 8));
...@@ -589,6 +601,19 @@ static int a5xx_hw_init(struct msm_gpu *gpu) ...@@ -589,6 +601,19 @@ static int a5xx_hw_init(struct msm_gpu *gpu)
/* Enable ME/PFP split notification */ /* Enable ME/PFP split notification */
gpu_write(gpu, REG_A5XX_RBBM_AHB_CNTL1, 0xA6FFFFFF); gpu_write(gpu, REG_A5XX_RBBM_AHB_CNTL1, 0xA6FFFFFF);
/*
* In A5x, CCU can send context_done event of a particular context to
* UCHE which ultimately reaches CP even when there is valid
* transaction of that context inside CCU. This can let CP to program
* config registers, which will make the "valid transaction" inside
* CCU to be interpreted differently. This can cause gpu fault. This
* bug is fixed in latest A510 revision. To enable this bug fix -
* bit[11] of RB_DBG_ECO_CNTL need to be set to 0, default is 1
* (disable). For older A510 version this bit is unused.
*/
if (adreno_is_a510(adreno_gpu))
gpu_rmw(gpu, REG_A5XX_RB_DBG_ECO_CNTL, (1 << 11), 0);
/* Enable HWCG */ /* Enable HWCG */
a5xx_set_hwcg(gpu, true); a5xx_set_hwcg(gpu, true);
...@@ -635,7 +660,7 @@ static int a5xx_hw_init(struct msm_gpu *gpu) ...@@ -635,7 +660,7 @@ static int a5xx_hw_init(struct msm_gpu *gpu)
/* UCHE */ /* UCHE */
gpu_write(gpu, REG_A5XX_CP_PROTECT(16), ADRENO_PROTECT_RW(0xE80, 16)); gpu_write(gpu, REG_A5XX_CP_PROTECT(16), ADRENO_PROTECT_RW(0xE80, 16));
if (adreno_is_a530(adreno_gpu)) if (adreno_is_a530(adreno_gpu) || adreno_is_a510(adreno_gpu))
gpu_write(gpu, REG_A5XX_CP_PROTECT(17), gpu_write(gpu, REG_A5XX_CP_PROTECT(17),
ADRENO_PROTECT_RW(0x10000, 0x8000)); ADRENO_PROTECT_RW(0x10000, 0x8000));
...@@ -679,7 +704,8 @@ static int a5xx_hw_init(struct msm_gpu *gpu) ...@@ -679,7 +704,8 @@ static int a5xx_hw_init(struct msm_gpu *gpu)
a5xx_preempt_hw_init(gpu); a5xx_preempt_hw_init(gpu);
a5xx_gpmu_ucode_init(gpu); if (!adreno_is_a510(adreno_gpu))
a5xx_gpmu_ucode_init(gpu);
ret = a5xx_ucode_init(gpu); ret = a5xx_ucode_init(gpu);
if (ret) if (ret)
...@@ -712,7 +738,8 @@ static int a5xx_hw_init(struct msm_gpu *gpu) ...@@ -712,7 +738,8 @@ static int a5xx_hw_init(struct msm_gpu *gpu)
} }
/* /*
* Try to load a zap shader into the secure world. If successful * If the chip that we are using does support loading one, then
* try to load a zap shader into the secure world. If successful
* we can use the CP to switch out of secure mode. If not then we * we can use the CP to switch out of secure mode. If not then we
* have no resource but to try to switch ourselves out manually. If we * have no resource but to try to switch ourselves out manually. If we
* guessed wrong then access to the RBBM_SECVID_TRUST_CNTL register will * guessed wrong then access to the RBBM_SECVID_TRUST_CNTL register will
...@@ -1066,6 +1093,7 @@ static void a5xx_dump(struct msm_gpu *gpu) ...@@ -1066,6 +1093,7 @@ static void a5xx_dump(struct msm_gpu *gpu)
static int a5xx_pm_resume(struct msm_gpu *gpu) static int a5xx_pm_resume(struct msm_gpu *gpu)
{ {
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
int ret; int ret;
/* Turn on the core power */ /* Turn on the core power */
...@@ -1073,6 +1101,15 @@ static int a5xx_pm_resume(struct msm_gpu *gpu) ...@@ -1073,6 +1101,15 @@ static int a5xx_pm_resume(struct msm_gpu *gpu)
if (ret) if (ret)
return ret; return ret;
if (adreno_is_a510(adreno_gpu)) {
/* Halt the sp_input_clk at HM level */
gpu_write(gpu, REG_A5XX_RBBM_CLOCK_CNTL, 0x00000055);
a5xx_set_hwcg(gpu, true);
/* Turn on sp_input_clk at HM level */
gpu_rmw(gpu, REG_A5XX_RBBM_CLOCK_CNTL, 0xff, 0);
return 0;
}
/* Turn the RBCCU domain first to limit the chances of voltage droop */ /* Turn the RBCCU domain first to limit the chances of voltage droop */
gpu_write(gpu, REG_A5XX_GPMU_RBCCU_POWER_CNTL, 0x778000); gpu_write(gpu, REG_A5XX_GPMU_RBCCU_POWER_CNTL, 0x778000);
...@@ -1101,9 +1138,17 @@ static int a5xx_pm_resume(struct msm_gpu *gpu) ...@@ -1101,9 +1138,17 @@ static int a5xx_pm_resume(struct msm_gpu *gpu)
static int a5xx_pm_suspend(struct msm_gpu *gpu) static int a5xx_pm_suspend(struct msm_gpu *gpu)
{ {
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
u32 mask = 0xf;
/* A510 has 3 XIN ports in VBIF */
if (adreno_is_a510(adreno_gpu))
mask = 0x7;
/* Clear the VBIF pipe before shutting down */ /* Clear the VBIF pipe before shutting down */
gpu_write(gpu, REG_A5XX_VBIF_XIN_HALT_CTRL0, 0xF); gpu_write(gpu, REG_A5XX_VBIF_XIN_HALT_CTRL0, mask);
spin_until((gpu_read(gpu, REG_A5XX_VBIF_XIN_HALT_CTRL1) & 0xF) == 0xF); spin_until((gpu_read(gpu, REG_A5XX_VBIF_XIN_HALT_CTRL1) &
mask) == mask);
gpu_write(gpu, REG_A5XX_VBIF_XIN_HALT_CTRL0, 0); gpu_write(gpu, REG_A5XX_VBIF_XIN_HALT_CTRL0, 0);
......
...@@ -297,6 +297,10 @@ int a5xx_power_init(struct msm_gpu *gpu) ...@@ -297,6 +297,10 @@ int a5xx_power_init(struct msm_gpu *gpu)
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
int ret; int ret;
/* Not all A5xx chips have a GPMU */
if (adreno_is_a510(adreno_gpu))
return 0;
/* Set up the limits management */ /* Set up the limits management */
if (adreno_is_a530(adreno_gpu)) if (adreno_is_a530(adreno_gpu))
a530_lm_setup(gpu); a530_lm_setup(gpu);
...@@ -326,6 +330,9 @@ void a5xx_gpmu_ucode_init(struct msm_gpu *gpu) ...@@ -326,6 +330,9 @@ void a5xx_gpmu_ucode_init(struct msm_gpu *gpu)
unsigned int *data, *ptr, *cmds; unsigned int *data, *ptr, *cmds;
unsigned int cmds_size; unsigned int cmds_size;
if (adreno_is_a510(adreno_gpu))
return;
if (a5xx_gpu->gpmu_bo) if (a5xx_gpu->gpmu_bo)
return; return;
......
...@@ -114,6 +114,21 @@ static const struct adreno_info gpulist[] = { ...@@ -114,6 +114,21 @@ static const struct adreno_info gpulist[] = {
.gmem = (SZ_1M + SZ_512K), .gmem = (SZ_1M + SZ_512K),
.inactive_period = DRM_MSM_INACTIVE_PERIOD, .inactive_period = DRM_MSM_INACTIVE_PERIOD,
.init = a4xx_gpu_init, .init = a4xx_gpu_init,
}, {
.rev = ADRENO_REV(5, 1, 0, ANY_ID),
.revn = 510,
.name = "A510",
.fw = {
[ADRENO_FW_PM4] = "a530_pm4.fw",
[ADRENO_FW_PFP] = "a530_pfp.fw",
},
.gmem = SZ_256K,
/*
* Increase inactive period to 250 to avoid bouncing
* the GDSC which appears to make it grumpy
*/
.inactive_period = 250,
.init = a5xx_gpu_init,
}, { }, {
.rev = ADRENO_REV(5, 3, 0, 2), .rev = ADRENO_REV(5, 3, 0, 2),
.revn = 530, .revn = 530,
......
...@@ -212,6 +212,11 @@ static inline int adreno_is_a430(struct adreno_gpu *gpu) ...@@ -212,6 +212,11 @@ static inline int adreno_is_a430(struct adreno_gpu *gpu)
return gpu->revn == 430; return gpu->revn == 430;
} }
static inline int adreno_is_a510(struct adreno_gpu *gpu)
{
return gpu->revn == 510;
}
static inline int adreno_is_a530(struct adreno_gpu *gpu) static inline int adreno_is_a530(struct adreno_gpu *gpu)
{ {
return gpu->revn == 530; return gpu->revn == 530;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment