Some A8x targets have a third memory rail (BX) in addition to GX and MX.
On these targets the GMU dependency vote carries a per-corner BX vote in
bits 25:20, which otherwise default to all-ones (no BX constraint).
Prepare BX vote field to pass this new voltage recommendation to GMU.

Signed-off-by: Akhil P Oommen <[email protected]>
---
 drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 37 +++++++++++++++++++++++++++++++++--
 1 file changed, 35 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c 
b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index 0ed01ce1c5c5..2b66d6c7fd19 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -1799,16 +1799,34 @@ static int a6xx_gmu_rpmh_arc_votes_init(struct device 
*dev, u32 *votes,
        return 0;
 }
 
+#define GMU_BX_MASK    GENMASK(25, 20)
+
 static int a6xx_gmu_rpmh_dep_votes_init(struct device *dev, u32 *votes,
                unsigned long *freqs, int freqs_count)
 {
-       const u16 *mx;
-       size_t count;
+       const u16 *mx, *gx = NULL, *gbx;
+       size_t count, gx_count = 0, gbx_count = 0;
 
        mx = a6xx_gmu_rpmh_read_arc("mx.lvl", &count);
        if (IS_ERR(mx))
                return PTR_ERR(mx);
 
+       /*
+        * Targets with a third memory rail (BX), in addition to GX and MX,
+        * expect a per-corner BX vote packed into the dependency vote. Detect
+        * such targets by the presence of the "gbx.lvl" RPMh resource. The BX
+        * corner is matched against the Gx rail level, so the "gfx.lvl" corners
+        * are needed as well.
+        */
+       gbx = a6xx_gmu_rpmh_read_arc("gbx.lvl", &gbx_count);
+       if (IS_ERR(gbx)) {
+               gbx = NULL;
+       } else {
+               gx = a6xx_gmu_rpmh_read_arc("gfx.lvl", &gx_count);
+               if (IS_ERR(gx))
+                       return PTR_ERR(gx);
+       }
+
        /* Fix the vote for zero frequency */
        votes[0] = 0xffffffff;
 
@@ -1816,12 +1834,27 @@ static int a6xx_gmu_rpmh_dep_votes_init(struct device 
*dev, u32 *votes,
        for (int i = 1; i < freqs_count; i++) {
                unsigned int level = a6xx_gmu_get_arc_level(dev, freqs[i]);
                int index = a6xx_gmu_rpmh_arc_index(dev, mx, count, level, 
false);
+               int bx;
 
                if (index < 0)
                        return index;
 
                /* Construct the vote */
                votes[i] = (0x3fff << 14) | (index << 8) | (0xff);
+
+               if (!gbx)
+                       continue;
+
+               index = a6xx_gmu_rpmh_arc_index(dev, gx, gx_count, level, 
false);
+               if (index < 0)
+                       return index;
+
+               /*
+                * Find the BX corner that satisfies that Gx level, falling
+                * back to the highest BX corner if none is high enough.
+                */
+               bx = a6xx_gmu_rpmh_arc_index(dev, gbx, gbx_count, gx[index], 
true);
+               FIELD_MODIFY(GMU_BX_MASK, &votes[i], bx);
        }
 
        return 0;

-- 
2.55.0

Reply via email to