Skip to content

Commit

Permalink
Merge branch 'cpufreq/arm/linux-next' of git://git.kernel.org/pub/scm…
Browse files Browse the repository at this point in the history
…/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
  • Loading branch information
Rafael J. Wysocki committed Nov 27, 2023
2 parents 2cc14f5 + 8f96e29 commit 6ba21d0
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 4 deletions.
2 changes: 1 addition & 1 deletion drivers/cpufreq/imx6q-cpufreq.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
73 changes: 70 additions & 3 deletions drivers/cpufreq/qcom-cpufreq-nvmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>

Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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,
};
Expand All @@ -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) {
Expand All @@ -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,
Expand All @@ -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;
}

Expand All @@ -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),
},
};

Expand Down
1 change: 1 addition & 0 deletions drivers/pmdomain/qcom/rpmpd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 6ba21d0

Please sign in to comment.