mirror of https://gitee.com/openkylin/linux.git
drm/amd/display: Wait for clean shutdown in DMCUB reset
[Why] The DMCUB may be currently executing commands when the reset is triggered. Before issuing a reset we should first wait for the DMCUB to finish its work. [How] Send the GPINT command for halting the firmware before reset. Get the ack for the command then wait for the scratch register to become the correct value. We want this to take under ~40us or so at most before we force reset to cover PHY delay sequence max time. Each register read will be at least ~1-3us so don't bother using udelay. Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Reviewed-by: Tony Cheng <Tony.Cheng@amd.com> Acked-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
fbbd3f8f6b
commit
b1e9da7f7d
|
@ -65,4 +65,10 @@ enum dmub_gpint_command {
|
|||
DMUB_GPINT__STOP_FW = 2,
|
||||
};
|
||||
|
||||
/**
|
||||
* Command responses.
|
||||
*/
|
||||
|
||||
#define DMUB_GPINT__STOP_FW_RESPONSE 0xDEADDEAD
|
||||
|
||||
#endif /* _DMUB_GPINT_CMD_H_ */
|
||||
|
|
|
@ -77,6 +77,42 @@ static inline void dmub_dcn20_translate_addr(const union dmub_addr *addr_in,
|
|||
|
||||
void dmub_dcn20_reset(struct dmub_srv *dmub)
|
||||
{
|
||||
union dmub_gpint_data_register cmd;
|
||||
const uint32_t timeout = 30;
|
||||
uint32_t in_reset, scratch, i;
|
||||
|
||||
REG_GET(DMCUB_CNTL, DMCUB_SOFT_RESET, &in_reset);
|
||||
|
||||
if (in_reset == 0) {
|
||||
cmd.bits.status = 1;
|
||||
cmd.bits.command_code = DMUB_GPINT__STOP_FW;
|
||||
cmd.bits.param = 0;
|
||||
|
||||
dmub->hw_funcs.set_gpint(dmub, cmd);
|
||||
|
||||
/**
|
||||
* Timeout covers both the ACK and the wait
|
||||
* for remaining work to finish.
|
||||
*
|
||||
* This is mostly bound by the PHY disable sequence.
|
||||
* Each register check will be greater than 1us, so
|
||||
* don't bother using udelay.
|
||||
*/
|
||||
|
||||
for (i = 0; i < timeout; ++i) {
|
||||
if (dmub->hw_funcs.is_gpint_acked(dmub, cmd))
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < timeout; ++i) {
|
||||
scratch = dmub->hw_funcs.get_gpint_response(dmub);
|
||||
if (scratch == DMUB_GPINT__STOP_FW_RESPONSE)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Force reset in case we timed out, DMCUB is likely hung. */
|
||||
}
|
||||
|
||||
REG_UPDATE(DMCUB_CNTL, DMCUB_SOFT_RESET, 1);
|
||||
REG_UPDATE(DMCUB_CNTL, DMCUB_ENABLE, 0);
|
||||
REG_UPDATE(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET, 1);
|
||||
|
|
Loading…
Reference in New Issue