evidence · 5.2 KiB

thermal.md

Committed at docs/thermal.md. This is what grounds the requirements that cite it.

Open raw source

Thermal protection on the K230: what exists, and what does not

Prompted by a direct question — whether it is safe to leave the board powered unattended. Short answer: the temperature is readable, and nothing acts on it. No throttling, no shutdown. That is a property of the vendor kernel and device tree, not of anything we configured.

All symbol evidence below is from System.map of our own build, linux-riscv64-unknown-linux-gnu-6.6.36-xuantie.

What works

The sensor has a driver, and it is built in.

t canaan_thermal_probe
t canaan_thermal_init
d __initcall__kmod_canaan_thermal__258_122_canaan_thermal_init6
d of_canaan_thermal_match

drivers/thermal/canaan_thermal.c, enabled by CONFIG_CANAAN_THERMAL, which is default ARCH_CANAAN and so comes in without being named in k230_defconfig. It matches tsensor@91107000, compatible = "canaan,k230-tsensor", which is status = "okay" in k230.dtsi:850.

The thermal core is built in — 306 thermal* symbols, including thermal_zone_device_register_with_trips and thermal_zone_device_critical, the emergency-shutdown path.

/sys/class/thermal/thermal_zone0 exists on the booted board and reads:

/sys/class/thermal/thermal_zone0 canaan_thermal_zone 7179

But that number is not a temperature. See below.

The reading is a raw sensor code, not millidegrees

canaan_get_temp() does no conversion at all:

while (1) {
	val = ioread32(data->base + TS_DATA);
	if (val >> 12) {
		*temp = val;
		break;
	}
}

*temp is the raw TS_DATA register. The sysfs contract for thermal_zone*/temp is millidegrees Celsius, so 7179 would be read by any standard consumer as 7.2 °C — implausible for a running SoC. It is neither 7.2 °C nor 71.8 °C; it is an uncalibrated ADC code with no published transfer function in the driver.

Two consequences:

Also worth noting: that while (1) has no timeout or iteration cap. If val >> 12 never becomes non-zero the read spins forever in kernel context. It has not been observed to hang, but nothing prevents it.

What does not work, and why

1. The driver registers a zone with no trip points, deliberately.

canaan_thermal.c:86:

data->tz = thermal_tripless_zone_device_register(

thermal_tripless_* is exactly what it says. A zone with no trips never crosses a trip, so the thermal core never invokes a governor and never calls thermal_zone_device_critical(). The driver is a thermometer.

2. No device tree supplies trips either. There is no thermal-zones node in any K230 device tree in the Xuantie tree — the usual place a board declares trip-point / critical and binds a cooling device. So the gap is not closed from the DT side.

3. There is no cooling device to bind even if a trip existed. The only cpufreq symbol in the kernel is cpufreq_add_device; there is no cpufreq_register_driver, so no cpufreq driver is present and the CPU has no DVFS states Linux can select. The conventional response to a passive trip — throttle the CPU — has nothing to act on.

That leaves a critical trip forcing an orderly poweroff as the only meaningful protection available, and it is not configured.

What this means in practice

Proposed next steps

Cheap, in order:

  1. Read the sensor. cat /sys/class/thermal/thermal_zone*/temp at idle, then after a sustained load, and write both down. This costs one boot and tells us whether the part even runs warm. It may make the rest moot.
  2. Find the hardware limit. The K230 datasheet’s operating range, and whether the TSENSOR block has its own hardware trip independent of Linux. canaan_thermal.c and the hardlock = <2> property in the DT node are the places to look.
  3. Add a critical trip. A thermal-zones node with a critical trip referencing the tsensor, which gives thermal_zone_device_critical() something to fire. This needs step 2 first — a made-up threshold is worse than none, because it either never fires or shuts the board down during normal work.
  4. Only then consider throttling, which means a cpufreq driver and OPP table, and is a substantially larger piece of work for a board that may simply never get hot enough to need it.

Steps 1 and 2 are research. Step 3 is a small change. Step 4 should not be started until 1 and 2 say it is needed.