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
