Commit 4ca35b4f authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'pm-5.10-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull power management fixes from Rafael Wysocki:
 "These fix two issues in ARM cpufreq drivers and one cpuidle driver
  issue.

  Specifics:

   - Add missing RCU_NONIDLE() annotations to the Tegra cpuidle driver
     (Dmitry Osipenko)

   - Fix boot frequency computation in the tegra186 cpufreq driver (Jon
     Hunter)

   - Make the SCMI cpufreq driver register a dummy clock provider to
     avoid OPP addition failures (Sudeep Holla)"

* tag 'pm-5.10-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  cpufreq: scmi: Fix OPP addition failure with a dummy clock provider
  cpufreq: tegra186: Fix get frequency callback
  cpuidle: tegra: Annotate tegra_pm_set_cpu_in_lp2() with RCU_NONIDLE
parents fee3c824 3a8ac4d3
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/clk-provider.h>
#include <linux/cpu.h> #include <linux/cpu.h>
#include <linux/cpufreq.h> #include <linux/cpufreq.h>
#include <linux/cpumask.h> #include <linux/cpumask.h>
...@@ -228,12 +229,17 @@ static struct cpufreq_driver scmi_cpufreq_driver = { ...@@ -228,12 +229,17 @@ static struct cpufreq_driver scmi_cpufreq_driver = {
static int scmi_cpufreq_probe(struct scmi_device *sdev) static int scmi_cpufreq_probe(struct scmi_device *sdev)
{ {
int ret; int ret;
struct device *dev = &sdev->dev;
handle = sdev->handle; handle = sdev->handle;
if (!handle || !handle->perf_ops) if (!handle || !handle->perf_ops)
return -ENODEV; return -ENODEV;
/* dummy clock provider as needed by OPP if clocks property is used */
if (of_find_property(dev->of_node, "#clock-cells", NULL))
devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, NULL);
ret = cpufreq_register_driver(&scmi_cpufreq_driver); ret = cpufreq_register_driver(&scmi_cpufreq_driver);
if (ret) { if (ret) {
dev_err(&sdev->dev, "%s: registering cpufreq failed, err: %d\n", dev_err(&sdev->dev, "%s: registering cpufreq failed, err: %d\n",
......
...@@ -42,6 +42,8 @@ static const struct tegra186_cpufreq_cluster_info tegra186_clusters[] = { ...@@ -42,6 +42,8 @@ static const struct tegra186_cpufreq_cluster_info tegra186_clusters[] = {
struct tegra186_cpufreq_cluster { struct tegra186_cpufreq_cluster {
const struct tegra186_cpufreq_cluster_info *info; const struct tegra186_cpufreq_cluster_info *info;
struct cpufreq_frequency_table *table; struct cpufreq_frequency_table *table;
u32 ref_clk_khz;
u32 div;
}; };
struct tegra186_cpufreq_data { struct tegra186_cpufreq_data {
...@@ -94,7 +96,7 @@ static int tegra186_cpufreq_set_target(struct cpufreq_policy *policy, ...@@ -94,7 +96,7 @@ static int tegra186_cpufreq_set_target(struct cpufreq_policy *policy,
static unsigned int tegra186_cpufreq_get(unsigned int cpu) static unsigned int tegra186_cpufreq_get(unsigned int cpu)
{ {
struct cpufreq_frequency_table *tbl; struct tegra186_cpufreq_data *data = cpufreq_get_driver_data();
struct cpufreq_policy *policy; struct cpufreq_policy *policy;
void __iomem *edvd_reg; void __iomem *edvd_reg;
unsigned int i, freq = 0; unsigned int i, freq = 0;
...@@ -104,17 +106,23 @@ static unsigned int tegra186_cpufreq_get(unsigned int cpu) ...@@ -104,17 +106,23 @@ static unsigned int tegra186_cpufreq_get(unsigned int cpu)
if (!policy) if (!policy)
return 0; return 0;
tbl = policy->freq_table;
edvd_reg = policy->driver_data; edvd_reg = policy->driver_data;
ndiv = readl(edvd_reg) & EDVD_CORE_VOLT_FREQ_F_MASK; ndiv = readl(edvd_reg) & EDVD_CORE_VOLT_FREQ_F_MASK;
for (i = 0; tbl[i].frequency != CPUFREQ_TABLE_END; i++) { for (i = 0; i < data->num_clusters; i++) {
if ((tbl[i].driver_data & EDVD_CORE_VOLT_FREQ_F_MASK) == ndiv) { struct tegra186_cpufreq_cluster *cluster = &data->clusters[i];
freq = tbl[i].frequency; int core;
break;
for (core = 0; core < ARRAY_SIZE(cluster->info->cpus); core++) {
if (cluster->info->cpus[core] != policy->cpu)
continue;
freq = (cluster->ref_clk_khz * ndiv) / cluster->div;
goto out;
} }
} }
out:
cpufreq_cpu_put(policy); cpufreq_cpu_put(policy);
return freq; return freq;
...@@ -133,7 +141,7 @@ static struct cpufreq_driver tegra186_cpufreq_driver = { ...@@ -133,7 +141,7 @@ static struct cpufreq_driver tegra186_cpufreq_driver = {
static struct cpufreq_frequency_table *init_vhint_table( static struct cpufreq_frequency_table *init_vhint_table(
struct platform_device *pdev, struct tegra_bpmp *bpmp, struct platform_device *pdev, struct tegra_bpmp *bpmp,
unsigned int cluster_id) struct tegra186_cpufreq_cluster *cluster)
{ {
struct cpufreq_frequency_table *table; struct cpufreq_frequency_table *table;
struct mrq_cpu_vhint_request req; struct mrq_cpu_vhint_request req;
...@@ -152,7 +160,7 @@ static struct cpufreq_frequency_table *init_vhint_table( ...@@ -152,7 +160,7 @@ static struct cpufreq_frequency_table *init_vhint_table(
memset(&req, 0, sizeof(req)); memset(&req, 0, sizeof(req));
req.addr = phys; req.addr = phys;
req.cluster_id = cluster_id; req.cluster_id = cluster->info->bpmp_cluster_id;
memset(&msg, 0, sizeof(msg)); memset(&msg, 0, sizeof(msg));
msg.mrq = MRQ_CPU_VHINT; msg.mrq = MRQ_CPU_VHINT;
...@@ -185,6 +193,9 @@ static struct cpufreq_frequency_table *init_vhint_table( ...@@ -185,6 +193,9 @@ static struct cpufreq_frequency_table *init_vhint_table(
goto free; goto free;
} }
cluster->ref_clk_khz = data->ref_clk_hz / 1000;
cluster->div = data->pdiv * data->mdiv;
for (i = data->vfloor, j = 0; i <= data->vceil; i++) { for (i = data->vfloor, j = 0; i <= data->vceil; i++) {
struct cpufreq_frequency_table *point; struct cpufreq_frequency_table *point;
u16 ndiv = data->ndiv[i]; u16 ndiv = data->ndiv[i];
...@@ -202,8 +213,7 @@ static struct cpufreq_frequency_table *init_vhint_table( ...@@ -202,8 +213,7 @@ static struct cpufreq_frequency_table *init_vhint_table(
point = &table[j++]; point = &table[j++];
point->driver_data = edvd_val; point->driver_data = edvd_val;
point->frequency = data->ref_clk_hz * ndiv / data->pdiv / point->frequency = (cluster->ref_clk_khz * ndiv) / cluster->div;
data->mdiv / 1000;
} }
table[j].frequency = CPUFREQ_TABLE_END; table[j].frequency = CPUFREQ_TABLE_END;
...@@ -245,8 +255,7 @@ static int tegra186_cpufreq_probe(struct platform_device *pdev) ...@@ -245,8 +255,7 @@ static int tegra186_cpufreq_probe(struct platform_device *pdev)
struct tegra186_cpufreq_cluster *cluster = &data->clusters[i]; struct tegra186_cpufreq_cluster *cluster = &data->clusters[i];
cluster->info = &tegra186_clusters[i]; cluster->info = &tegra186_clusters[i];
cluster->table = init_vhint_table( cluster->table = init_vhint_table(pdev, bpmp, cluster);
pdev, bpmp, cluster->info->bpmp_cluster_id);
if (IS_ERR(cluster->table)) { if (IS_ERR(cluster->table)) {
err = PTR_ERR(cluster->table); err = PTR_ERR(cluster->table);
goto put_bpmp; goto put_bpmp;
......
...@@ -189,7 +189,7 @@ static int tegra_cpuidle_state_enter(struct cpuidle_device *dev, ...@@ -189,7 +189,7 @@ static int tegra_cpuidle_state_enter(struct cpuidle_device *dev,
} }
local_fiq_disable(); local_fiq_disable();
tegra_pm_set_cpu_in_lp2(); RCU_NONIDLE(tegra_pm_set_cpu_in_lp2());
cpu_pm_enter(); cpu_pm_enter();
switch (index) { switch (index) {
...@@ -207,7 +207,7 @@ static int tegra_cpuidle_state_enter(struct cpuidle_device *dev, ...@@ -207,7 +207,7 @@ static int tegra_cpuidle_state_enter(struct cpuidle_device *dev,
} }
cpu_pm_exit(); cpu_pm_exit();
tegra_pm_clear_cpu_in_lp2(); RCU_NONIDLE(tegra_pm_clear_cpu_in_lp2());
local_fiq_enable(); local_fiq_enable();
return err ?: index; return err ?: index;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment