Skip to content

Day22 - I2C hwmon Driver with Polling Mode

Objective

Enhance the Day21 hwmon I2C sensor driver by adding:

  • background polling with delayed work
  • cache-only hwmon read path when polling is enabled
  • sysfs controls for polling
  • fallback to on-demand mode when polling is disabled

Environment

  • Target board: Raspberry Pi 5
  • Kernel: Raspberry Pi Linux 6.12.x
  • Driver: myi2c_sensor
  • Sensor side: STM32 fake I2C sensor device
  • Interface: I2C + hwmon

Features Implemented

Polling worker

A delayed workqueue periodically:

  1. sends update command to sensor
  2. reads raw temperature registers
  3. converts raw value to milli-degree Celsius
  4. updates internal cache

hwmon read path

temp1_input behavior:

  • polling enabled:
  • read cached value only
  • return -EAGAIN if cache is not ready
  • polling disabled:
  • fallback to on-demand update logic

Sysfs attributes

Driver-specific attributes:

  • chip_id
  • temp_raw
  • config
  • status
  • update_period
  • update_once
  • cache_interval
  • polling_enable
  • polling_interval

Standard hwmon attribute:

  • temp1_input

Implementation Notes

New driver fields

Added to struct myi2c_sensor_data:

struct delayed_work poll_work;
bool polling_enable;
unsigned int polling_interval_ms;

Background polling callback

Polling worker:

  • locks driver state
  • performs sensor update
  • updates cache
  • reschedules itself if polling remains enabled

Read path

The hwmon read callback uses myi2c_sensor_read_temp_mc().

Behavior:

  • polling enabled -> cache-only
  • polling disabled -> update if needed

Build

Example:

make

If needed:

make clean
make

Load Driver

Example:

sudo insmod myi2c_sensor.ko
dmesg | tail -n 30

Expected result:

  • probe succeeds
  • chip ID check passes
  • hwmon device is registered
  • first polling work is scheduled

Find hwmon Node

Example:

ls /sys/class/hwmon/
for d in /sys/class/hwmon/hwmon*; do
    echo "== $d =="
    cat "$d/name"
done

Find the hwmon node whose name is:

myi2c_sensor

Basic Read Test

Example:

cat /sys/class/hwmon/hwmonX/temp1_input

Possible early result:

cat: temp1_input: Resource temporarily unavailable

This means cache is not valid yet and the driver returned -EAGAIN.

Retry after a short delay:

sleep 1
cat /sys/class/hwmon/hwmonX/temp1_input

Check Polling Controls

Example:

cat /sys/class/hwmon/hwmonX/polling_enable
cat /sys/class/hwmon/hwmonX/polling_interval

Enable Polling

Example:

echo 1 | sudo tee /sys/class/hwmon/hwmonX/polling_enable

Disable Polling

Example:

echo 0 | sudo tee /sys/class/hwmon/hwmonX/polling_enable

Expected behavior:

  • background updates stop
  • temp1_input falls back to on-demand update logic

Change Polling Interval

Example:

echo 1000 | sudo tee /sys/class/hwmon/hwmonX/polling_interval
echo 3000 | sudo tee /sys/class/hwmon/hwmonX/polling_interval

Expected behavior:

  • shorter interval -> more frequent refresh
  • longer interval -> slower cache updates

Debug Raw Temperature Path

Example:

cat /sys/class/hwmon/hwmonX/temp_raw

This path performs direct access to the sensor and is intended for debugging.


Manual Update

Example:

echo 1 | sudo tee /sys/class/hwmon/hwmonX/update_once

This is useful for:

  • debug
  • manual refresh
  • verifying device response

Test Script

A helper script was used to verify:

  • polling enable/disable
  • polling interval effect
  • cache-only hwmon behavior

Example:

./test_polling.sh /sys/class/hwmon/hwmonX

The script checks:

  1. enable polling
  2. set polling interval
  3. read temp1_input repeatedly
  4. disable polling
  5. enable polling again

Observed Result

Observed behavior matched expectation:

  • polling mode updated cached values periodically
  • changing polling interval affected update frequency
  • disabling polling stopped periodic updates
  • re-enabling polling resumed updates
  • hwmon path operated correctly

Conclusion

Day22 successfully migrated the driver from a purely read-triggered update model to a polling-based cached model.

This completes the second active update model in the learning path:

  • Day21: on-demand
  • Day22: polling
  • Day23: interrupt-driven (planned)