From: Konrad Dybcio <[email protected]> IFPC is largely supported by the current upstream driver, add the missing plumbing that's specific to A6xx, based on kgsl.
Signed-off-by: Konrad Dybcio <[email protected]> --- drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 97 +++++++++++++++++++++-- drivers/gpu/drm/msm/adreno/a6xx_hfi.c | 11 ++- drivers/gpu/drm/msm/registers/adreno/a6xx_gmu.xml | 1 + 3 files changed, 98 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index e7c3da5d3ac6..8ea9ab5b9886 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -647,6 +647,7 @@ static void a6xx_set_hwcg(struct msm_gpu *gpu, bool state) unsigned int i; u32 cgc_delay, cgc_hyst; u32 val, clock_cntl_on; + u32 gmu_wfi_config; if (!(adreno_gpu->info->a6xx->hwcg || adreno_is_a7xx(adreno_gpu))) return; @@ -674,12 +675,20 @@ static void a6xx_set_hwcg(struct msm_gpu *gpu, bool state) else cgc_hyst = 0x5555; + /* TODO: Also A620 */ + if (adreno_is_a640(adreno_gpu) || adreno_is_a650(adreno_gpu)) + gmu_wfi_config = 0x2; + else + gmu_wfi_config = 0; + gmu_write(&a6xx_gpu->gmu, REG_A6XX_GPU_GMU_AO_GMU_CGC_MODE_CNTL, state ? adreno_gpu->info->a6xx->gmu_cgc_mode : 0); gmu_write(&a6xx_gpu->gmu, REG_A6XX_GPU_GMU_AO_GMU_CGC_DELAY_CNTL, state ? cgc_delay : 0); gmu_write(&a6xx_gpu->gmu, REG_A6XX_GPU_GMU_AO_GMU_CGC_HYST_CNTL, state ? cgc_hyst : 0); + gmu_write(&a6xx_gpu->gmu, REG_A6XX_GMU_CX_GMU_WFI_CONFIG, + state ? gmu_wfi_config : 0); if (!adreno_gpu->info->a6xx->hwcg) { gpu_write(gpu, REG_A7XX_RBBM_CLOCK_CNTL_GLOBAL, 1); @@ -878,6 +887,43 @@ static void a7xx_patch_pwrup_reglist(struct msm_gpu *gpu) a6xx_gpu->dynamic_sel_reglist_offset = dyn_pwrup_reglist_count; } +static void a6xx_patch_pwrup_reglist(struct msm_gpu *gpu) +{ + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); + const struct adreno_reglist_list *reglist; + void *ptr = a6xx_gpu->pwrup_reglist_ptr; + struct cpu_gpu_lock *lock = ptr; + u32 *dest = (u32 *)&lock->regs[0]; + int i; + + lock->gpu_req = lock->cpu_req = lock->turn = 0; + lock->list_length = 0; + + /* Static IFPC-only registers */ + reglist = adreno_gpu->info->a6xx->ifpc_reglist; + if (reglist) { + for (i = 0; i < reglist->count; i++) { + *dest++ = reglist->regs[i]; + *dest++ = gpu_read(gpu, reglist->regs[i]); + } + lock->list_length += reglist->count * 2; + } + + /* The CP sees IFPC-only and IFPC + preemption as one list from list_offset */ + lock->list_offset = lock->list_length; + + /* Static IFPC + preemption registers */ + reglist = adreno_gpu->info->a6xx->pwrup_reglist; + if (reglist) { + for (i = 0; i < reglist->count; i++) { + *dest++ = reglist->regs[i]; + *dest++ = gpu_read(gpu, reglist->regs[i]); + } + lock->list_length += reglist->count * 2; + } +} + static int a7xx_preempt_start(struct msm_gpu *gpu) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); @@ -898,13 +944,43 @@ static int a7xx_preempt_start(struct msm_gpu *gpu) return a6xx_idle(gpu, ring) ? 0 : -EINVAL; } +/* Select whether multiple hardware contexts can run at once or are serialized */ +#define CP_INIT_MAX_CONTEXT BIT(0) +/* Enable register protection mode */ +#define CP_INIT_ERROR_DETECTION_CONTROL BIT(1) +/* Header dump information, reserved */ +#define CP_INIT_HEADER_DUMP BIT(2) +/* Default Reset states enabled for PFP and ME */ +#define CP_INIT_DEFAULT_RESET_STATE BIT(3) +/* Drawcall filter range */ +#define CP_INIT_DRAWCALL_FILTER_RANGE BIT(4) +/* Ucode workaround masks */ +#define CP_INIT_UCODE_WORKAROUND_MASK BIT(5) +/* Disable the save/restore of performance counters across preemption. */ +#define CP_INIT_OPERATION_MODE_MASK BIT(6) +/* Register initialization list */ +#define CP_INIT_REGISTER_INIT_LIST BIT(7) +/* Register initialization list with spinlock */ +#define CP_INIT_REGISTER_INIT_LIST_WITH_SPINLOCK BIT(8) + +#define CP_INIT_MASK (CP_INIT_MAX_CONTEXT | \ + CP_INIT_ERROR_DETECTION_CONTROL | \ + CP_INIT_HEADER_DUMP | \ + CP_INIT_DEFAULT_RESET_STATE | \ + CP_INIT_UCODE_WORKAROUND_MASK | \ + CP_INIT_OPERATION_MODE_MASK | \ + CP_INIT_REGISTER_INIT_LIST_WITH_SPINLOCK) + static int a6xx_cp_init(struct msm_gpu *gpu) { + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); struct msm_ringbuffer *ring = gpu->rb[0]; - OUT_PKT7(ring, CP_ME_INIT, 8); + OUT_PKT7(ring, CP_ME_INIT, 10); - OUT_RING(ring, 0x0000002f); + /* Enabled ordinal mask */ + OUT_RING(ring, CP_INIT_MASK); /* Enable multiple hardware contexts */ OUT_RING(ring, 0x00000003); @@ -919,9 +995,12 @@ static int a6xx_cp_init(struct msm_gpu *gpu) /* No workarounds enabled */ OUT_RING(ring, 0x00000000); - /* Pad rest of the cmds with 0's */ - OUT_RING(ring, 0x00000000); - OUT_RING(ring, 0x00000000); + /* Operation mode mask */ + OUT_RING(ring, 0x00000002); + + OUT_RING(ring, lower_32_bits(a6xx_gpu->pwrup_reglist_iova)); + OUT_RING(ring, upper_32_bits(a6xx_gpu->pwrup_reglist_iova)); + OUT_RING(ring, 0); a6xx_flush(gpu, ring); return a6xx_idle(gpu, ring) ? 0 : -EINVAL; @@ -1485,8 +1564,12 @@ static int hw_init(struct msm_gpu *gpu) /* Enable the SQE_to start the CP engine */ gpu_write(gpu, REG_A6XX_CP_SQE_CNTL, 1); - if (adreno_is_a7xx(adreno_gpu) && !a6xx_gpu->pwrup_reglist_emitted) { - a7xx_patch_pwrup_reglist(gpu); + if (!a6xx_gpu->pwrup_reglist_emitted) { + if (adreno_is_a7xx(adreno_gpu)) + a7xx_patch_pwrup_reglist(gpu); + else + a6xx_patch_pwrup_reglist(gpu); + a6xx_gpu->pwrup_reglist_emitted = true; } diff --git a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c index 6b34e704a70d..b07ba7233c2e 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c @@ -855,7 +855,7 @@ static int a6xx_hfi_feature_ctrl_msg(struct a6xx_gmu *gmu, u32 feature, u32 enab #define IFPC_LONG_HYST 0x1680 -static int a6xx_hfi_enable_ifpc(struct a6xx_gmu *gmu) +static int a7xx_hfi_enable_ifpc(struct a6xx_gmu *gmu) { if (gmu->idle_level != GMU_IDLE_STATE_IFPC) return 0; @@ -1059,6 +1059,7 @@ static int a6xx_hfi_start_v1(struct a6xx_gmu *gmu, int boot_state) int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state) { + struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu); int ret; if (gmu->legacy) @@ -1081,9 +1082,11 @@ int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state) if (ret) return ret; - ret = a6xx_hfi_enable_ifpc(gmu); - if (ret) - return ret; + if (!adreno_is_a6xx(&a6xx_gpu->base)) { + ret = a7xx_hfi_enable_ifpc(gmu); + if (ret) + return ret; + } ret = a6xx_hfi_send_thinmem_config(gmu); if (ret) diff --git a/drivers/gpu/drm/msm/registers/adreno/a6xx_gmu.xml b/drivers/gpu/drm/msm/registers/adreno/a6xx_gmu.xml index 4f934c194f73..e5fe940d6cbf 100644 --- a/drivers/gpu/drm/msm/registers/adreno/a6xx_gmu.xml +++ b/drivers/gpu/drm/msm/registers/adreno/a6xx_gmu.xml @@ -68,6 +68,7 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd"> <reg32 offset="0x1f82d" name="GMU_CM3_CFG"/> <reg32 offset="0x1f840" name="GMU_CX_GMU_POWER_COUNTER_ENABLE"/> <reg32 offset="0x1fc10" name="GMU_CX_GMU_POWER_COUNTER_ENABLE" variants="A8XX"/> + <reg32 offset="0x1f802" name="GMU_CX_GMU_WFI_CONFIG"/> <reg32 offset="0x1f841" name="GMU_CX_GMU_POWER_COUNTER_SELECT_0"/> <reg32 offset="0x1f842" name="GMU_CX_GMU_POWER_COUNTER_SELECT_1"/> <reg32 offset="0x1fc40" name="GMU_CX_GMU_POWER_COUNTER_SELECT_XOCLK_0" variants="A8XX-"/> -- 2.56.0
