public inbox for linux-iio@vger.kernel.org
 help / color / mirror / Atom feed
From: Muchamad Coirul Anwar <muchamadcoirulanwar@gmail.com>
To: Jonathan Cameron <jic23@kernel.org>,
	Lars-Peter Clausen <lars@metafoo.de>,
	Miguel Ojeda <ojeda@kernel.org>
Cc: Frank Zago <frank@zago.net>,
	linux-iio@vger.kernel.org, rust-for-linux@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	Muchamad Coirul Anwar <muchamadcoirulanwar@gmail.com>
Subject: [RFC PATCH] [RFC PATCH] iio: position: rust: add initial AS5600 driver
Date: Sun, 19 Apr 2026 22:13:27 +0700	[thread overview]
Message-ID: <20260419151327.26306-1-muchamadcoirulanwar@gmail.com> (raw)

This RFC introduces an initial Rust implementation for the ams OSRAM AS5600 magnetic rotary position sensor. The current scope covers I2C communication, device probing, and strict parsing of the AGC (Automatic Gain Control) hardware status.

For context, a C-based driver was proposed by Frank Zago in 2021 (Link: https://lore.kernel.org/linux-iio/20211216202651.120172-1-frank@zago.net/), but it was not merged. This fresh Rust implementation takes a stricter approach to probing by enforcing mandatory validation of the STATUS (0x0B) register. It gracefully aborts with -ENODEV if a valid diametrical magnet is not detected.

I have intentionally deferred exposing the IIO channels (in_angl_raw and scale) to avoid writing raw unsafe C FFI bindings. Full sysfs support will be added in a V2 once the safe Rust IIO abstractions land upstream.

Testing was performed on kernel v7.0.0-rc3 using a BeagleBone Black (AM335x) on i2c-2 (0x36) operating at 3.3V.

Testing logs verifying probe behavior and AGC logic via sysfs bind/unbind:

No magnet or magnetic field out of range:
$ echo 2-0036 > /sys/bus/i2c/drivers/as5600/bind
[ 1928.138249] as5600 2-0036: AS5600: No magnet detected

(Probe aborted, safely returns -ENODEV)
Magnet pushed too far (weak field):
$ echo 2-0036 > /sys/bus/i2c/drivers/as5600/bind
[ 1966.130616] as5600 2-0036: AS5600: Magnet too weak
[ 1966.135628] as5600 2-0036: AS5600: Sensor probed, driver ready

Magnet placed too close (strong field):
$ echo 2-0036 > /sys/bus/i2c/drivers/as5600/bind
[ 1988.541979] as5600 2-0036: AS5600: Magnet too strong
[ 1988.547183] as5600 2-0036: AS5600: Sensor probed, driver ready

Optimal diametrical spot:
$ echo 2-0036 > /sys/bus/i2c/drivers/as5600/bind
[ 1977.527490] as5600 2-0036: AS5600: Sensor probed, driver ready

Signed-off-by: Muchamad Coirul Anwar <muchamadcoirulanwar@gmail.com>
---
 drivers/iio/position/Kconfig   | 13 +++++++
 drivers/iio/position/Makefile  |  1 +
 drivers/iio/position/as5600.rs | 64 ++++++++++++++++++++++++++++++++++
 3 files changed, 78 insertions(+)
 create mode 100644 drivers/iio/position/as5600.rs

diff --git a/drivers/iio/position/Kconfig b/drivers/iio/position/Kconfig
index 1576a6380b53..9d2611a71e33 100644
--- a/drivers/iio/position/Kconfig
+++ b/drivers/iio/position/Kconfig
@@ -6,6 +6,19 @@
 
 menu "Linear and angular position sensors"
 
+config AS5600
+	tristate "ams AS5600 magnetic rotary position sensor"
+	depends on I2C && RUST
+	help	  
+	  Say Y here to build support for the ams AS5600 12-bit
+	  magnetic rotary position sensor.
+
+	  This driver provides hardware validation and I2C probing
+	  in Rust for the AS5600.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called as5600.
+
 config IQS624_POS
 	tristate "Azoteq IQS624/625 angular position sensors"
 	depends on MFD_IQS62X || COMPILE_TEST
diff --git a/drivers/iio/position/Makefile b/drivers/iio/position/Makefile
index d70902f2979d..2d26f6d6ace3 100644
--- a/drivers/iio/position/Makefile
+++ b/drivers/iio/position/Makefile
@@ -4,5 +4,6 @@
 
 # When adding new entries keep the list in alphabetical order
 
+obj-$(CONFIG_AS5600) += as5600.o
 obj-$(CONFIG_HID_SENSOR_CUSTOM_INTEL_HINGE) += hid-sensor-custom-intel-hinge.o
 obj-$(CONFIG_IQS624_POS)	+= iqs624-pos.o
diff --git a/drivers/iio/position/as5600.rs b/drivers/iio/position/as5600.rs
new file mode 100644
index 000000000000..c5aab2230acf
--- /dev/null
+++ b/drivers/iio/position/as5600.rs
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (C) 2026 Muchamad Coirul Anwar <muchamadcoirulanwar@gmail.com>
+//! Driver for ams AS5600 12-bit magnetic rotary position sensor.
+//!
+//! Datasheet: https://ams.com/documents/20143/36005/AS5600_DS000365_5-00.pdf
+
+use kernel::device::Core;
+use kernel::i2c;
+use kernel::module_i2c_driver;
+use kernel::prelude::*;
+
+// AS5600 register addresses (from datasheet v1.06)
+const AS5600_REG_STATUS: u8 = 0x0B;
+const AS5600_REG_RAW_ANGLE_H: u8 = 0x0C; // High nibble [11:8] in bits [3:0]
+const AS5600_REG_RAW_ANGLE_L: u8 = 0x0D; // Low byte [7:0]
+
+// STATUS register bit masks
+const AS5600_STATUS_MH: u8 = 0x08; // Magnet too strong (AGC minimum gain overflow)
+const AS5600_STATUS_ML: u8 = 0x10; // Magnet too weak (AGC maximum gain overflow)
+const AS5600_STATUS_MD: u8 = 0x20; // Magnet detected
+
+module_i2c_driver! {
+    type: As5600,
+    name: "as5600",
+    authors: ["Muchamad Coirul Anwar"],
+    description: "I2C Driver for ams OSRAM AS5600 Magnetic Rotary Position Sensor",
+    license: "GPL",
+}
+
+kernel::i2c_device_table!(
+    I2C_TABLE,
+    MODULE_I2C_TABLE,
+    <As5600 as i2c::Driver>::IdInfo,
+    [(i2c::DeviceId::new(c"as5600"), ())]
+);
+
+struct As5600 {}
+
+impl i2c::Driver for As5600 {
+    type IdInfo = ();
+    const I2C_ID_TABLE: Option<i2c::IdTable<Self::IdInfo>> = Some(&I2C_TABLE);
+
+    fn probe(
+        dev: &i2c::I2cClient<Core>,
+        _id_info: Option<&Self::IdInfo>,
+    ) -> impl PinInit<Self, Error> {
+        let status = dev.smbus_read_byte_data(AS5600_REG_STATUS)?;
+        if (status & AS5600_STATUS_MD) == 0 {
+            dev_err!(dev.as_ref(), "AS5600: No magnet detected\n");
+            return Err(ENODEV);
+        } else if (status & AS5600_STATUS_MH) != 0 {
+            dev_warn!(dev.as_ref(), "AS5600: Magnet too strong\n");
+        } else if (status & AS5600_STATUS_ML) != 0 {
+            dev_warn!(dev.as_ref(), "AS5600: Magnet too weak\n");
+        }
+
+        dev_info!(dev.as_ref(), "AS5600: Sensor probed, driver ready\n");
+        Ok::<_, Error>(As5600 {})
+    }
+
+    fn unbind(dev: &i2c::I2cClient<Core>, _this: Pin<&Self>) {
+        dev_info!(dev.as_ref(), "AS5600 Sensor Driver Unbound\n");
+    }
+}
-- 
2.50.0


             reply	other threads:[~2026-04-19 15:13 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-19 15:13 Muchamad Coirul Anwar [this message]
2026-04-20 18:33 ` [RFC PATCH] [RFC PATCH] iio: position: rust: add initial AS5600 driver Jonathan Cameron
2026-04-21  9:49   ` Miguel Ojeda

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260419151327.26306-1-muchamadcoirulanwar@gmail.com \
    --to=muchamadcoirulanwar@gmail.com \
    --cc=frank@zago.net \
    --cc=jic23@kernel.org \
    --cc=lars@metafoo.de \
    --cc=linux-iio@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=ojeda@kernel.org \
    --cc=rust-for-linux@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox