Is it possible to adjust CPU & GPU clock scaling on the TX2?

We have measured some EMI into the GPS spectrum from the CPU and GPU at certain clock frequencies and would like to limit theses.

On the older TX1 platform, this was easy to do by editing drivers/platform/tegra/tegra21_dvfs.c in the linux kernel and commenting out the frequencies that we didn’t want.

An equivalent table does not seem to exist from the TX2. From what I gather in the source code, it looks like the lookup table is configured in the BPMP. Is it possible to modify that table?

For power-saving reasons, I can’t use fixed frequencies.

I am not trying to add my own table since I assume those have been verified to work well by NVIDIA. Instead, I only wish to remove certain frequencies from the list.

Hi robb_n,

Yes, this table is now under bpmp driver and may not allow to make a change to it.

Hello, thanks for the response. Unfortunately, this doesn’t help us at all. Can you please provide a concrete answer? Either we can’t change it, or you will provide us a way to change it.

Hi Jerry and Rob,

Do you want to cap the max freq for any particular clock to a lower value? that could be achieved easily.
Removing one intermediate freq will be little involved. Let us know. based on that we will guide you.

regards
Bibek

Hi Bbasu,

Ideally, we would like to remove one (or more) of the intermediate frequencies. The specific CPU frequency we would like to eliminate is 1574400 kHz. This applies to both the A57 and Denver CPUs.

We would like to keep the ability to use the higher frequencies for the best performance. However, we can’t configure a fixed frequency since we still need to keep the TX2 cool when possible.

Also, an you confirm if dynamic frequency scaling is enabled or disabled for EMC? From my testing, I have found EMC to be fixed at 1866000000 Hz.

Thanks,
Robb

Hi,

In next release we plan to provide hook to remove any particular freq from cpufreq list.
For the time being, can you check if something like this solves your purpose?

diff --git a/drivers/cpufreq/tegra_cpufreq.c b/drivers/cpufreq/tegra_cpufreq.c
index 25da74f..241f711 100644
--- a/drivers/cpufreq/tegra_cpufreq.c
+++ b/drivers/cpufreq/tegra_cpufreq.c
@@ -1157,7 +1157,8 @@ static int __init init_freqtbls(struct device_node *dn)
 	struct cpu_vhint_table *vhtbl;
 	u16 ndiv, max_freq_steps, delta_ndiv;
 	int cl;
-	int ret = 0, index;
+	int ret = 0, index, local_index;
+	unsigned int local_frequency;
 
 	if (!of_property_read_u16(dn, "freq_table_step_size",
 					&dt_freq_table_step_size)) {
@@ -1205,18 +1206,24 @@ static int __init init_freqtbls(struct device_node *dn)
 			goto err_out;
 		}
 
-		for (index = 0, ndiv = vhtbl->ndiv_min;
+		for (local_index = index = 0, ndiv = vhtbl->ndiv_min;
 				ndiv < vhtbl->ndiv_max;
-				index++, ndiv += freq_table_step_size)
-			ftbl[index].frequency = (unsigned long)
+				index++, ndiv += freq_table_step_size) {
+			local_frequency = (unsigned long)
 				(vhtbl->ref_clk_hz * ndiv)
 				/ (vhtbl->pdiv * vhtbl->mdiv * 1000);
-
-		ftbl[index++].frequency = (unsigned long)
+			if (local_frequency == 806400) /* freq with EMI */
+				continue;
+			ftbl[local_index++].frequency = local_frequency;
+		}
+		local_frequency = (unsigned long)
 			(vhtbl->ndiv_max * vhtbl->ref_clk_hz) /
 			(vhtbl->pdiv * vhtbl->mdiv * 1000);
-
-		ftbl[index].frequency = CPUFREQ_TABLE_END;
+		if (local_frequency != 806400) /* freq with EMI */
+			ftbl[local_index].frequency = local_frequency;
+		index++;
+		local_index++;
+		ftbl[local_index].frequency = CPUFREQ_TABLE_END;
 
 		tfreq_data.pcluster[cl].clft = ftbl;

Dynamic freq scaling is enabled for EMC, Are you telling that without any load also you see emc freq as 1866?
Can you run ./tegrastats.sh after boot without your usecase and after your usecase.

thanks
Bibek

Hi bbasu,

Thank you for the code sample for the CPU clocks. I will apply the patch and report back.

Regarding the EMC clocks: it appears my original test case was flawed.

I was temporarily avoiding the EMI problem in my tests by updating the CPU scaling_governor to “userspace” and setting a fixed clock. This setting appears to also adjust the EMC clock. By disabling my configuration, I can see that the EMC clock is scaling correctly with cpu/memory load.

Tegrastats when the CPU is idle:

RAM 680/7851MB (lfb 1534x4MB) cpu [1%@345,0%@345,0%@345,0%@346,1%@345,0%@345] EMC 0%@665 APE 150 GR3D 0%@114
RAM 680/7851MB (lfb 1534x4MB) cpu [2%@345,0%@345,0%@345,0%@345,0%@345,0%@345] EMC 0%@665 APE 150 GR3D 0%@114
RAM 680/7851MB (lfb 1534x4MB) cpu [0%@345,0%@345,0%@345,1%@345,0%@345,0%@345] EMC 0%@665 APE 150 GR3D 0%@114

Tegrastats when running a stress test:

RAM 1276/7851MB (lfb 1519x4MB) cpu [0%@2014,100%@2035,100%@2034,0%@2018,100%@2014,0%@2016] EMC 18%@1866 APE 150 GR3D 0%@114
RAM 1018/7851MB (lfb 1519x4MB) cpu [0%@2034,100%@2035,100%@2035,0%@2033,100%@2035,1%@2033] EMC 19%@1866 APE 150 GR3D 0%@114
RAM 1109/7851MB (lfb 1519x4MB) cpu [0%@2035,100%@2035,100%@2035,0%@2035,100%@2035,0%@2035] EMC 19%@1866 APE 150 GR3D 0%@114

Since dynamic frequency scaling is correctly enabled, is it possible to also filter these? I am specifically looking to avoid 1.6 GHz.

Thanks,
Robb

Hi Rob,

Yeah, you can remove a particular emc freq from the list by removing the entry from the bpmp dtb.
convert the dtb to dts and remove the node(s) emc-table@1600000 and convert back the dts to dtb. reflash.

You will find the file here:
Linux_for_Tegra$ ll bootloader/t186ref/tegra186-a02-bpmp-quill-p3310-1000-c04-00.dtb

There may be many files there, so just confirm from the flashing host side log which bpmp file is getting flashed.

thanks
Bibek

Hi bbasu,

I can confirm that your patch to tegra_cpufreq.c works. I was able to filter the frequencies that I was interested in.

I was also able to filter the the EMC frequencies by modifying bootloader/tegra186-a02-bpmp-quill-p3310-1000-c01-00-te770d-ucm2.dtb. I have removed both the emc-table@1600000 and emc-table-derated@1600000 entries.

The last open question is regarding the GPU frequencies.

This was also previously configurable in drivers/platform/tegra/tegra21_dvfs.c. Can you also filter these on the TX2? I am specifically interested in filtering 420750000 and 828750000 Hz.

Thanks,
Robb

Hi Robb,

You can do something like

diff --git a/drivers/gpu/nvgpu/gp10b/platform_gp10b_tegra.c b/drivers/gpu/nvgpu/gp10b/platform_gp10b_tegra.c
index e037a25..2611be4 100644
--- a/drivers/gpu/nvgpu/gp10b/platform_gp10b_tegra.c
+++ b/drivers/gpu/nvgpu/gp10b/platform_gp10b_tegra.c
@@ -389,6 +389,9 @@ static int gp10b_clk_get_freqs(struct device *dev,
 
                if (i % GP10B_FREQ_SELECT_STEP == 0 ||
                                new_rate == max_rate) {
+
+                       if (318750000 == new_rate)
+                               continue;
                        gp10b_freq_table[freq_counter++] = new_rate;
 
                        if (new_rate == max_rate)

Hi bbasu,

The recommendations for filtering frequencies all work well on my end. Thanks for the help!