drm/imagination: Improve firmware power off for layout_mars config

In layout_mars HW config, Firmware MCU moved from Sidekick to new Mars
domain so Firmware takes care of powering down Sidekick/Jones and SLC.
Skip checks for those from kernel and check idle bits for Firmware MCU
and system arbiter excluding SOCIF.

Signed-off-by: Brajesh Gupta <brajesh.gupta@imgtec.com>
Reviewed-by: Matt Coster <matt.coster@imgtec.com>
Link: https://patch.msgid.link/20260313-b4-staging-layout_mars_base-v2-1-9e3c251d278e@imgtec.com
Signed-off-by: Matt Coster <matt.coster@imgtec.com>
This commit is contained in:
Brajesh Gupta 2026-03-13 06:38:24 +00:00 committed by Matt Coster
parent 25e90f486f
commit 51e39ceeca
No known key found for this signature in database
GPG Key ID: 79BC19F3D9DE6AB0

View File

@ -209,18 +209,32 @@ pvr_fw_stop(struct pvr_device *pvr_dev)
ROGUE_CR_SIDEKICK_IDLE_SOCIF_EN |
ROGUE_CR_SIDEKICK_IDLE_HOSTIF_EN);
bool skip_garten_idle = false;
u64 layout_mars_value = 0;
bool layout_mars = false;
bool meta_fw = pvr_dev->fw_dev.processor_type == PVR_FW_PROCESSOR_TYPE_META;
u32 reg_value;
int err;
if (PVR_FEATURE_VALUE(pvr_dev, layout_mars, &layout_mars_value) == 0)
layout_mars = layout_mars_value > 0;
/*
* Wait for Sidekick/Jones to signal IDLE except for the Garten Wrapper.
* For cores with the LAYOUT_MARS feature, SIDEKICK would have been
* For cores with the LAYOUT_MARS feature, SIDEKICK and SLC would have been
* powered down by the FW.
*/
err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_SIDEKICK_IDLE, sidekick_idle_mask,
sidekick_idle_mask, POLL_TIMEOUT_USEC);
if (err)
return err;
if (!layout_mars) {
/* Wait for Sidekick/Jones to signal IDLE except for the Garten Wrapper. */
err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_SIDEKICK_IDLE, sidekick_idle_mask,
sidekick_idle_mask, POLL_TIMEOUT_USEC);
if (err)
return err;
/* Wait for SLC to signal IDLE. */
err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_SLC_IDLE, ROGUE_CR_SLC_IDLE_MASKFULL,
ROGUE_CR_SLC_IDLE_MASKFULL, POLL_TIMEOUT_USEC);
if (err)
return err;
}
/* Unset MTS DM association with threads. */
pvr_cr_write32(pvr_dev, ROGUE_CR_MTS_INTCTX_THREAD0_DM_ASSOC,
@ -270,27 +284,25 @@ pvr_fw_stop(struct pvr_device *pvr_dev)
return err;
/*
* Wait for SLC to signal IDLE.
* For cores with the LAYOUT_MARS feature, SLC would have been powered
* down by the FW.
* For cores with the LAYOUT_MARS feature, SIDEKICK and SLC would have been
* powered down by the FW.
*/
err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_SLC_IDLE,
ROGUE_CR_SLC_IDLE_MASKFULL,
ROGUE_CR_SLC_IDLE_MASKFULL, POLL_TIMEOUT_USEC);
if (err)
return err;
if (!layout_mars) {
/* Wait for SLC to signal IDLE. */
err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_SLC_IDLE,
ROGUE_CR_SLC_IDLE_MASKFULL,
ROGUE_CR_SLC_IDLE_MASKFULL, POLL_TIMEOUT_USEC);
if (err)
return err;
/*
* Wait for Sidekick/Jones to signal IDLE except for the Garten Wrapper.
* For cores with the LAYOUT_MARS feature, SIDEKICK would have been powered
* down by the FW.
*/
err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_SIDEKICK_IDLE, sidekick_idle_mask,
sidekick_idle_mask, POLL_TIMEOUT_USEC);
if (err)
return err;
/* Wait for Sidekick/Jones to signal IDLE except for the Garten Wrapper. */
err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_SIDEKICK_IDLE, sidekick_idle_mask,
sidekick_idle_mask, POLL_TIMEOUT_USEC);
if (err)
return err;
}
if (pvr_dev->fw_dev.processor_type == PVR_FW_PROCESSOR_TYPE_META) {
if (meta_fw) {
err = pvr_meta_cr_read32(pvr_dev, META_CR_TxVECINT_BHALT, &reg_value);
if (err)
return err;
@ -304,11 +316,28 @@ pvr_fw_stop(struct pvr_device *pvr_dev)
skip_garten_idle = true;
}
if (!skip_garten_idle) {
err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_SIDEKICK_IDLE,
ROGUE_CR_SIDEKICK_IDLE_GARTEN_EN,
ROGUE_CR_SIDEKICK_IDLE_GARTEN_EN,
if (meta_fw || !layout_mars) {
if (!skip_garten_idle) {
err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_SIDEKICK_IDLE,
ROGUE_CR_SIDEKICK_IDLE_GARTEN_EN,
ROGUE_CR_SIDEKICK_IDLE_GARTEN_EN,
POLL_TIMEOUT_USEC);
if (err)
return err;
}
} else {
/*
* As FW core has been moved from SIDEKICK to the new MARS domain, checking
* idle bits for CPU & System Arbiter excluding SOCIF which will never be
* idle if Host polling on this register
*/
err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_MARS_IDLE,
ROGUE_CR_MARS_IDLE_CPU_EN |
ROGUE_CR_MARS_IDLE_MH_SYSARB0_EN,
ROGUE_CR_MARS_IDLE_CPU_EN |
ROGUE_CR_MARS_IDLE_MH_SYSARB0_EN,
POLL_TIMEOUT_USEC);
if (err)
return err;
}