Commit 6ba21d02 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

Merge branch 'cpufreq/arm/linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm

Merge ARM cpufreq fixes for 6.7-rc4 from Viresh Kumar.

These fix issues related to power domains in the qcom cpufreq driver
and an OPP-related issue in the imx6q cpufreq driver.

* 'cpufreq/arm/linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm:
  pmdomain: qcom: rpmpd: Set GENPD_FLAG_ACTIVE_WAKEUP
  cpufreq: qcom-nvmem: Preserve PM domain votes in system suspend
  cpufreq: qcom-nvmem: Enable virtual power domain devices
  cpufreq: imx6q: Don't disable 792 Mhz OPP unnecessarily
parents 2cc14f52 8f96e29a
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -327,7 +327,7 @@ static int imx6ul_opp_check_speed_grading(struct device *dev)
			imx6x_disable_freq_in_opp(dev, 696000000);

	if (of_machine_is_compatible("fsl,imx6ull")) {
		if (val != OCOTP_CFG3_6ULL_SPEED_792MHZ)
		if (val < OCOTP_CFG3_6ULL_SPEED_792MHZ)
			imx6x_disable_freq_in_opp(dev, 792000000);

		if (val != OCOTP_CFG3_6ULL_SPEED_900MHZ)
+70 −3
Original line number Diff line number Diff line
@@ -23,8 +23,10 @@
#include <linux/nvmem-consumer.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/pm_domain.h>
#include <linux/pm_opp.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/soc/qcom/smem.h>

@@ -55,6 +57,7 @@ struct qcom_cpufreq_match_data {

struct qcom_cpufreq_drv_cpu {
	int opp_token;
	struct device **virt_devs;
};

struct qcom_cpufreq_drv {
@@ -424,6 +427,30 @@ static const struct qcom_cpufreq_match_data match_data_ipq8074 = {
	.get_version = qcom_cpufreq_ipq8074_name_version,
};

static void qcom_cpufreq_suspend_virt_devs(struct qcom_cpufreq_drv *drv, unsigned int cpu)
{
	const char * const *name = drv->data->genpd_names;
	int i;

	if (!drv->cpus[cpu].virt_devs)
		return;

	for (i = 0; *name; i++, name++)
		device_set_awake_path(drv->cpus[cpu].virt_devs[i]);
}

static void qcom_cpufreq_put_virt_devs(struct qcom_cpufreq_drv *drv, unsigned int cpu)
{
	const char * const *name = drv->data->genpd_names;
	int i;

	if (!drv->cpus[cpu].virt_devs)
		return;

	for (i = 0; *name; i++, name++)
		pm_runtime_put(drv->cpus[cpu].virt_devs[i]);
}

static int qcom_cpufreq_probe(struct platform_device *pdev)
{
	struct qcom_cpufreq_drv *drv;
@@ -478,6 +505,7 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
	of_node_put(np);

	for_each_possible_cpu(cpu) {
		struct device **virt_devs = NULL;
		struct dev_pm_opp_config config = {
			.supported_hw = NULL,
		};
@@ -498,7 +526,7 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)

		if (drv->data->genpd_names) {
			config.genpd_names = drv->data->genpd_names;
			config.virt_devs = NULL;
			config.virt_devs = &virt_devs;
		}

		if (config.supported_hw || config.genpd_names) {
@@ -509,6 +537,27 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
				goto free_opp;
			}
		}

		if (virt_devs) {
			const char * const *name = config.genpd_names;
			int i, j;

			for (i = 0; *name; i++, name++) {
				ret = pm_runtime_resume_and_get(virt_devs[i]);
				if (ret) {
					dev_err(cpu_dev, "failed to resume %s: %d\n",
						*name, ret);

					/* Rollback previous PM runtime calls */
					name = config.genpd_names;
					for (j = 0; *name && j < i; j++, name++)
						pm_runtime_put(virt_devs[j]);

					goto free_opp;
				}
			}
			drv->cpus[cpu].virt_devs = virt_devs;
		}
	}

	cpufreq_dt_pdev = platform_device_register_simple("cpufreq-dt", -1,
@@ -522,8 +571,10 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
	dev_err(cpu_dev, "Failed to register platform device\n");

free_opp:
	for_each_possible_cpu(cpu)
	for_each_possible_cpu(cpu) {
		qcom_cpufreq_put_virt_devs(drv, cpu);
		dev_pm_opp_clear_config(drv->cpus[cpu].opp_token);
	}
	return ret;
}

@@ -534,15 +585,31 @@ static void qcom_cpufreq_remove(struct platform_device *pdev)

	platform_device_unregister(cpufreq_dt_pdev);

	for_each_possible_cpu(cpu)
	for_each_possible_cpu(cpu) {
		qcom_cpufreq_put_virt_devs(drv, cpu);
		dev_pm_opp_clear_config(drv->cpus[cpu].opp_token);
	}
}

static int qcom_cpufreq_suspend(struct device *dev)
{
	struct qcom_cpufreq_drv *drv = dev_get_drvdata(dev);
	unsigned int cpu;

	for_each_possible_cpu(cpu)
		qcom_cpufreq_suspend_virt_devs(drv, cpu);

	return 0;
}

static DEFINE_SIMPLE_DEV_PM_OPS(qcom_cpufreq_pm_ops, qcom_cpufreq_suspend, NULL);

static struct platform_driver qcom_cpufreq_driver = {
	.probe = qcom_cpufreq_probe,
	.remove_new = qcom_cpufreq_remove,
	.driver = {
		.name = "qcom-cpufreq-nvmem",
		.pm = pm_sleep_ptr(&qcom_cpufreq_pm_ops),
	},
};

+1 −0
Original line number Diff line number Diff line
@@ -1044,6 +1044,7 @@ static int rpmpd_probe(struct platform_device *pdev)
		rpmpds[i]->pd.power_off = rpmpd_power_off;
		rpmpds[i]->pd.power_on = rpmpd_power_on;
		rpmpds[i]->pd.set_performance_state = rpmpd_set_performance;
		rpmpds[i]->pd.flags = GENPD_FLAG_ACTIVE_WAKEUP;
		pm_genpd_init(&rpmpds[i]->pd, NULL, true);

		data->domains[i] = &rpmpds[i]->pd;