Tag Archives: dtb

Working around a A64 thermal sensor miscalibration – recompiling .dtb to change the kernel driver trip point

I got a SoPine (Pine64-based board) 2 years ago. Hooked it up just now, trying to make it boot since I want to use it for a project. Flashed Armbian Focal on a 8GB MicroSD (this version: Armbian_20.08.1_Pine64so_focal_current_5.8.5.img). It wouldn’t boot, so I connected to the board’s serial port, and after all the uboot logs, here’s what I got after “Starting kernel”:

[    3.070744] thermal thermal_zone0: critical temperature reached (188 C), shutting down
[    3.082243] reboot: Power down

Everything was cold – all ICs on the SoPine board were cold, all ICs on the baseboard were cold, whatever was 200 degrees hot, I couldn’t find it anywhere.

Trying to “bisect” the issue, I loaded an old Armbian Ubuntu 16.04 image from January of 2019 and it actually booted the board without instantly shutting down – that was a good start. What did I notice?

1) armbianmonitor -m actually gave reasonable temperatures, though it did throw some weird Bash errors:

22:37:39: 1152MHz 0.11 8% 1% 2% 0% 5% 0%/usr/bin/armbianmonitor: line 385: read: read error: 0: Operation not permitted
/usr/bin/armbianmonitor: line 386: [: -ge: unary operator expected
°C 41°C 0/7

2) dmesg had output that indicated the kernel couldn’t even read the thermal zone properly
[ +1.967998] thermal thermal_zone0: failed to read out thermal zone 0
[ +1.968005] thermal thermal_zone0: failed to read out thermal zone 0
[ +1.967997] thermal thermal_zone0: failed to read out thermal zone 0
[ +1.967971] thermal thermal_zone0: failed to read out thermal zone 0

Well, perhaps it was just an old kernel, who knows.

After much talking on Pine64 Discord, we’ve found a relevant-ish bugtracker issue. Sounds like it’s possible for A64 temperature sensors to not be properly calibrated at the factory, and that’s what apparently happened to me too. The image wouldn’t even start booting because the shutdown was initiated by the Linux thermal driver and would immediately shutdown the kernel as soon as it booted up and noticed the temps were outrageously high.

The bugtracker issue:

1) Mentioned a tool that let me see the calibration register values that, apparently, were responsible for temperature calibration.

root@pine64so:~# ./regtool a64-sid
0x01c14234 : 07ab07b1
0x01c14238 : 000007b4

2) mentioned you could recompile the .dtb files to change the trip points that the kernel driver should use.

Well, I couldn’t guarantee that I would be able to both change the temperature calibration values and figure out the right values to make the A64 CPU show the right temperature – the factory probably uses some sort of algorithm to calculate those values and flash them into the CPU. However, I could definitely change the trip points.

I initially went the “set up a kernel compile environment and compile the dtb files from there” route, however, that’s not required. Just mount the OS SD card, and go to its /boot/dts/. Decompile the SoPine file:

dtc -I dtb -O dts -f sun50i-a64-sopine-baseboard.dtb -o sun5i-a64-sopine-baseboard.dts

Ctrl+F (or Ctrl+W if you’re in nano) for “thermal”, you’ll see a “trips {“ section. Start with cpu_alert0, change the “temperature” section to something large in hexadecimal, like, 230000 (230 degrees) => 0x38270, and also up the next alerts to, say, 240000 (0x3a980) and 250000 (0x3d090):

Then, compile the dts file back into a dtb file:

dtc -I dts -O dtb -o sun5i-a64-sopine-baseboard.dtb sun50i-a64-sopine-baseboard.dts

You might need to compile with sudo since you’re replacing a file owned by root on the SD card’s filesystem. That should set trippoints to a value larger than the bogus value returned by the sensors.

In the end, I successfully booted into the latest OS!

root@pine64so:~# armbianmonitor -m
Stop monitoring using [ctrl]-[c]
Time CPU load %cpu %sys %usr %nice %io %irq CPU C.St.

13:16:25: 1008MHz 0.37 24% 2% 2% 0% 18% 0% 198.5°C 0/7
13:16:30: 1008MHz 0.34 1% 0% 0% 0% 1% 0% 198.2°C 0/7

That’s one hot CPU. Shame it can’t be used as a space heater – with how little SoPine consumes while heating up the CPU so much, I could really save on my heating bills. Oh, BTW – temps stayed at 199 even after an apt dist-upgrade that heated the CPU up quite a bit.

Oh, also – any OS upgrade (with apt dist-upgrade) might install a new version of dtb files that’ll set the trip points back to normal. I should consider some kind of long-term solution to this issue.

Also, I took my .dts files from the mainline kernel tree, and with them, I2C wouldn’t work on SoPine – there was only /dev/i2c-0, and cat /sys/class/i2c-adapter/i2c-0/name highlighted that it’s the HDMI I2C port. I needed to 1) enable the I2C ports in the .dts files and compile 2) add external I2C pullup resistors, since my SoPine board didn’t have any pullup resistors on the Pi header I2C pins. The symptom was that the “i2cdetect -y 1” command ran painfully slow and didn’t show any devices attached even if there were some sensors hooked up to the pins.