]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
drm/imagination: Improve firmware power off for layout_mars config
authorBrajesh Gupta <brajesh.gupta@imgtec.com>
Fri, 13 Mar 2026 06:38:24 +0000 (06:38 +0000)
committerMatt Coster <matt.coster@imgtec.com>
Mon, 23 Mar 2026 15:01:05 +0000 (15:01 +0000)
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>
drivers/gpu/drm/imagination/pvr_fw_startstop.c

index dcbb9903e791e600db22d334b2e9580057edc89b..6ae0489f7e2ed73d390bd026954e7fbd617cf152 100644 (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;
        }