On Fri, Aug 3, 2018 at 4:41 AM, Rex Zhu <Rex.Zhu at amd.com> wrote: > Different from ordinary stoney,For Stoney Fanless, > smu firmware do not poweron/off acp tiles, so need to > poweron/off acp in driver. > > Partially revert > 'commit f766dd23e5ce ("drm/amdgpu/acp: Powrgate acp via smu")' > > Signed-off-by: Rex Zhu <Rex.Zhu at amd.com> Acked-by: Alex Deucher <alexander.deucher at amd.com> > --- > drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c | 118 +++++++++++++++++++++++++++++--- > drivers/gpu/drm/amd/amdgpu/amdgpu_acp.h | 4 ++ > 2 files changed, 114 insertions(+), 8 deletions(-) > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c > index 8bf3a98..f673c99 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c > @@ -91,6 +91,8 @@ enum { > ACP_TILE_DSP1, > ACP_TILE_DSP2, > }; > +static int acp_set_powergating_state(void *handle, > + enum amd_powergating_state state); > > static int acp_sw_init(void *handle) > { > @@ -135,8 +137,7 @@ static int acp_poweroff(struct generic_pm_domain *genpd) > * 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); > + acp_set_powergating_state(adev, AMD_PG_STATE_GATE); > } > return 0; > } > @@ -155,8 +156,7 @@ static int acp_poweron(struct generic_pm_domain *genpd) > * 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); > + acp_set_powergating_state(adev, AMD_PG_STATE_UNGATE); > } > return 0; > } > @@ -201,7 +201,7 @@ static int acp_hw_init(void *handle) > ip_block->version->major, ip_block->version->minor); > /* -ENODEV means board uses AZ rather than ACP */ > if (r == -ENODEV) { > - amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, true); > + acp_set_powergating_state(adev, AMD_PG_STATE_GATE); > return 0; > } else if (r) { > return r; > @@ -407,7 +407,7 @@ static int acp_hw_fini(void *handle) > > /* return early if no ACP */ > if (!adev->acp.acp_genpd) { > - amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, false); > + acp_set_powergating_state(adev, AMD_PG_STATE_UNGATE); > return 0; > } > > @@ -469,7 +469,7 @@ static int acp_suspend(void *handle) > > /* power up on suspend */ > if (!adev->acp.acp_cell) > - amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, false); > + acp_set_powergating_state(adev, AMD_PG_STATE_UNGATE); > return 0; > } > > @@ -479,7 +479,7 @@ static int acp_resume(void *handle) > > /* power down again on resume */ > if (!adev->acp.acp_cell) > - amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, true); > + acp_set_powergating_state(adev, AMD_PG_STATE_GATE); > return 0; > } > > @@ -509,15 +509,117 @@ static int acp_set_clockgating_state(void *handle, > return 0; > } > > +/* power off a tile/block within ACP */ > +static int acp_suspend_tile(struct amdgpu_device *adev, 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 = RREG32(mmACP_PGFSM_READ_REG_0 + tile); > + val &= ACP_TILE_ON_MASK; > + > + if (val == 0x0) { > + val = RREG32(mmACP_PGFSM_RETAIN_REG); > + val = val | (1 << tile); > + WREG32(mmACP_PGFSM_RETAIN_REG, val); > + WREG32(mmACP_PGFSM_CONFIG_REG, > + 0x500 + tile); > + > + count = ACP_TIMEOUT_LOOP; > + while (true) { > + val = RREG32(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 = RREG32(mmACP_PGFSM_RETAIN_REG); > + > + val |= ACP_TILE_OFF_RETAIN_REG_MASK; > + WREG32(mmACP_PGFSM_RETAIN_REG, val); > + } > + return 0; > +} > + > +/* power on a tile/block within ACP */ > +static int acp_resume_tile(struct amdgpu_device *adev, 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 = RREG32(mmACP_PGFSM_READ_REG_0 + tile); > + val = val & ACP_TILE_ON_MASK; > + > + if (val != 0x0) { > + WREG32(mmACP_PGFSM_CONFIG_REG, > + 0x600 + tile); > + count = ACP_TIMEOUT_LOOP; > + while (true) { > + val = RREG32(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 = RREG32(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); > + > + WREG32(mmACP_PGFSM_RETAIN_REG, val); > + } > + return 0; > +} > + > static int acp_set_powergating_state(void *handle, > enum amd_powergating_state state) > { > struct amdgpu_device *adev = (struct amdgpu_device *)handle; > bool enable = state == AMD_PG_STATE_GATE ? true : false; > + int i, ret; > + > + if (!enable && IS_ST_KICKER(adev)) { > + for (i = 0; i < 2; i++) { > + /* do not power up DSPs which are not going to be used */ > + ret = acp_resume_tile(adev, ACP_TILE_P1 + i); > + if (ret) { > + pr_err("ACP tile %d resume failed\n", i); > + break; > + } > + } > + } > > if (adev->powerplay.pp_funcs->set_powergating_by_smu) > amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, enable); > > + if (enable && IS_ST_KICKER(adev)) { > + for (i = 0; i < 5; i++) { > + ret = acp_suspend_tile(adev, ACP_TILE_P1 + i); > + if (ret) > + pr_err("ACP tile %d suspend failed\n", i); > + } > + } > + > return 0; > } > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.h > index a288ce2..fcb2e7d 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.h > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.h > @@ -39,4 +39,8 @@ struct amdgpu_acp { > > extern const struct amdgpu_ip_block_version acp_ip_block; > > +#define IS_ST_KICKER(dev) ((dev)->asic_type == CHIP_STONEY && \ > + (((dev)->pm.fw_version & 0xff00) == 0x2100 || \ > + ((dev)->pm.fw_version & 0xff00) == 0x1A00)) > + > #endif /* __AMDGPU_ACP_H__ */ > -- > 1.9.1 > > _______________________________________________ > amd-gfx mailing list > amd-gfx at lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/amd-gfx