[RFC PATCH v5 0/3] iio: position: add Rust driver for ams AS5600

Muchamad Coirul Anwar <[email protected]>
Newsgroups org.kernel.vger.linux-i2c,org.kernel.vger.linux-iio,org.kernel.vger.linux-kernel,org.kernel.vger.rust-for-linux
Message-ID <[email protected]>
This is v5 of the Rust driver for the ams AS5600 12-bit magnetic rotary
position sensor.

Link: https://lore.kernel.org/linux-iio/[email protected]/

Base tree and dependencies:

  This series is based on driver-core-testing [1], not vanilla rust-next.
  It depends on Gary Guo's io_projection-v6 [2] for IoBackend, IoBase,
  Region, and KnownSize.

  FallibleIoCapable is included in patch 1/3 following Danilo's
  suggestion [3] to carry it as a prerequisite until it lands upstream.

  [1] https://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core.git/log/?h=driver-core-testing
  [2] https://lore.kernel.org/driver-core/[email protected]/
  [3] https://lore.kernel.org/all/[email protected]/

Changes since RFC v4:

  I2C abstraction:
  - Switch to FallibleIoCapable — IoCapable is infallible by design,
    but I2C can fail at transport level (Igor)
  - Restrict I/O ops to I2cClient<Bound> (Danilo)
  - Add smbus_read_word() and smbus_read_word_swapped() for odd offsets
  - Add FallibleIoCapable trait to io.rs with blanket impl
  - Add bit_usize() to bits.rs

  IIO abstraction:
  - Replace raw isize mask with IioChanInfo enum (Nuno)
  - Expand PinnedDrop SAFETY comment re: kernfs_drain() (Danilo)
  - build_device() takes modes parameter instead of hardcoding
  - channels() now returns &'static slice

  Driver:
  - Use smbus_read_word_swapped() instead of manual swap_bytes()
  - Use ARef<I2cClient<Bound>> (Danilo)
  - Drop pr_info! debug logging
  - Kconfig cleanup (Jonathan)

  Known limitations (unchanged):
  - No power management
  - No write_raw, buffer, or trigger support

Design notes:

  The IIO abstraction uses iio_device_alloc (not devm_*) so the Rust
  Drop controls cleanup ordering: unregister, drop driver data, then
  free iio_dev.

  iio_device_unregister() drains in-flight sysfs reads via kernfs_drain().
  This is sufficient for INDIO_DIRECT_MODE without buffer/trigger.
  Character device paths need separate analysis.

  Module ownership via __iio_device_register(), not iio_info.owner.

Muchamad Coirul Anwar (3):
  i2c: rust: implement SMBus access via IoBackend and FallibleIoCapable
  rust: add minimal IIO subsystem abstractions
  iio: position: add Rust driver for ams AS5600

 drivers/iio/position/Kconfig    |  11 +
 drivers/iio/position/Makefile   |   1 +
 drivers/iio/position/as5600.rs  | 189 +++++++++++++++++
 rust/bindings/bindings_helper.h |   2 +
 rust/kernel/bits.rs             |  29 +++
 rust/kernel/error.rs            |   1 +
 rust/kernel/i2c.rs              | 302 +++++++++++++++++++++++++++
 rust/kernel/iio.rs              | 384 +++++++++++++++++++++++++++++++++++
 rust/kernel/io.rs               |  66 ++++--
 rust/kernel/lib.rs              |   2 +
 10 files changed, 967 insertions(+), 20 deletions(-)
 create mode 100644 drivers/iio/position/as5600.rs
 create mode 100644 rust/kernel/iio.rs

---
Tested on BeagleBone Black (AM335x), kernel 7.2.0-rc1+,
AS5600 on i2c-2 (0x36) at 3.3V, 6mm diametric neodymium magnet.
Full test session: 2026-08-17.

Build: make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- modules
       (zero warnings, zero errors)

Functional tests:

  1. Probe and registration:
     $ sudo insmod as5600.ko
     $ echo "as5600 0x36" > /sys/bus/i2c/devices/i2c-2/new_device
     $ cat /sys/bus/iio/devices/iio:device0/name
     as5600
     $ ls /sys/bus/i2c/devices/2-0036/driver
     2-0036  bind  module  uevent  unbind

  2. Raw angle and scale (magnet present):
     $ cat /sys/bus/iio/devices/iio:device0/in_angl_raw
     3366
     $ cat /sys/bus/iio/devices/iio:device0/in_angl_scale
     0.001533981
     20 consecutive reads, all within 0-4095.
     Computed: 3366 * 0.001533981 = 5.163 rad (~295.9 degrees).

  3. Unbind/rebind lifecycle (PinnedDrop with ARef cleanup):
     $ echo "2-0036" > /sys/bus/i2c/devices/2-0036/driver/unbind
     $ ls /sys/bus/iio/devices/iio:device0 2>&1
     ls: cannot access '...': No such file or directory
     $ echo "2-0036" > /sys/bus/i2c/drivers/as5600/bind
     $ cat /sys/bus/iio/devices/iio:device0/name
     as5600
     $ dmesg | grep -i "oops\|panic\|bug:"
     (empty)

  4. Concurrent stress (Mutex serialization under contention):
     10 parallel readers hammering in_angl_raw for 5 seconds.
     Repeated as 20-cycle unbind/rebind loop with readers active
     throughout (8 seconds total).
     $ dmesg | grep -i "oops\|panic\|bug:\|rcu"
     (empty)

  5. Module removal under active I/O:
     a) rmmod while flood readers are running — no crash.
        iio_device_unregister() drains in-flight read_raw callbacks
        before PinnedDrop proceeds; subsequent reads return ENOENT.
     b) rmmod while a sysfs fd is held open — no crash.
        iio_dev kref not released until fd is closed.
     $ dmesg | grep -i "oops\|panic\|bug:"
     (empty)

  6. Lifecycle stress:
     50x rapid unbind/rebind — no crash, device functional after all
     cycles.
     50x insmod/rmmod — no crash.
     $ dmesg | grep -i "oops\|panic\|bug:"
     (empty)

  7. I2C bus disconnect:
     SCL/SDA physically pulled while read loop is running. Driver
     returns "Remote I/O error" immediately on each failed transfer;
     no hang, no internal retry loop. Cable reconnected — reads resume
     from the next iteration without rmmod (about 2 seconds downtime).
     rmmod issued while bus still in error state — exits cleanly.
     ARef<I2cClient> drop is put_device() only, no bus transaction.
     $ dmesg | grep -i "oops\|panic\|bug:"
     (empty)

  8. Memory and locking:
     dmesg contains no strings matching "KASAN:" or "possible deadlock".
     The test kernel was not built with CONFIG_KASAN or CONFIG_PROVE_LOCKING;
     the above is a pattern match against kernel log output, not sanitizer
     or lockdep instrumentation.
     kmemleak not available (CONFIG_DEBUG_KMEMLEAK not set).

-- 
2.50.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.