[Freedreno] [PATCH v3 05/10] drm/msm/a6xx: Add skeleton A7xx support
Dmitry Baryshkov
dmitry.baryshkov at linaro.org
Mon Sep 11 15:30:09 UTC 2023
On 23/08/2023 15:55, Konrad Dybcio wrote:
> A7xx GPUs are - from kernel's POV anyway - basically another generation
> of A6xx. They build upon the A650/A660_family advancements, skipping some
> writes (presumably more values are preset correctly on reset), adding
> some new ones and changing others.
>
> One notable difference is the introduction of a second shadow, called BV.
> To handle this with the current code, allocate it right after the current
> RPTR shadow.
>
> BV handling and .submit are mostly based on Jonathan Marek's work.
>
> All A7xx GPUs are assumed to have a GMU.
> A702 is not an A7xx-class GPU, it's a weird forked A610.
>
> Tested-by: Neil Armstrong <neil.armstrong at linaro.org> # on SM8550-QRD
> Tested-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org> # sm8450
> Signed-off-by: Konrad Dybcio <konrad.dybcio at linaro.org>
> ---
> drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 95 +++++--
> drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 451 ++++++++++++++++++++++++++++----
> drivers/gpu/drm/msm/adreno/adreno_gpu.c | 1 +
> drivers/gpu/drm/msm/adreno/adreno_gpu.h | 10 +-
> drivers/gpu/drm/msm/msm_ringbuffer.h | 2 +
> 5 files changed, 478 insertions(+), 81 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> index 03fa89bf3e4b..75984260898e 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> @@ -200,9 +200,10 @@ int a6xx_gmu_wait_for_idle(struct a6xx_gmu *gmu)
>
> static int a6xx_gmu_start(struct a6xx_gmu *gmu)
> {
> + struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu);
> + struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
> + u32 mask, reset_val, val;
> int ret;
> - u32 val;
> - u32 mask, reset_val;
>
> val = gmu_read(gmu, REG_A6XX_GMU_CM3_DTCM_START + 0xff8);
> if (val <= 0x20010004) {
> @@ -218,7 +219,11 @@ static int a6xx_gmu_start(struct a6xx_gmu *gmu)
> /* Set the log wptr index
> * note: downstream saves the value in poweroff and restores it here
> */
> - gmu_write(gmu, REG_A6XX_GPU_GMU_CX_GMU_PWR_COL_CP_RESP, 0);
> + if (adreno_is_a7xx(adreno_gpu))
> + gmu_write(gmu, REG_A6XX_GMU_GENERAL_9, 0);
> + else
> + gmu_write(gmu, REG_A6XX_GPU_GMU_CX_GMU_PWR_COL_CP_RESP, 0);
> +
>
> gmu_write(gmu, REG_A6XX_GMU_CM3_SYSRESET, 0);
>
> @@ -518,7 +523,9 @@ static void a6xx_gmu_rpmh_init(struct a6xx_gmu *gmu)
> if (IS_ERR(pdcptr))
> goto err;
>
> - if (adreno_is_a650(adreno_gpu) || adreno_is_a660_family(adreno_gpu))
> + if (adreno_is_a650(adreno_gpu) ||
> + adreno_is_a660_family(adreno_gpu) ||
> + adreno_is_a7xx(adreno_gpu))
> pdc_in_aop = true;
> else if (adreno_is_a618(adreno_gpu) || adreno_is_a640_family(adreno_gpu))
> pdc_address_offset = 0x30090;
> @@ -550,7 +557,8 @@ static void a6xx_gmu_rpmh_init(struct a6xx_gmu *gmu)
> gmu_write_rscc(gmu, REG_A6XX_RSCC_PDC_MATCH_VALUE_HI, 0x4514);
>
> /* Load RSC sequencer uCode for sleep and wakeup */
> - if (adreno_is_a650_family(adreno_gpu)) {
> + if (adreno_is_a650_family(adreno_gpu) ||
> + adreno_is_a7xx(adreno_gpu)) {
> gmu_write_rscc(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0, 0xeaaae5a0);
> gmu_write_rscc(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0 + 1, 0xe1a1ebab);
> gmu_write_rscc(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0 + 2, 0xa2e0a581);
> @@ -635,11 +643,18 @@ static void a6xx_gmu_rpmh_init(struct a6xx_gmu *gmu)
> /* Set up the idle state for the GMU */
> static void a6xx_gmu_power_config(struct a6xx_gmu *gmu)
> {
> + struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu);
> + struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
> +
> /* Disable GMU WB/RB buffer */
> gmu_write(gmu, REG_A6XX_GMU_SYS_BUS_CONFIG, 0x1);
> gmu_write(gmu, REG_A6XX_GMU_ICACHE_CONFIG, 0x1);
> gmu_write(gmu, REG_A6XX_GMU_DCACHE_CONFIG, 0x1);
>
> + /* A7xx knows better by default! */
> + if (adreno_is_a7xx(adreno_gpu))
> + return;
> +
> gmu_write(gmu, REG_A6XX_GMU_PWR_COL_INTER_FRAME_CTRL, 0x9c40400);
>
> switch (gmu->idle_level) {
> @@ -702,7 +717,7 @@ static int a6xx_gmu_fw_load(struct a6xx_gmu *gmu)
> u32 itcm_base = 0x00000000;
> u32 dtcm_base = 0x00040000;
>
> - if (adreno_is_a650_family(adreno_gpu))
> + if (adreno_is_a650_family(adreno_gpu) || adreno_is_a7xx(adreno_gpu))
> dtcm_base = 0x10004000;
>
> if (gmu->legacy) {
> @@ -751,14 +766,22 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state)
> {
> struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu);
> struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
> + u32 fence_range_lower, fence_range_upper;
> int ret;
> u32 chipid;
>
> - if (adreno_is_a650_family(adreno_gpu)) {
> + /* Vote veto for FAL10 */
> + if (adreno_is_a650_family(adreno_gpu) || adreno_is_a7xx(adreno_gpu)) {
> gmu_write(gmu, REG_A6XX_GPU_GMU_CX_GMU_CX_FALNEXT_INTF, 1);
> gmu_write(gmu, REG_A6XX_GPU_GMU_CX_GMU_CX_FAL_INTF, 1);
> }
>
> + /* Turn on TCM (Tightly Coupled Memory) retention */
> + if (adreno_is_a7xx(adreno_gpu))
> + a6xx_llc_write(a6xx_gpu, REG_A7XX_CX_MISC_TCM_RET_CNTL, 1);
> + else
> + gmu_write(gmu, REG_A6XX_GMU_GENERAL_7, 1);
> +
> if (state == GMU_WARM_BOOT) {
> ret = a6xx_rpmh_start(gmu);
> if (ret)
> @@ -768,9 +791,6 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state)
> "GMU firmware is not loaded\n"))
> return -ENOENT;
>
> - /* Turn on register retention */
> - gmu_write(gmu, REG_A6XX_GMU_GENERAL_7, 1);
> -
> ret = a6xx_rpmh_start(gmu);
> if (ret)
> return ret;
> @@ -780,6 +800,7 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state)
> return ret;
> }
>
> + /* Clear init result to make sure we are getting a fresh value */
> gmu_write(gmu, REG_A6XX_GMU_CM3_FW_INIT_RESULT, 0);
> gmu_write(gmu, REG_A6XX_GMU_CM3_BOOT_CONFIG, 0x02);
>
> @@ -787,8 +808,18 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state)
> gmu_write(gmu, REG_A6XX_GMU_HFI_QTBL_ADDR, gmu->hfi.iova);
> gmu_write(gmu, REG_A6XX_GMU_HFI_QTBL_INFO, 1);
>
> + if (adreno_is_a7xx(adreno_gpu)) {
> + fence_range_upper = 0x32;
> + fence_range_lower = 0x8a0;
> + } else {
> + fence_range_upper = 0xa;
> + fence_range_lower = 0xa0;
> + }
> +
> gmu_write(gmu, REG_A6XX_GMU_AHB_FENCE_RANGE_0,
> - (1 << 31) | (0xa << 18) | (0xa0));
> + BIT(31) |
> + FIELD_PREP(GENMASK(30, 18), fence_range_upper) |
> + FIELD_PREP(GENMASK(17, 0), fence_range_lower));
This fails on arm32 because of the missing #include <linux/bitfields.h>
>
> /*
> * Snapshots toggle the NMI bit which will result in a jump to the NMI
--
With best wishes
Dmitry
More information about the Freedreno
mailing list