[PATCH 1/3] cpufreq: mediatek: add support for CPU speedbin

Roman Vivchar rva333 at protonmail.com
Wed Sep 23 01:55:01 PDT 2026


Hi Angelo,

On Wednesday, September 23rd, 2026 at 11:31 AM, AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com> wrote:

> On 9/23/26 09:23, Roman Vivchar via B4 Relay wrote:
> > From: Roman Vivchar <rva333 at protonmail.com>
> >
> > MediaTek SoCs are often released under the same marketing name, but with
> > different suffix for the speedbin. For example, mt6572m has 1 GHz limit,
> > mt6572a - 1.2 GHz, mt6572w - 1.4 GHz.
> >
> > Add code to support per-cluster 'opp-supported-hw' property. The DT is
> > expected to pass a CPU speedbin using standard 'nvmem-cells' property
> > under the CPU node.
> >
> > Signed-off-by: Roman Vivchar <rva333 at protonmail.com>
> > ---
> >   drivers/cpufreq/mediatek-cpufreq.c | 50 ++++++++++++++++++++++++++++++++++++--
> >   1 file changed, 48 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c
> > index 052ca7cd2f4f..f15135b2898b 100644
> > --- a/drivers/cpufreq/mediatek-cpufreq.c
> > +++ b/drivers/cpufreq/mediatek-cpufreq.c
> > @@ -10,6 +10,7 @@
> >   #include <linux/cpumask.h>
> >   #include <linux/minmax.h>
> >   #include <linux/module.h>
> > +#include <linux/nvmem-consumer.h>
> >   #include <linux/of.h>
> >   #include <linux/of_platform.h>
> >   #include <linux/platform_device.h>
> > @@ -57,6 +58,7 @@ struct mtk_cpu_dvfs_info {
> >   	const struct mtk_cpufreq_platform_data *soc_data;
> >   	int vtrack_max;
> >   	bool ccifreq_bound;
> > +	int opp_token;
> >   };
> >
> >   static struct platform_device *cpufreq_pdev;
> > @@ -381,6 +383,38 @@ static struct device *of_get_cci(struct device *cpu_dev)
> >   	return &pdev->dev;
> >   }
> >
> > +static int mtk_cpu_parse_speedbin(struct mtk_cpu_dvfs_info *info, int cpu)
> > +{
> > +	struct device *cpu_dev = get_cpu_device(cpu);
> > +	struct dev_pm_opp_config config = {};
> > +	u32 val, opp_hw_ver;
> > +	int ret;
> > +
> > +	ret = nvmem_cell_read_variable_le_u32(cpu_dev, "speed_grade", &val);
> 
> Let's keep consistency with cell names: for example, on the GPU side, the node
> in devicetree is called "gpu-speedbin at 1234", and the panfrost node has
> 
> nvmem-cells = <&gpu_speedbin>;
> nvmem-cell-names = "speed-bin";
> 
> Check MT8186 and MT8188 devicetrees ;-)

Not sure if it works like that. speed_grade comes from the arm/cpus.yaml.
Indeed I'd prefer some other name, but this means either modifying cpus.yaml
schema or making something like qcom's custom opp table binding.

> 
> > +	if (ret) {
> > +		if (ret == -ENOENT)
> 
> if (ret != -ENOENT && ret != -EOPNOTSUPP)

Ack.

> 
> > +			/* speedbin is optional */
> > +			return 0;
> > +		return dev_err_probe(cpu_dev, ret, "cpu%d: failed to read speedbin\n", cpu);
> > +	}
> > +
> > +	/* Convert the raw value to a bitmask */
> > +	if (val >= 32)
> > +		return dev_err_probe(cpu_dev, -EINVAL,
> > +				     "cpu%d: invalid speedbin value %u\n", cpu, val);
> > +	opp_hw_ver = BIT(val);
> 
> If you look at nvmem/mtk-efuse.c there is a mtk_efuse_gpu_speedbin_pp() function
> that is doing (almost) *exactly* what you're doing here.
> 
> Check if the same constraints as GPU speed binning applies to the CPU: if they do,
> just allow "cpu-speedbin" as node name in the fixup function, otherwise add a new
> post processing function for the CPU and act accordingly.

...right. Should this go as separate nvmem patch or include it in this
series?

> 
> > +
> > +	config.supported_hw = &opp_hw_ver;
> > +	config.supported_hw_count = 1;
> > +
> > +	info->opp_token = dev_pm_opp_set_config(cpu_dev, &config);
> 
> It's way easier if you use
> 
> devm_pm_opp_set_supported_hw(dev, &opp_hw_ver, 1);

Ack

Best regards,
Roman



More information about the linux-arm-kernel mailing list