diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-11-19 11:11:50 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-11-19 11:11:50 -0800 |
commit | 4ca35b4f45092634df21dada47746571a34cc09c (patch) | |
tree | 054bae0e499efc9344b4374adf9f678caced7adc | |
parent | fee3c824edf24fd4c497bb3b887d1447150ec4ec (diff) | |
parent | 3a8ac4d39651c71d6d2f3376b13d0bad1484249a (diff) | |
download | linux-4ca35b4f45092634df21dada47746571a34cc09c.tar.bz2 |
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
-rw-r--r-- | drivers/cpufreq/scmi-cpufreq.c | 6 | ||||
-rw-r--r-- | drivers/cpufreq/tegra186-cpufreq.c | 33 | ||||
-rw-r--r-- | drivers/cpuidle/cpuidle-tegra.c | 4 |
3 files changed, 29 insertions, 14 deletions
diff --git a/drivers/cpufreq/scmi-cpufreq.c b/drivers/cpufreq/scmi-cpufreq.c index e855e8612a67..78318508a6d6 100644 --- a/drivers/cpufreq/scmi-cpufreq.c +++ b/drivers/cpufreq/scmi-cpufreq.c @@ -8,6 +8,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include <linux/clk-provider.h> #include <linux/cpu.h> #include <linux/cpufreq.h> #include <linux/cpumask.h> @@ -228,12 +229,17 @@ static struct cpufreq_driver scmi_cpufreq_driver = { static int scmi_cpufreq_probe(struct scmi_device *sdev) { int ret; + struct device *dev = &sdev->dev; handle = sdev->handle; if (!handle || !handle->perf_ops) 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); if (ret) { dev_err(&sdev->dev, "%s: registering cpufreq failed, err: %d\n", diff --git a/drivers/cpufreq/tegra186-cpufreq.c b/drivers/cpufreq/tegra186-cpufreq.c index 4b4079f51559..7eb2c56c65de 100644 --- a/drivers/cpufreq/tegra186-cpufreq.c +++ b/drivers/cpufreq/tegra186-cpufreq.c @@ -42,6 +42,8 @@ static const struct tegra186_cpufreq_cluster_info tegra186_clusters[] = { struct tegra186_cpufreq_cluster { const struct tegra186_cpufreq_cluster_info *info; struct cpufreq_frequency_table *table; + u32 ref_clk_khz; + u32 div; }; struct tegra186_cpufreq_data { @@ -94,7 +96,7 @@ static int tegra186_cpufreq_set_target(struct cpufreq_policy *policy, 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; void __iomem *edvd_reg; unsigned int i, freq = 0; @@ -104,17 +106,23 @@ static unsigned int tegra186_cpufreq_get(unsigned int cpu) if (!policy) return 0; - tbl = policy->freq_table; edvd_reg = policy->driver_data; ndiv = readl(edvd_reg) & EDVD_CORE_VOLT_FREQ_F_MASK; - for (i = 0; tbl[i].frequency != CPUFREQ_TABLE_END; i++) { - if ((tbl[i].driver_data & EDVD_CORE_VOLT_FREQ_F_MASK) == ndiv) { - freq = tbl[i].frequency; - break; + for (i = 0; i < data->num_clusters; i++) { + struct tegra186_cpufreq_cluster *cluster = &data->clusters[i]; + int core; + + 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); return freq; @@ -133,7 +141,7 @@ static struct cpufreq_driver tegra186_cpufreq_driver = { static struct cpufreq_frequency_table *init_vhint_table( struct platform_device *pdev, struct tegra_bpmp *bpmp, - unsigned int cluster_id) + struct tegra186_cpufreq_cluster *cluster) { struct cpufreq_frequency_table *table; struct mrq_cpu_vhint_request req; @@ -152,7 +160,7 @@ static struct cpufreq_frequency_table *init_vhint_table( memset(&req, 0, sizeof(req)); req.addr = phys; - req.cluster_id = cluster_id; + req.cluster_id = cluster->info->bpmp_cluster_id; memset(&msg, 0, sizeof(msg)); msg.mrq = MRQ_CPU_VHINT; @@ -185,6 +193,9 @@ static struct cpufreq_frequency_table *init_vhint_table( 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++) { struct cpufreq_frequency_table *point; u16 ndiv = data->ndiv[i]; @@ -202,8 +213,7 @@ static struct cpufreq_frequency_table *init_vhint_table( point = &table[j++]; point->driver_data = edvd_val; - point->frequency = data->ref_clk_hz * ndiv / data->pdiv / - data->mdiv / 1000; + point->frequency = (cluster->ref_clk_khz * ndiv) / cluster->div; } table[j].frequency = CPUFREQ_TABLE_END; @@ -245,8 +255,7 @@ static int tegra186_cpufreq_probe(struct platform_device *pdev) struct tegra186_cpufreq_cluster *cluster = &data->clusters[i]; cluster->info = &tegra186_clusters[i]; - cluster->table = init_vhint_table( - pdev, bpmp, cluster->info->bpmp_cluster_id); + cluster->table = init_vhint_table(pdev, bpmp, cluster); if (IS_ERR(cluster->table)) { err = PTR_ERR(cluster->table); goto put_bpmp; diff --git a/drivers/cpuidle/cpuidle-tegra.c b/drivers/cpuidle/cpuidle-tegra.c index e8956706a291..191966dc8d02 100644 --- a/drivers/cpuidle/cpuidle-tegra.c +++ b/drivers/cpuidle/cpuidle-tegra.c @@ -189,7 +189,7 @@ static int tegra_cpuidle_state_enter(struct cpuidle_device *dev, } local_fiq_disable(); - tegra_pm_set_cpu_in_lp2(); + RCU_NONIDLE(tegra_pm_set_cpu_in_lp2()); cpu_pm_enter(); switch (index) { @@ -207,7 +207,7 @@ static int tegra_cpuidle_state_enter(struct cpuidle_device *dev, } cpu_pm_exit(); - tegra_pm_clear_cpu_in_lp2(); + RCU_NONIDLE(tegra_pm_clear_cpu_in_lp2()); local_fiq_enable(); return err ?: index; |