Maybe to your surprise I’m no expert in Kernel-related things.
But let me share the little I assume to know and what I did so far:
On the Librem 5 platform like on many other ARM-based devices there’s no BIOS-Chip or BIOS-UI, so device specific config and settings (for instance cpu-clockrate or display-parameters) have to be somewhere else.
In case of Linux on ARM there are devicetree-binaries in the boot-partition, the devicetree-sources for the librem5 actually are part of the mainline-Linux-kernel-sources, these can be compiled with the device-tree-compiler dtc.
Although trying to compile these for the librem 5 and placing them in the boot partition of my devices resulted in weird graphical glitches, no clue what happened there)
But dtc can also decompile those binaries back to some sourcecode, which to my surprise is fairly readable. So I decompiled the working dtb-files from the device back to dts files, compiled them unchanged and placed these on the boot partition… no glitches
(dtc decompile command:
dtc -I dtb -O dts imx8mq-librem5-r4.dtb -o imx8mq-librem-r4.dts
dtc compile command:
dtc -I dts -O dtb imx8mq-librem5-r4.dts -o imx8mq-librem-r4.dtb
)
In the dts files there’s a section “opp-table” which defines different operating points of the CPU, in the imx8mq.dts, which is for the cpu the librem5 uses and is also included in the imx8mq-librem5-r4.dts file, theres 4 different opp’s 800mhz, 1000mhz, 1300mhz and 1500mhz, while 800 and 1300 are commented to be “industrial only” and the other two as “consumer only”.
All 4 opps have each values for opp-supported-hw:
800mhz : <0x0f 0x04> (industrial only)
1000mhz: <0x0e 0x03> (consumer only)
1300mhz: <0x0c 0x04>(industrial only)
1500mhz: <0x08 0x03>(consumer only)
So I went ahead and changed both 0x04 values to 0x03, used dtc to compile the dts to a dtb, put it onto the phones-boot partition replacing the existing imx8mq-librem-r4.dtb file and rebooted the phone, hoping it wouldn’t be bricked, which to my relief it wasn’t.
Checking which frequencies were available, through “cat /sys/devices/cpu/cpu0/cpufreq/scaling_available_frequencies”, I found that my tiny change actually worked and, instead of only having 1000000 and 1500000, I also had 800000 and 1300000 available.
Through the program cpupower I set the cpu-governor to powersave, and checked the frequency through “cat /sys/devices/cpu/cpu0/cpufreq/cpuinfo_cpu_freq”, which appeared to be 800000.
Apparently this really unlocked those other two operating points and the cpu did run at 800mhz.
I then edited the dts file further and just copy-pasted the 800mhz opp two times and edited them to 200mhz and 600mhz, compiled it, put the dtb on the phone, rebooted and checked the available frequencies.
200mhz and 600mhz unlocked
Set the cpu-governor to powersave again, and checked the clockspeed: yup 200mhz!
Since in the opp-table theres also “opp-microvolt” values for each operating point, I tried to lower the voltage for 200mhz down to 0.6Volts. This change resulted in 200mhz not being listed as available frequency, so I tried 0.7V and that did work.
I don’t know why 0.6V did not work at all, either the volategcontroller doesn’t support such low voltage as Vcpu, or something checks at boot which operating points are stable. Normally I would have expected the system to become unstable and crash with a too low voltage for the frequency.
Yesterday I did try to test this config for power consumption on the secondary OS, I have on sd-card, with the cpu-governor set to conservative.
But somehow the udev-process decided to pin a single CPU-Core to 100%Usage which resulted in the governor to clock it up to full-speed. No clue if this came from instability through my new dtb or if the OS is just somehow borked. But since the device was otherwise operational I put the dtb in the boot-partition of the eMMC with pureOS on it.