Re: [PATCH v4 8/8] pmdomain: mediatek: Add support for MFlexGraphics

Ulf Hansson
2025-09-23T14:24:50Z

On Tue, 23 Sept 2025 at 13:41, Nicolas Frattaroli
<nicolas.frattaroli@collabora.com> wrote:
>
> Various MediaTek SoCs use GPU integration silicon named "MFlexGraphics"
> by MediaTek. On the MT8196 and MT6991 SoCs, interacting with this
> integration silicon is required to power on the GPU.
>
> This glue silicon is in the form of an embedded microcontroller running
> special-purpose firmware, which autonomously adjusts clocks and
> regulators.
>
> Implement a driver, modelled as a pmdomain driver with a
> set_performance_state operation, to support these SoCs.
>
> The driver also exposes the actual achieved clock rate, as read back
> from the MCU, as common clock framework clocks, by acting as a clock
> provider as well.
>
> Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
> ---
> drivers/pmdomain/mediatek/Kconfig | 16 +
> drivers/pmdomain/mediatek/Makefile | 1 +
> drivers/pmdomain/mediatek/mtk-mfg-pmdomain.c | 928 +++++++++++++++++++++++++++
> 3 files changed, 945 insertions(+)

[...]

> +
> +static int mtk_mfg_set_performance(struct generic_pm_domain *pd,
> + unsigned int state)
> +{
> + struct mtk_mfg *mfg = mtk_mfg_from_genpd(pd);
> +
> + /*
> + * Occasionally, we're asked to set OPPs when we're off. This will fail,
> + * so don't do it at all. We do foo != GENPD_STATE_ON instead of !foo
> + * as to not depend on the actual value of the enum.
> + */
> + if (mfg->pd.status != GENPD_STATE_ON)
> + return 0;

Returning 0 here, means that we may end up never restoring the
performance state for a device and its genpd, when the device is
getting runtime resumed. In genpd_runtime_resume() we are calling
genpd_restore_performance_state() before calling genpd_power_on().
This is deliberate, see commit ae8ac19655e0.

That said, I think we need to manage the restore in the ->power_on()
callback. In principle, it means we should call
mtk_mfg_set_oppidx(mfg, genpd->performance_state) from there.

> +
> + return mtk_mfg_set_oppidx(mfg, state);
> +}
> +
> +static int mtk_mfg_power_on(struct generic_pm_domain *pd)
> +{
> + struct mtk_mfg *mfg = mtk_mfg_from_genpd(pd);
> + int ret;
> +
> + ret = regulator_bulk_enable(mfg->variant->num_regulators,
> + mfg->gpu_regs);
> + if (ret)
> + return ret;
> +
> + ret = clk_prepare_enable(mfg->clk_eb);
> + if (ret)
> + goto err_disable_regulators;
> +
> + ret = clk_bulk_prepare_enable(mfg->variant->num_clks, mfg->gpu_clks);
> + if (ret)
> + goto err_disable_eb_clk;
> +
> + ret = mtk_mfg_eb_on(mfg);
> + if (ret)
> + goto err_disable_clks;
> +
> + ret = mtk_mfg_power_control(mfg, true);
> + if (ret)
> + goto err_eb_off;
> +
> + return 0;
> +
> +err_eb_off:
> + mtk_mfg_eb_off(mfg);
> +err_disable_clks:
> + clk_bulk_disable_unprepare(mfg->variant->num_clks, mfg->gpu_clks);
> +err_disable_eb_clk:
> + clk_disable_unprepare(mfg->clk_eb);
> +err_disable_regulators:
> + regulator_bulk_disable(mfg->variant->num_regulators, mfg->gpu_regs);
> +
> + return ret;
> +}

[...]

Note, I intend to have a bit closer look at this soon, but I just
observed the issue I pointed out above from my first quick look.

Kind regards
Uffe