diff options
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.14.71/5061-drm-amdgpu-acp-Powrgate-acp-via-smu.patch')
-rw-r--r-- | common/recipes-kernel/linux/linux-yocto-4.14.71/5061-drm-amdgpu-acp-Powrgate-acp-via-smu.patch | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.14.71/5061-drm-amdgpu-acp-Powrgate-acp-via-smu.patch b/common/recipes-kernel/linux/linux-yocto-4.14.71/5061-drm-amdgpu-acp-Powrgate-acp-via-smu.patch new file mode 100644 index 00000000..5fe12313 --- /dev/null +++ b/common/recipes-kernel/linux/linux-yocto-4.14.71/5061-drm-amdgpu-acp-Powrgate-acp-via-smu.patch @@ -0,0 +1,195 @@ +From 76d153eb4639747d82c87de111dc805951992109 Mon Sep 17 00:00:00 2001 +From: Rex Zhu <Rex.Zhu@amd.com> +Date: Sun, 29 Jul 2018 18:44:06 +0800 +Subject: [PATCH 5061/5725] drm/amdgpu/acp: Powrgate acp via smu + +Call smu to power gate/ungate acp instand of only +powr down acp tiles in acp block. +when smu power gate acp: +smu will turn off clock, power down acp tiles,check and +enter in ULV state. +when smu ungate acp: +smu will exit ulv, turn on clocks, power on acp tiles. + +Reviewed-by: Alex Deucher <alexander.deucher@amd.com> +Signed-off-by: Rex Zhu <Rex.Zhu@amd.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +Signed-off-by: Raveendra Talabattula <raveendra.talabattula@amd.com> +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c | 133 ++++++-------------------------- + 1 file changed, 22 insertions(+), 111 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c +index 38ecca2..b8228a2 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c +@@ -116,136 +116,47 @@ static int acp_sw_fini(void *handle) + return 0; + } + +-/* power off a tile/block within ACP */ +-static int acp_suspend_tile(void *cgs_dev, int tile) +-{ +- u32 val = 0; +- u32 count = 0; +- +- if ((tile < ACP_TILE_P1) || (tile > ACP_TILE_DSP2)) { +- pr_err("Invalid ACP tile : %d to suspend\n", tile); +- return -1; +- } +- +- val = cgs_read_register(cgs_dev, mmACP_PGFSM_READ_REG_0 + tile); +- val &= ACP_TILE_ON_MASK; +- +- if (val == 0x0) { +- val = cgs_read_register(cgs_dev, mmACP_PGFSM_RETAIN_REG); +- val = val | (1 << tile); +- cgs_write_register(cgs_dev, mmACP_PGFSM_RETAIN_REG, val); +- cgs_write_register(cgs_dev, mmACP_PGFSM_CONFIG_REG, +- 0x500 + tile); +- +- count = ACP_TIMEOUT_LOOP; +- while (true) { +- val = cgs_read_register(cgs_dev, mmACP_PGFSM_READ_REG_0 +- + tile); +- val = val & ACP_TILE_ON_MASK; +- if (val == ACP_TILE_OFF_MASK) +- break; +- if (--count == 0) { +- pr_err("Timeout reading ACP PGFSM status\n"); +- return -ETIMEDOUT; +- } +- udelay(100); +- } +- +- val = cgs_read_register(cgs_dev, mmACP_PGFSM_RETAIN_REG); +- +- val |= ACP_TILE_OFF_RETAIN_REG_MASK; +- cgs_write_register(cgs_dev, mmACP_PGFSM_RETAIN_REG, val); +- } +- return 0; +-} +- +-/* power on a tile/block within ACP */ +-static int acp_resume_tile(void *cgs_dev, int tile) +-{ +- u32 val = 0; +- u32 count = 0; +- +- if ((tile < ACP_TILE_P1) || (tile > ACP_TILE_DSP2)) { +- pr_err("Invalid ACP tile to resume\n"); +- return -1; +- } +- +- val = cgs_read_register(cgs_dev, mmACP_PGFSM_READ_REG_0 + tile); +- val = val & ACP_TILE_ON_MASK; +- +- if (val != 0x0) { +- cgs_write_register(cgs_dev, mmACP_PGFSM_CONFIG_REG, +- 0x600 + tile); +- count = ACP_TIMEOUT_LOOP; +- while (true) { +- val = cgs_read_register(cgs_dev, mmACP_PGFSM_READ_REG_0 +- + tile); +- val = val & ACP_TILE_ON_MASK; +- if (val == 0x0) +- break; +- if (--count == 0) { +- pr_err("Timeout reading ACP PGFSM status\n"); +- return -ETIMEDOUT; +- } +- udelay(100); +- } +- val = cgs_read_register(cgs_dev, mmACP_PGFSM_RETAIN_REG); +- if (tile == ACP_TILE_P1) +- val = val & (ACP_TILE_P1_MASK); +- else if (tile == ACP_TILE_P2) +- val = val & (ACP_TILE_P2_MASK); +- +- cgs_write_register(cgs_dev, mmACP_PGFSM_RETAIN_REG, val); +- } +- return 0; +-} +- + struct acp_pm_domain { +- void *cgs_dev; ++ void *adev; + struct generic_pm_domain gpd; + }; + + static int acp_poweroff(struct generic_pm_domain *genpd) + { +- int i, ret; + struct acp_pm_domain *apd; ++ struct amdgpu_device *adev; + + apd = container_of(genpd, struct acp_pm_domain, gpd); + if (apd != NULL) { +- /* Donot return abruptly if any of power tile fails to suspend. +- * Log it and continue powering off other tile +- */ +- for (i = 4; i >= 0 ; i--) { +- ret = acp_suspend_tile(apd->cgs_dev, ACP_TILE_P1 + i); +- if (ret) +- pr_err("ACP tile %d tile suspend failed\n", i); +- } ++ adev = apd->adev; ++ /* call smu to POWER GATE ACP block ++ * smu will ++ * 1. turn off the acp clock ++ * 2. power off the acp tiles ++ * 3. check and enter ulv state ++ */ ++ if (adev->powerplay.pp_funcs->set_powergating_by_smu) ++ amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, true); + } + return 0; + } + + static int acp_poweron(struct generic_pm_domain *genpd) + { +- int i, ret; + struct acp_pm_domain *apd; ++ struct amdgpu_device *adev; + + apd = container_of(genpd, struct acp_pm_domain, gpd); + if (apd != NULL) { +- for (i = 0; i < 2; i++) { +- ret = acp_resume_tile(apd->cgs_dev, ACP_TILE_P1 + i); +- if (ret) { +- pr_err("ACP tile %d resume failed\n", i); +- break; +- } +- } +- +- /* Disable DSPs which are not going to be used */ +- for (i = 0; i < 3; i++) { +- ret = acp_suspend_tile(apd->cgs_dev, ACP_TILE_DSP0 + i); +- /* Continue suspending other DSP, even if one fails */ +- if (ret) +- pr_err("ACP DSP %d suspend failed\n", i); +- } ++ adev = apd->adev; ++ /* call smu to UNGATE ACP block ++ * smu will ++ * 1. exit ulv ++ * 2. turn on acp clock ++ * 3. power on acp tiles ++ */ ++ if (adev->powerplay.pp_funcs->set_powergating_by_smu) ++ amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, false); + } + return 0; + } +@@ -309,7 +220,7 @@ static int acp_hw_init(void *handle) + adev->acp.acp_genpd->gpd.power_off = acp_poweroff; + adev->acp.acp_genpd->gpd.power_on = acp_poweron; + +- adev->acp.acp_genpd->cgs_dev = adev->acp.cgs_device; ++ adev->acp.acp_genpd->adev = adev; + + pm_genpd_init(&adev->acp.acp_genpd->gpd, NULL, false); + +-- +2.7.4 + |