All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] cpufreq: tegra186: Fix get frequency callback
@ 2020-11-03 11:55 Jon Hunter
  2020-11-04  9:33 ` Viresh Kumar
  0 siblings, 1 reply; 4+ messages in thread
From: Jon Hunter @ 2020-11-03 11:55 UTC (permalink / raw)
  To: Rafael J . Wysocki, Viresh Kumar, Thierry Reding, Sumit Gupta
  Cc: linux-pm, linux-tegra, linux-kernel, Jon Hunter

Commit b89c01c96051 ("cpufreq: tegra186: Fix initial frequency")
implemented the CPUFREQ 'get' callback to determine the current
operating frequency for each CPU. This implementation used a simple
looked up to determine the current operating frequency. The problem
with this is that frequency table for different Tegra186 devices may
vary and so the default boot frequency for Tegra186 device may or may
not be present in the frequency table. If the default boot frequency is
not present in the frequency table, this causes the function
tegra186_cpufreq_get() to return 0 and in turn causes cpufreq_online()
to fail which prevents CPUFREQ from working.

Fix this by always calculating the CPU frequency based upon the current
'ndiv' setting for the CPU. Note that the CPU frequency for Tegra186 is
calculated by reading the current 'ndiv' setting, multiplying by the
CPU reference clock and dividing by a constant divisor.

Fixes: b89c01c96051 ("cpufreq: tegra186: Fix initial frequency")

Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
---
 drivers/cpufreq/tegra186-cpufreq.c | 33 +++++++++++++++++++-----------
 1 file changed, 21 insertions(+), 12 deletions(-)

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;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH] cpufreq: tegra186: Fix get frequency callback
  2020-11-03 11:55 [PATCH] cpufreq: tegra186: Fix get frequency callback Jon Hunter
@ 2020-11-04  9:33 ` Viresh Kumar
  2020-11-16 15:55   ` Jon Hunter
  0 siblings, 1 reply; 4+ messages in thread
From: Viresh Kumar @ 2020-11-04  9:33 UTC (permalink / raw)
  To: Jon Hunter
  Cc: Rafael J . Wysocki, Thierry Reding, Sumit Gupta, linux-pm,
	linux-tegra, linux-kernel

On 03-11-20, 11:55, Jon Hunter wrote:
> Commit b89c01c96051 ("cpufreq: tegra186: Fix initial frequency")
> implemented the CPUFREQ 'get' callback to determine the current
> operating frequency for each CPU. This implementation used a simple
> looked up to determine the current operating frequency. The problem
> with this is that frequency table for different Tegra186 devices may
> vary and so the default boot frequency for Tegra186 device may or may
> not be present in the frequency table. If the default boot frequency is
> not present in the frequency table, this causes the function
> tegra186_cpufreq_get() to return 0 and in turn causes cpufreq_online()
> to fail which prevents CPUFREQ from working.
> 
> Fix this by always calculating the CPU frequency based upon the current
> 'ndiv' setting for the CPU. Note that the CPU frequency for Tegra186 is
> calculated by reading the current 'ndiv' setting, multiplying by the
> CPU reference clock and dividing by a constant divisor.
> 
> Fixes: b89c01c96051 ("cpufreq: tegra186: Fix initial frequency")
> 
> Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
> ---
>  drivers/cpufreq/tegra186-cpufreq.c | 33 +++++++++++++++++++-----------
>  1 file changed, 21 insertions(+), 12 deletions(-)

Acked-by: Viresh Kumar <viresh.kumar@linaro.org>

Rafael: This needs to go in the next rc and so I am not applying it
in my tree as this is the only fix I have for now.

-- 
viresh

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] cpufreq: tegra186: Fix get frequency callback
  2020-11-04  9:33 ` Viresh Kumar
@ 2020-11-16 15:55   ` Jon Hunter
  2020-11-17  4:36     ` Viresh Kumar
  0 siblings, 1 reply; 4+ messages in thread
From: Jon Hunter @ 2020-11-16 15:55 UTC (permalink / raw)
  To: Viresh Kumar, Rafael J . Wysocki
  Cc: Thierry Reding, Sumit Gupta, linux-pm, linux-tegra, linux-kernel

Hi Rafael,

On 04/11/2020 09:33, Viresh Kumar wrote:
> On 03-11-20, 11:55, Jon Hunter wrote:
>> Commit b89c01c96051 ("cpufreq: tegra186: Fix initial frequency")
>> implemented the CPUFREQ 'get' callback to determine the current
>> operating frequency for each CPU. This implementation used a simple
>> looked up to determine the current operating frequency. The problem
>> with this is that frequency table for different Tegra186 devices may
>> vary and so the default boot frequency for Tegra186 device may or may
>> not be present in the frequency table. If the default boot frequency is
>> not present in the frequency table, this causes the function
>> tegra186_cpufreq_get() to return 0 and in turn causes cpufreq_online()
>> to fail which prevents CPUFREQ from working.
>>
>> Fix this by always calculating the CPU frequency based upon the current
>> 'ndiv' setting for the CPU. Note that the CPU frequency for Tegra186 is
>> calculated by reading the current 'ndiv' setting, multiplying by the
>> CPU reference clock and dividing by a constant divisor.
>>
>> Fixes: b89c01c96051 ("cpufreq: tegra186: Fix initial frequency")
>>
>> Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
>> ---
>>  drivers/cpufreq/tegra186-cpufreq.c | 33 +++++++++++++++++++-----------
>>  1 file changed, 21 insertions(+), 12 deletions(-)
> 
> Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
> 
> Rafael: This needs to go in the next rc and so I am not applying it
> in my tree as this is the only fix I have for now.


Are you able to pick this up for v5.10 fixes?

Thanks
Jon

-- 
nvpublic

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] cpufreq: tegra186: Fix get frequency callback
  2020-11-16 15:55   ` Jon Hunter
@ 2020-11-17  4:36     ` Viresh Kumar
  0 siblings, 0 replies; 4+ messages in thread
From: Viresh Kumar @ 2020-11-17  4:36 UTC (permalink / raw)
  To: Jon Hunter
  Cc: Rafael J . Wysocki, Thierry Reding, Sumit Gupta, linux-pm,
	linux-tegra, linux-kernel

On 16-11-20, 15:55, Jon Hunter wrote:
> Hi Rafael,
> 
> On 04/11/2020 09:33, Viresh Kumar wrote:
> > On 03-11-20, 11:55, Jon Hunter wrote:
> >> Commit b89c01c96051 ("cpufreq: tegra186: Fix initial frequency")
> >> implemented the CPUFREQ 'get' callback to determine the current
> >> operating frequency for each CPU. This implementation used a simple
> >> looked up to determine the current operating frequency. The problem
> >> with this is that frequency table for different Tegra186 devices may
> >> vary and so the default boot frequency for Tegra186 device may or may
> >> not be present in the frequency table. If the default boot frequency is
> >> not present in the frequency table, this causes the function
> >> tegra186_cpufreq_get() to return 0 and in turn causes cpufreq_online()
> >> to fail which prevents CPUFREQ from working.
> >>
> >> Fix this by always calculating the CPU frequency based upon the current
> >> 'ndiv' setting for the CPU. Note that the CPU frequency for Tegra186 is
> >> calculated by reading the current 'ndiv' setting, multiplying by the
> >> CPU reference clock and dividing by a constant divisor.
> >>
> >> Fixes: b89c01c96051 ("cpufreq: tegra186: Fix initial frequency")
> >>
> >> Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
> >> ---
> >>  drivers/cpufreq/tegra186-cpufreq.c | 33 +++++++++++++++++++-----------
> >>  1 file changed, 21 insertions(+), 12 deletions(-)
> > 
> > Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
> > 
> > Rafael: This needs to go in the next rc and so I am not applying it
> > in my tree as this is the only fix I have for now.
> 
> 
> Are you able to pick this up for v5.10 fixes?

Applied to my tree now, will send a PULL request soon.

-- 
viresh

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2020-11-17  4:36 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-03 11:55 [PATCH] cpufreq: tegra186: Fix get frequency callback Jon Hunter
2020-11-04  9:33 ` Viresh Kumar
2020-11-16 15:55   ` Jon Hunter
2020-11-17  4:36     ` Viresh Kumar

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.