12-26-2014 07:25 AM
We are using the latest kernel and booting linux on a 7020. Our board clock is 33.333 MHz.
After linux boots, we use the system control registers in a user application and fully bypass the PLL, in order to reduce the power consumption. We do notice the immedate performance drop when we bypass the PLL. However, all timing information under linux becomes incorrect. For example, we use the usleep() call in a C application, which waits for 100ms. When we run the same application after we bypass the PLL, the call waits for several seconds.
Similarly, we use the linux "time" command to measure runtime of an executable. For the same executable, linux reports same runtime of around 4 seconds, even though when we bypass the PLL it takes around 90 seconds to run the application.
Should we "reset" something else after we bypass the PLL in order for Linux to figure out the new clock?
12-26-2014 08:57 AM
You will need to rebuild linux with the correct constants for the new clock rate. Of course, if you need to operate with more than one clock rate, the git linux build will be unable to deliver accurate time information. You could write your own drivers in that case, and not use the buit-in routines.
(google set linux time to match cpu clock rate zynq linux)
12-29-2014 12:51 AM
Thanks for the information. We're interested in the "dynamic" rate switching. (We would like to boot as fast as possible and then reduce to a lower frequency.)
The cpufreq framework appears to successfully change the frequency and keep a sane wall-clock. However, it only allows for changing between 667, 333 and 222 Mhz (and we couldn't get the 222 Mhz to work, but that's a topic for another day).
After reading Soren's (Brinkmann) e-mails over on LKML (https://lkml.org/lkml/2014/2/19/641), I get the impression that the linux kernel has (had?) a problem with dynamically adjusting the frequency to an arbitrary value, which is why the implementation only supports 667, 333 and 222. Would you happen to know if this is still the case?
12-29-2014 04:27 AM
The problematic around Zynq timers is still there and there is not much that can be done around that. So, with the generic out-of-the box Linux things will probably not work without some flaws.
Bitbanging registers after Linux has booted and bypassing the OS can be problematic in general. But definitely when you change timers, clock dividers etc. that way. In that case the HW and SW state of the clock tree and frequencies don't match which is - amongst other things - reflected in a broken time base.
I suspect you won't get around some customizations to get your use-case working.
12-29-2014 04:51 AM
Actually, I'm taking the following statement back:
The cpufreq framework appears to successfully change the frequency and keep a sane wall-clock.
We just tried the 2014.4 release at http://www.wiki.xilinx.com/Zynq+2014.4+Release . We switched the frequency from 667 to 333 Mhz. The frequency appears to change, however the system clock goes out of sync with the wall clock. (This was on ZC702)
A couple questions:
- Based on my understanding of Soren's LKML e-mails and the code on GitHub, I thought the switch from 667 to 333 or 222 will actually work while maintaining a correct time base. Is that not the case? Should we be on another branch/tag?
- If we remove cpufreq support from the kernel (disable the kernel defines and recompile), and set the CPU frequency from the EDK to an arbitrary value, say, 222 MHz, how does that information currently propagate to the kernel?
Thanks for your help
12-29-2014 05:53 AM
The frequency adjustment should work as long as the TTC is used as clocksource. When other timers are used as clocksource you'd see those issues around timing (http://www.wiki.xilinx.com/Zynq+Power+Management#cpufreq-Known Issues ). Try removing the arm_global_timer.
The frequency should propagate to Linux, but you may have to hand-edit the operating points in the device tree (https://github.com/Xilinx/linux-xlnx/blob/master/arch/arm/boot/dts/zynq-7000.dtsi#L29 )
12-29-2014 07:57 AM
"In sync with wall clock" implies the crystal used is as accrate as one in a (presumably good) wall clock.
Most crystals used in the boards are +/- 50 ppm, and seldom better than 25 ppm. So I would not expect the time to be "as accurate" as a wall clock. It will gain or lose a few seconds (50E-6*3600*24 ~~ 4 seconds gained or lost per day).
12-29-2014 11:56 AM
"In sync with wall clock" implied that we are in sync with the wall clock, given the accuracy and resolution of a wall clock. Now I don't know what kind of wall clocks you furnish your offices with, but ours have the resolution of a second.
Also, given the meticulousness of your answer, I find it surprising that you completely discounted the probability of our on-board oscillator operating with 0ppm total error, when integrated over the duration of our test, which was around 90 seconds.
Now, back to a more useful discussion please:
Soren: Thanks for your help. We were able to switch to 333 Mhz when we switched from arm_global_timer to the TTC. The 222 operating point however still does not work. When we attempt to switch to that mode, we get an error indicating that the frequency is not supported, even though it is defined in the devicetree and also reported as a valid frequency in the frequency table. (Hoping that this is due to a rounding error, we tried 2222222, 2222223 and 2222221, but no go...) We will dig further into this so I appreciate any tips that can guide is in the right direction.
Also, can you please briefly describe what stands in the way of supporting other frequencies (eg, 111 Mhz) for dynamic switching ?
12-29-2014 12:20 PM
In the default configuration the 222 MHz OPP is unreachable.
To keep the time base constant, the TTC pre-scaler is adjusted on frequency changes. That pre-scaler can compensate for changes by powers of two only (the commit message you found mentioned that, I think). So, if you boot Linux with 666 MHz, the only other valid OPP is 333 (we removed the 222 OPP recently).
What the actual limits are, may depend on your use-case. 666 is default, hence 333 is the other valid OPP. At the moment the OPPs aren't dynamically created, but you can basically punch in whatever you like. But:
- the TTC will prevent all changes that are not by powers of two
- other drivers may enforce similar restrictions (I don't think this is relevant for your case though since peripherals should be driven by the IOPLL)
- the system may not be able to keep up with its tasks. e.g. we chose 200 MHz as lowest valid frequency because we saw issues with USB at lower speeds
Another note: cpufreq will only change the divider in the ARM_CLK_CTRL register. It does not alter the PLLs.
08-24-2016 02:18 AM
Is there a fix for making the 222Mhz OPP work?
If 222 MHz OPP is unreachable in the default configuration then why do I see the cpufreq/stats/trans_table as
If it is unreachable it should have been 0 always!!