Zephyr EC Temperature Sensors

Overview

Temperature sensors are critical for monitoring the operating temperature of the device and taking action if temperatures rise beyond safe levels by throttling or shutting down the AP.

Zephyr-supported Temperature Sensors

PartFileDescription
F75303include/driver/temp_sensor/f75303.hSMBus / I2C temperature sensor
PCT2075include/driver/temp_sensor/pct2075.hSMBus / I2C temperature sensor
SB_TSIinclude/driver/temp_sensor/sb_tsi.hI2C temperature sensor on AMD Stony Ridge FT4 SoC
TMP112include/driver/temp_sensor/tmp112.hSMBus / I2C temperature sensor
Thermistorsinclude/driver/temp_sensor/thermistor.hVarious analog thermistor configurations

See zephyr/shim/include/temp_sensor/temp_sensor.h.

Supported Thermistor Configurations

  • thermistor_3V3_30K9_47K_4050B
  • thermistor_3V0_22K6_47K_4050B
  • thermistor_3V3_13K7_47K_4050B
  • thermistor_3V3_51K1_47K_4050B

See zephyr/include/cros/thermistor/thermistor.dtsi and zephyr/test/drivers/boards/native_sim.overlay.

Legacy EC Temperature Sensors

These models have drivers written for the legacy EC code, but would need further work to adapt to Zephyr.

Part #FileDescription
ADT7481driver/temp_sensor/adt7481.hSMBus / I2C 3-channel temperature sensor (local + 2x remote)
R19ME4070driver/temp_sensor/amd_r19me4070.hAMD GPU, but has an onboard temperature sensor.
BD99992GWdriver/temp_sensor/bd99992gw.hThis is a PMIC, but has an onboard temp sensor.
F75303driver/temp_sensor/f75303.hSMBus / I2C 3-channel temperature sensor (local + 2x remote)
G781/G782driver/temp_sensor/g78x.hSMBus / I2C 2-channel temperature sensor (local + remote)
G753driver/temp_sensor/g753.hSMBus / I2C single-channel temperature sensor
OTI502driver/temp_sensor/oti502.hI2C ambient plus infrared temperature sensor
PCT2075driver/temp_sensor/pct2075.hI2C temperature sensor
SB-TSIdriver/temp_sensor/sb_tsi.hI2C temp sensor on the AMD Stony Ridge FT4 SOC
NCP15WBdriver/temp_sensor/thermistor_ncp15wb.cNTC thermistor (used with ADC)
TMP006driver/temp_sensor/tmp006.hSMBus / I2C infrared temperature sensor
TMP411driver/temp_sensor/tmp411.hSMBus / I2C 2-channel temperature sensor (local + remote)
TMP432driver/temp_sensor/tmp432.hSMBus / I2C 2-channel temperature sensor (local + remote)
TMP468driver/temp_sensor/tmp468.hSMBus / I2C 9-channel temperature sensor (local + 8x remote)

Kconfig Options

Overall support for temperature sensors is enabled using the config flag PLATFORM_EC_TEMP_SENSOR. See zephyr/Kconfig.temperature for more information. A separate config flag, PLATFORM_EC_THERMISTOR, is needed if analog thermistor sensors are being used. This option is dependent on ADCs being supported. These flags are configured in each board’s prj.conf file.

There are no sensor-specific Kconfig options for specifying sensor types, drivers, or configuration. This is handled by the device tree (see below) on Zephyr-based boards.

Device Tree Nodes

Temperature sensors are declared as separate nodes and additional properties are defined by the cros-ec,temp-sensors node in the device tree. This example is from zephyr/program/rex/temp_sensors.dtsi:

	temp_ddr_soc: ddr_soc {
		compatible = "cros-ec,temp-sensor-thermistor";
		thermistor = <&thermistor_3V3_30K9_47K_4050B>;
		adc = <&adc_temp_sensor_1>;
	};
...
	named-temp-sensors {
		compatible = "cros-ec,temp-sensors";
		ddr_soc {
			temp_fan_off = <35>;
			temp_fan_max = <60>;
			temp_host_high = <85>;
			temp_host_halt = <90>;
			temp_host_release_high = <80>;
			sensor = <&temp_ddr_soc>;
		};
		...

More information about temperature sensor device tree settings can be found in the following locations:

Thermistors

In addition to setting up the sensors, each type of supported thermistor needs to have calibration data saved in the device tree that is used to compute temperature values from the ADC counts / measured voltages. Example from zephyr/include/cros/thermistor/thermistor.dtsi.

This must only be done once for each type of thermistor. Most boards should be covered by one of the existing types and can simply reference them in the device tree named-temp-sensors nodes.

	thermistor_3V3_30K9_47K_4050B: thermistor-3V3-30K9-47K-4050B {
		status = "disabled";
		compatible = "cros-ec,thermistor";
		scaling-factor = <11>;
		num-pairs = <10>;
		steinhart-reference-mv = <3300>;
		steinhart-reference-res = <30900>;
		/*
		 * Data derived from Steinhart-Hart equation in a resistor
		 * divider circuit with Vdd=3300mV, R = 30.9Kohm, and thermistor
		 * (B = 4050, T0 = 298.15 K, nominal resistance (R0) = 47Kohm).
		 */
		sample-datum-0 {
			milivolt = <(2753 / 11)>;
			temp = <0>;
			sample-index = <0>;
		};
		sample-datum-1 {
			milivolt = <(2487 / 11)>;
			temp = <10>;
			sample-index = <1>;
		};
		/* . . . */

Thermistor Circuit

Type thermistor_3V3_30K9_47K_4050B corresponds to this circuit:

Schematic of a thermistor voltage divider

The thermistor naming scheme is as follows:

  • 3V3 - The voltage divider is supplied from a 3.3V rail.
  • 30K9 - The high side of the voltage divider is a 30.9K ohm resistor.
  • 47K - The nominal thermistor resistance (R_0) is 47K ohm.
  • 4050B - Coefficient B in the Steinhart–Hart thermistor equation is 4050.

Board-specific code

No board-specific code is required. Temperature sensors are automatically configured based on information in the device tree.

Threads

There is no dedicated thread for monitoring temperature sensors. The sensor data is ultimately consumed by the thermal engine’s thermal_control() function in common/thermal.c, which runs every second in the TICK thread by registering it as a callback with the Hook API.

The mechanism for pulling in temperature data depends on the type of sensor:

Thermistors

Thermistor-based temperature sensor readings are measured and processed on-the-fly whenever requested, so the TICK thread reads from the ADC directly during the thermal_control() routine.

I2C-based Sensors

Most I2C-based sensors involve an extra step. Their drivers separately set up an internal function to run on a one second interval (also on the TICK task using the Hook API). For example, the TMP006 does this in tmp006.c:

static void tmp006_poll(void)
{
	int i;

	for (i = 0; i < TMP006_COUNT; ++i)
		tmp006_poll_sensor(i);
}
DECLARE_HOOK(HOOK_SECOND, tmp006_poll, HOOK_PRIO_TEMP_SENSOR);

The poll function only updates an internal struct within the driver with the latest reading(s). These values then get read by the thermal engine through the same, standard API as the thermistors. This spares the thermal routine from having to wait on I2C accesses.

However, not all temperature sensor drivers follow this approach. For instance, the SB-TSI driver simply performs the I2C transaction to read the temperature directly in the public sb_tsi_get_val() function.

Testing and Debugging

Temperature sensors can be queried with the temps console command:

> temps
  Charger             : 303 K = 30 C
  SOC                 : 303 K = 30 C
  CPU                 : 301 K = 28 C