Commit 0a81b0eb authored by Ulf Hansson's avatar Ulf Hansson Committed by Sudeep Holla
Browse files

firmware: arm_scmi: Add generic OPP support to the SCMI performance domain



To allow a consumer driver to use the OPP library to scale the performance
for its device, let's dynamically add the OPP table when the device gets
attached to its SCMI performance domain.

Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
Link: https://lore.kernel.org/r/20230925131715.138411-10-ulf.hansson@linaro.org


Signed-off-by: default avatarSudeep Holla <sudeep.holla@arm.com>
parent 5a6a1041
Loading
Loading
Loading
Loading
+34 −0
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@
#include <linux/device.h>
#include <linux/module.h>
#include <linux/pm_domain.h>
#include <linux/pm_opp.h>
#include <linux/scmi_protocol.h>
#include <linux/slab.h>

@@ -42,6 +43,37 @@ scmi_pd_set_perf_state(struct generic_pm_domain *genpd, unsigned int state)
	return ret;
}

static int
scmi_pd_attach_dev(struct generic_pm_domain *genpd, struct device *dev)
{
	struct scmi_perf_domain *pd = to_scmi_pd(genpd);
	int ret;

	/*
	 * Allow the device to be attached, but don't add the OPP table unless
	 * the performance level can be changed.
	 */
	if (!pd->info->set_perf)
		return 0;

	ret = pd->perf_ops->device_opps_add(pd->ph, dev, pd->domain_id);
	if (ret)
		dev_warn(dev, "failed to add OPPs for the device\n");

	return ret;
}

static void
scmi_pd_detach_dev(struct generic_pm_domain *genpd, struct device *dev)
{
	struct scmi_perf_domain *pd = to_scmi_pd(genpd);

	if (!pd->info->set_perf)
		return;

	dev_pm_opp_remove_all_dynamic(dev);
}

static int scmi_perf_domain_probe(struct scmi_device *sdev)
{
	struct device *dev = &sdev->dev;
@@ -95,6 +127,8 @@ static int scmi_perf_domain_probe(struct scmi_device *sdev)
		scmi_pd->genpd.flags = GENPD_FLAG_ALWAYS_ON |
				       GENPD_FLAG_OPP_TABLE_FW;
		scmi_pd->genpd.set_performance_state = scmi_pd_set_perf_state;
		scmi_pd->genpd.attach_dev = scmi_pd_attach_dev;
		scmi_pd->genpd.detach_dev = scmi_pd_detach_dev;

		ret = pm_genpd_init(&scmi_pd->genpd, NULL, false);
		if (ret)