From nobody Tue Jun 16 19:33:46 2026 Received: from mail-pg1-f173.google.com (mail-pg1-f173.google.com [209.85.215.173]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 82EEA3F54AB for ; Wed, 29 Apr 2026 13:22:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777468977; cv=none; b=uXC3F1/sltJ6UqsAuVQeUEH9luD3aY9Rih0dpAJOqRUT0eyVda8xZ3uKvIxdvgvcvmfYXEp32G+nuEIMF76vmrMd2heHXc3TzYWNAMvhRHM+w4vt61Ea255ZLHaNH0wFFYs1NvNdtnUctSbADLEpNyikHk23SBZHJyKfZ4+Mhfs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777468977; c=relaxed/simple; bh=01DQgwaJ3ce2HaFqHqFVOsD/TYkkeJShpzCaK3dyx4M=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=nTlDfomy3WoRRaIv32B/RUQ/C122/5rfC6DChQbvDjB7lu1UZlhTP865w9Bzbzojmj9fNk1rmDxMB1zfmxS9Q4PB8QjDxKFp0IgPmvNtdh4ZTSG1WLguufFPE0nTQ7ecZTREocq3ALy3enlcFnZc/566qcmBDM3XHej4umS5XSM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=EvMG5VKB; arc=none smtp.client-ip=209.85.215.173 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="EvMG5VKB" Received: by mail-pg1-f173.google.com with SMTP id 41be03b00d2f7-c7973bbc16dso8282343a12.0 for ; Wed, 29 Apr 2026 06:22:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777468974; x=1778073774; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=DZTB0k5HzoHvpW2eiYdnzwypWK5KqzxoJlBxqEnFu+U=; b=EvMG5VKByiGkhnQNWvlq+k0VssqHnbUaCTMi9hYZGr5HsGBTfAbPCehd6dav8zCxrT pEBNgmNaUjIMMJwpKrk+ON+TNvPiZNmzIgWnv67s3t0yQDwFeJHwxyKqcPzl8J5IF/5+ CxAn3MHz3z38B8lSfbrrFwCOAGgRxi4AfcHvQz3y0VaOz8iAmMxexzltu/abDGMC5Bkb /gY5ZsB4GWg2EQN0HsqNGvJ9IE2htbmU3mySv2CaSNbo33rhwGC8Va9lzMGHvgWfmv8i 1DuQkKsqmFFby4XI61DW8XFwUj8Kz2+SMcLm0MZ6d9PeZU1x/kUCZXYIgnEEp18tQBR9 8ccw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777468974; x=1778073774; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=DZTB0k5HzoHvpW2eiYdnzwypWK5KqzxoJlBxqEnFu+U=; b=im2wqOg9v/8kxIMFBoXtuiFr0eUgOuIWwTMqBSJcylP8vX44FXgKwJYGqePIGzooHY 5bAlW8JZCbO9aaBURV/87Tu59BtDDWKRsB/68GdrPpqo8nI09sPY/V+XcWNPYtA8F/0a tx/LsvGnNsKzE8dRxYeEpSTTLXlWpKnj6dhWZzQu3WVYn7EsBzrhWCrI7iQXS4aiZeum VZDUuje9mLZ2/ihRBh3JXwHqcl2+qYolvuf8jeraIiIz3Sk7BHWg0J4NDEuNToxzuUZv 64PRDzMxQirOVTDETi6LfA4WIBd0123j/LdYyb78JRy6dIAsoEsIQOFJSEPEedXMgtuU 1vXA== X-Forwarded-Encrypted: i=1; AFNElJ+FfvsHxjSh2BBo3wO4FKR2RiamWYlgSo9qZtSW32aNdtzCBxZaLMS1ilk7l/nKvC+9NRvSFVvQ1yOpkF4=@vger.kernel.org X-Gm-Message-State: AOJu0YzomBJZgqNpKfin6aAWQn9CExlIAE7Xa2OzJ9o8/WSXBgqALmWZ uv+42zaWKQHD7de/FgHD0JS8CHWZTqw3rhIqSlfTa+7ff5Dt6/2ZgBGr X-Gm-Gg: AeBDieu1JLd2NT52N1XIrieQkIv+xrEaGsqjfWFb/06qEyyV1m2gHEXAvMaw+JsZVDn hgjIgLAswIHtP4L1PG4hfoLisf59b4tL1m5CRkOaUtz3tbhdXUdw45PHxyvJiXxwvz1eiNFJul9 D2Y+T6wmdqXxVb6dHKsYs5D1be7AfCJRpIBaGUkonAsfYPYgJb/jA3fJXODwi44SbPijT0o0BNC 2UVK6H7N4XHOMllmwe4emsTVIxKwqWBRUzeZil61Vz7hawDk17wH5OwYjfXjzq6IhcSh5eekzsR xGA2a4cO+nKYUI7TAh6PufxtNs3o9Bh6WBcczf2rXLEoQgR+gzdF05lI7fj6pIsAEamgaNbg0HY GFGA2OoLzdD4Go4raIsb7sgal6ASIeCTLIvJp6/PAzaa6Gu/1XL4Q8MiF9ljv2u1FzV+bjSmM5T P1lp96IXikl1M3tgk4IzNZhuxoK8+iF5zGEXwdgvi3PHq0MtQxoj77eOqeEn5fcKRLmkEisx++X atWUArFJUwzWO+JL5NBJRoPqA== X-Received: by 2002:a05:6a21:9981:b0:3a3:472b:2e6a with SMTP id adf61e73a8af0-3a39c058afcmr8013894637.18.1777468973973; Wed, 29 Apr 2026 06:22:53 -0700 (PDT) Received: from localhost.localdomain ([2001:448a:2002:4381:3859:fd0d:505e:362c]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-834ed5cd407sm2091372b3a.13.2026.04.29.06.22.47 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Wed, 29 Apr 2026 06:22:53 -0700 (PDT) From: Muchamad Coirul Anwar To: jic23@kernel.org, linux-iio@vger.kernel.org, rust-for-linux@vger.kernel.org, devicetree@vger.kernel.org Cc: branstj@gmail.com, lars@metafoo.de, ojeda@kernel.org, robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org, igor.korotin.linux@gmail.com, linux-kernel@vger.kernel.org, Muchamad Coirul Anwar Subject: [RFC PATCH v2 1/4] i2c: rust: add smbus_read_byte_data and smbus_read_word_data Date: Wed, 29 Apr 2026 20:22:27 +0700 Message-ID: <20260429132234.30514-2-muchamadcoirulanwar@gmail.com> X-Mailer: git-send-email 2.50.0 In-Reply-To: <20260429132234.30514-1-muchamadcoirulanwar@gmail.com> References: <20260429132234.30514-1-muchamadcoirulanwar@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Signed-off-by: Muchamad Coirul Anwar --- rust/kernel/i2c.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/rust/kernel/i2c.rs b/rust/kernel/i2c.rs index 7b908f0c5a58..6eaea1158fda 100644 --- a/rust/kernel/i2c.rs +++ b/rust/kernel/i2c.rs @@ -477,6 +477,30 @@ impl I2cClient { fn as_raw(&self) -> *mut bindings::i2c_client { self.0.get() } + + /// Reads a single byte from a register via SMBus. + pub fn smbus_read_byte_data(&self, reg: u8) -> Result { + // SAFETY: `self.as_raw()` is a valid pointer to a `struct i2c_cli= ent` + // by the type invariant of `I2cClient`. + let ret =3D unsafe { bindings::i2c_smbus_read_byte_data(self.as_ra= w(), reg) }; + if ret < 0 { + Err(Error::from_errno(ret)) + } else { + Ok(ret as u8) + } + } + + /// Reads a 16-bit word from a register via SMBus. + pub fn smbus_read_word_data(&self, reg: u8) -> Result { + // SAFETY: `self.as_raw()` is a valid pointer to a `struct i2c_cli= ent` + // by the type invariant of `I2cClient`. + let ret =3D unsafe { bindings::i2c_smbus_read_word_data(self.as_ra= w(), reg) }; + if ret < 0 { + Err(Error::from_errno(ret)) + } else { + Ok(ret as u16) + } + } } =20 // SAFETY: `I2cClient` is a transparent wrapper of `struct i2c_client`. --=20 2.50.0 From nobody Tue Jun 16 19:33:46 2026 Received: from mail-pf1-f170.google.com (mail-pf1-f170.google.com [209.85.210.170]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3A1103FE67D for ; Wed, 29 Apr 2026 13:23:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.170 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777468984; cv=none; b=DwPRnk3vXkwon6ZsDqE/dkmkiyIriFyfLHTIKaVVfVuIr48QumrRt3o5MnwL3LuY2jQfWgnAz7qsINiLLDUbKjx7g6C/1ZRRyTg7+gGtTlKJyDd5C3PNy06vcx5X9XKknplZnZDfSCgz1PMHlmd/Rct07MKBThGOE2E0DPP0mYI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777468984; c=relaxed/simple; bh=gczVuAShdEGpAOX27PF16GmBdqERLGb5Ax6/ItUK9YQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=iuPpfl+NDcG+ey+/LeiMye7t000LFpmKuWjD9/FSHlN/s+JRuXm9S/t5ZPzyxtkgcXxlNKeX408i1RHlnT8rk57mk1X77vUmoSW6p40s5aFAr7Z8fgO8VNyMrMdVmavSvpL3KUeYfRTSpOhOsjtB/Ic9InkJKMipZGK9igfvmrY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Acgbd25z; arc=none smtp.client-ip=209.85.210.170 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Acgbd25z" Received: by mail-pf1-f170.google.com with SMTP id d2e1a72fcca58-82f943870baso5387744b3a.1 for ; Wed, 29 Apr 2026 06:23:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777468983; x=1778073783; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Zk/HPFBK4IBkCNGG/AGyeD13qmMu2NSM3WquJIJ4QH8=; b=Acgbd25zS4d6QKVVjX6aSYyMdu5Z7lO/fvh1ZPHuSoWXV1IMtEyNP8BHvmBKv/OJK+ OWQtHYmmYHoDv9kdZgxjmWnAVoKqGRA0b9orlds63l/M2eTrgBgz5Z5OSf9r9+F2En2u Cdqgif7oOUFO+X5Z6ScF2yHBP5hjgUQA6Hj9/9MnEsNJcsC8dtHSLhuJE50V+HGK+Ec0 NKX4wrIUP0zmdA0Yuq3JJCrU1gE8ZiVbMiZqqGtENEJf2oqbOqwU9d4W8OqCIECcoK/Y cYoP9Tz+VRc/x5fg1G0LikDJIu4wx3W2Ifd7430ZjBmCErSqufVOthg2Ky9dfGqPSfcM dJgw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777468983; x=1778073783; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=Zk/HPFBK4IBkCNGG/AGyeD13qmMu2NSM3WquJIJ4QH8=; b=qs/OIMzEJjpztaFhLhr6pwRvUKMGHiJ0HsTkGbI7so/J9NRQ74xczdedo8w8PYx96y fvmeoTrTKeO4f4g6dGU5LSvoLDhOwGScIBfmISPOpIEPtwOwOQFtzQfVmFcMKnjJU6Eb hVdzEUbiccQIM3LZYggKvWAHPr3Y06J2M7l844UxpamRVIULuxKd3FjMnEzl3Avhywtb LATXrXhC1JvQCJDzOxO8/RnO6LzhcrTgj9OIFI7HV2pG4yW3hk5j1ogAWw/vhLz80SOi dkgtY2m8y6JYXw8//4jIwewtPFi94D8T6Zgm32urIG28AYqPKXfNubfQ3a9+ZtgTiaGS iZdQ== X-Forwarded-Encrypted: i=1; AFNElJ9SImaf+yY5pyZyB9TRRbHjKmlWNw2+AT/9DSj0/JtK/v7DPsGcTvi+woo+wS5sWvLjpjmde/RXHCthc2c=@vger.kernel.org X-Gm-Message-State: AOJu0Yx+2j0QqzEJ32SXhh2Xx0+gHlYEfSpSOSkHk5ZqX+I2hmmxbxuH 6t3ZKQZZT9pG8IODkcgai9TVctMJIaM11UrxOAB8uVwXH0STcoiwcfoS X-Gm-Gg: AeBDietwFtyyp0qUj/VtWbHTStdK01qSI/IZtiv6lLjm5dtZw3UOV2ZRkf0JkLsqozC pO89qXa53TAmO21vggGQ6bGLnES1wpTk9LZavuoIqFbZElJN0Bo0UXjT/O3iMIReW0IBeV8kagZ vS1qPEKb8p2JAVuzIlmWx6s+T3a5ZM0V1/75Ozms3cIitMIKxWjki02UuPy6F3S6Rsdcd3ScsPt wI5lmxAWXEN8RqzOiv3NaYcmi6HYrHpmVJCGyo2DefZ8VrPfxGfPC+3mX+RyCIm290xaJKOAKYs V+/J/mHwkNqnyHzWUwZCxObe33AXYyawzAzUA4ZviyR4FD3PsXe9ykLGz+YkjOcKsTj/+7o2jBy 2qFd93XgLOcMwp6NzEi/NPyrF0sJR7q9m/PCMIrypylexAD1D+eZ5U3n1B46Ulb9nvLvEMMKpNY xJXOnMDYwfbj2+P8aXWdWz8ByZrN7SNbsZ+F42RuhVjq8+sLBplhu72vzLdowogDArzIKiPT4Ed q5anax4WYmKR68pL7kbcRQo7w== X-Received: by 2002:a05:6a00:849:b0:82f:238f:b5a8 with SMTP id d2e1a72fcca58-834ddae11cfmr7829325b3a.9.1777468982443; Wed, 29 Apr 2026 06:23:02 -0700 (PDT) Received: from localhost.localdomain ([2001:448a:2002:4381:3859:fd0d:505e:362c]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-834ed5cd407sm2091372b3a.13.2026.04.29.06.22.58 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Wed, 29 Apr 2026 06:23:01 -0700 (PDT) From: Muchamad Coirul Anwar To: jic23@kernel.org, linux-iio@vger.kernel.org, rust-for-linux@vger.kernel.org, devicetree@vger.kernel.org Cc: branstj@gmail.com, lars@metafoo.de, ojeda@kernel.org, robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org, igor.korotin.linux@gmail.com, linux-kernel@vger.kernel.org, Muchamad Coirul Anwar Subject: [RFC PATCH v2 2/4] rust: add minimal IIO subsystem abstractions Date: Wed, 29 Apr 2026 20:22:28 +0700 Message-ID: <20260429132234.30514-3-muchamadcoirulanwar@gmail.com> X-Mailer: git-send-email 2.50.0 In-Reply-To: <20260429132234.30514-1-muchamadcoirulanwar@gmail.com> References: <20260429132234.30514-1-muchamadcoirulanwar@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Signed-off-by: Muchamad Coirul Anwar --- rust/bindings/bindings_helper.h | 2 + rust/kernel/iio.rs | 224 ++++++++++++++++++++++++++++++++ rust/kernel/lib.rs | 2 + 3 files changed, 228 insertions(+) create mode 100644 rust/kernel/iio.rs diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helpe= r.h index 083cc44aa952..e732ee19b90c 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -58,6 +58,8 @@ #include #include #include +#include +#include #include #include #include diff --git a/rust/kernel/iio.rs b/rust/kernel/iio.rs new file mode 100644 index 000000000000..ee27d928e803 --- /dev/null +++ b/rust/kernel/iio.rs @@ -0,0 +1,224 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2026 Muchamad Coirul Anwar +//! IIO subsystem abstractions. +//! +//! Minimal safe Rust wrappers for the Linux IIO (Industrial I/O) subsyste= m. +//! Provides [`Device`] for allocating and registering an IIO device, and = the +//! [`IioDriver`] trait for implementing `read_raw` callbacks in safe Rust. + +use crate::{ + bindings::{ + __iio_device_register, iio_chan_spec, iio_dev, iio_device_alloc, i= io_device_free, + iio_device_unregister, iio_info, INDIO_DIRECT_MODE, + }, + device, + error::{code::*, to_result, Result}, + prelude::*, + ThisModule, +}; +use core::{ + ffi::c_int, + marker::PhantomData, + mem::{size_of, zeroed}, + ptr::{drop_in_place, write}, +}; +use pin_init::{pin_data, pinned_drop}; +/// IIO value type: single integer (`IIO_VAL_INT`). +pub const IIO_VAL_INT: c_int =3D crate::bindings::IIO_VAL_INT as c_int; +/// IIO value type: integer plus micro part (`IIO_VAL_INT_PLUS_MICRO`). +pub const IIO_VAL_INT_PLUS_MICRO: c_int =3D crate::bindings::IIO_VAL_INT_P= LUS_MICRO as c_int; +/// IIO value type: integer plus nano part (`IIO_VAL_INT_PLUS_NANO`). +pub const IIO_VAL_INT_PLUS_NANO: c_int =3D crate::bindings::IIO_VAL_INT_PL= US_NANO as c_int; +/// IIO value type: fractional (`IIO_VAL_FRACTIONAL`). +pub const IIO_VAL_FRACTIONAL: c_int =3D crate::bindings::IIO_VAL_FRACTIONA= L as c_int; + +/// Represents the return value of a `read_raw` operation. +/// +/// Each variant corresponds to an `IIO_VAL_*` constant and tells the +/// IIO core how to format `val` and `val2` for userspace. +pub enum IioVal { + /// A single integer value. + Int(i32), + /// A fractional value represented as `val / val2`. + Fractional(i32, i32), + /// An integer plus a micro (10=E2=81=BB=E2=81=B6) fractional part: `v= al.val2`. + IntPlusMicro(i32, i32), + /// An integer plus a nano (10=E2=81=BB=E2=81=B9) fractional part: `va= l.val2`. + IntPlusNano(i32, i32), +} + +/// Trait to be implemented by IIO driver private data. +/// +/// Implementors supply the `read_raw` callback invoked by the IIO core +/// when userspace reads a channel attribute (e.g. `in_angl_raw`). +pub trait IioDriver { + /// Called by the IIO core when userspace reads a channel attribute. + /// + /// `chan` is the channel being read; `mask` selects the attribute + /// (e.g. `IIO_CHAN_INFO_RAW`, `IIO_CHAN_INFO_SCALE`). + fn read_raw(&self, chan: *const iio_chan_spec, mask: isize) -> Result<= IioVal>; + + /// Returns the channel specifications for this driver. + /// + /// The default implementation returns an empty slice. + fn channels(&self) -> &[iio_chan_spec] { + &[] + } +} + +/// C-compatible trampoline for the `iio_info.read_raw` callback. +/// +/// # Safety +/// +/// This function is only called by the IIO core with valid pointers: +/// - `indio_dev` is a valid `iio_dev` allocated by `iio_device_alloc`. +/// - `chan` points to a valid channel spec from the device's channel arra= y. +/// - `val` and `val2` are valid pointers for writing the result. +unsafe extern "C" fn read_raw_callback( + indio_dev: *mut iio_dev, + chan: *const iio_chan_spec, + val: *mut c_int, + val2: *mut c_int, + mask: isize, +) -> c_int { + // SAFETY: `indio_dev` is valid and was allocated with space for `T` i= n its + // private data area. The `priv_` field was initialized in `Device::ne= w()`. + let priv_ptr =3D unsafe { (*indio_dev).priv_ as *mut T }; + // SAFETY: `priv_ptr` points to a valid, initialized instance of `T` t= hat + // lives as long as the `iio_dev` allocation. + let driver =3D unsafe { &*priv_ptr }; + + match driver.read_raw(chan, mask) { + Ok(IioVal::Int(v)) =3D> { + // SAFETY: `val` is a valid pointer provided by the IIO core. + unsafe { *val =3D v }; + IIO_VAL_INT + } + Ok(IioVal::Fractional(v, v2)) =3D> { + // SAFETY: `val` and `val2` are valid pointers provided by the= IIO core. + unsafe { + *val =3D v; + *val2 =3D v2; + }; + IIO_VAL_FRACTIONAL + } + Ok(IioVal::IntPlusMicro(v, v2)) =3D> { + // SAFETY: `val` and `val2` are valid pointers provided by the= IIO core. + unsafe { + *val =3D v; + *val2 =3D v2; + } + IIO_VAL_INT_PLUS_MICRO + } + Ok(IioVal::IntPlusNano(v, v2)) =3D> { + // SAFETY: `val` and `val2` are valid pointers provided by the= IIO core. + unsafe { + *val =3D v; + *val2 =3D v2; + } + IIO_VAL_INT_PLUS_NANO + } + Err(e) =3D> e.to_errno(), + } +} + +/// A registered IIO device. +/// +/// Wraps a C `struct iio_dev` and manages its lifetime. On drop the +/// device is unregistered (if registered) and its memory freed. +#[pin_data(PinnedDrop)] +pub struct Device { + indio_dev: *mut iio_dev, + registered: bool, + _p: PhantomData, +} + +// SAFETY: `Device` only contains a raw pointer to a kernel-managed `iio_d= ev`. +// The IIO core serializes access to the device, and `T` is required to be= `Send`. +unsafe impl Send for Device {} +// SAFETY: All `&self` access to the `iio_dev` is read-only or goes throug= h the +// IIO core which provides its own synchronization. `T` is required to be = `Sync`. +unsafe impl Sync for Device {} + +#[pinned_drop] +impl PinnedDrop for Device { + // SAFETY: `self.indio_dev` was allocated by `iio_device_alloc` in `ne= w()` + // and is valid for the lifetime of this struct. We unregister first (= if + // registered), then drop the private data, then free the `iio_dev`. + // This ordering is critical: unregister ensures no more callbacks can + // fire before we drop the driver data they reference. + fn drop(self: Pin<&mut Self>) { + unsafe { + if self.registered { + iio_device_unregister(self.indio_dev); + } + let priv_ptr =3D (*self.indio_dev).priv_ as *mut T; + drop_in_place(priv_ptr); + iio_device_free(self.indio_dev); + } + } +} + +impl Device { + // SAFETY: The remaining fields of `iio_info` are pointers and function + // pointers. Zeroed values are NULL, and the IIO core checks for NULL + // before invoking callbacks or dereferencing attribute group pointers. + const VTABLE: iio_info =3D iio_info { + read_raw: Some(read_raw_callback::), + ..unsafe { zeroed() } + }; + + /// Allocates a new IIO device with the given driver data. + /// + /// The device is not yet registered; call [`register`](Self::register) + /// to make it visible to userspace. + pub fn new(dev: &device::Device, data: T, name: &'static CStr) -> Resu= lt { + // SAFETY: `dev.as_raw()` returns a valid `struct device` pointer. + // `iio_device_alloc` allocates an `iio_dev` with `sizeof(T)` byte= s of + // private data. Returns NULL on failure. + let indio_dev =3D unsafe { iio_device_alloc(dev.as_raw(), size_of:= :() as _) }; + if indio_dev.is_null() { + return Err(ENOMEM); + } + + // SAFETY: `indio_dev` is a valid, newly allocated `iio_dev`. + // - `priv_` points to an uninitialized area of `sizeof(T)` bytes. + // - `core::ptr::write` initializes it without reading the old val= ue. + // - `name` is a `'static` C string that outlives the device. + // - `VTABLE` is a `'static` const and outlives the device. + // - `channels()` returns a reference to data owned by `T` in `pri= v_`, + // which remains at a fixed address for the lifetime of `indio_d= ev` + // because `priv_` is heap-allocated by `iio_device_alloc`. + unsafe { + let priv_ptr =3D (*indio_dev).priv_ as *mut T; + write(priv_ptr, data); + (*indio_dev).name =3D name.as_char_ptr(); + (*indio_dev).info =3D &Self::VTABLE; + + let chans =3D (*priv_ptr).channels(); + (*indio_dev).channels =3D chans.as_ptr() as *const iio_chan_sp= ec; + (*indio_dev).num_channels =3D chans.len() as _; + (*indio_dev).modes =3D INDIO_DIRECT_MODE as i32; + } + + Ok(Self { + indio_dev, + registered: false, + _p: PhantomData, + }) + } + + /// Registers the IIO device, making it visible to userspace via sysfs. + /// + /// On success, channel attributes like `in_angl_raw` become readable. + /// On failure the device stays unregistered and will be freed when + /// this [`Device`] is dropped. + pub fn register(&mut self, _dev: &device::Device, module: &'static Thi= sModule) -> Result { + // SAFETY: `self.indio_dev` is a valid, fully initialized `iio_dev= `. + // `module.as_ptr()` provides the module owner for proper refcount= ing. + let ret =3D unsafe { __iio_device_register(self.indio_dev, module.= as_ptr()) }; + to_result(ret)?; + self.registered =3D true; + Ok(()) + } +} diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 138d846f798d..ec6eb4dbdb6a 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -99,6 +99,8 @@ #[cfg(CONFIG_I2C =3D "y")] pub mod i2c; pub mod id_pool; +#[cfg(CONFIG_IIO)] +pub mod iio; #[doc(hidden)] pub mod impl_flags; pub mod init; --=20 2.50.0 From nobody Tue Jun 16 19:33:46 2026 Received: from mail-pf1-f178.google.com (mail-pf1-f178.google.com [209.85.210.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 787143FE67D for ; Wed, 29 Apr 2026 13:23:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777468990; cv=none; b=FkJMAZPNb3ejxV4WMGBz47DKZXkC9Qj8z+o0aH7oIIi5XS4ZpJsSjdBsG2tKJ8gV6yNwyDU2bhevObQbfZtij8+2o7CmKQUuV7j6nDC7OwYyExepNh12e7psbp3+xs+gUfs0r58fU4MKlelz8koHvnGO7qBcOVeM+1+fAxzP9bo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777468990; c=relaxed/simple; bh=XI6T6E8eQ16tquB9SZpNeOdIKNi56M+uqkEzHvHoV1s=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=glqFZtS9ADOTlaXhS06XZvjjSqwl3JaZEGMW1U/B/rszfriSRTanJNca5trM6tTt7T0+G2LheO7mmZDO/wyiWC/wJK+miBjHBxKGNzXoXJs3PpY7NSFcI/67jgyLJZoq7GfwdyDDdukMBWvcTkHpHljogv3PspM79eF27WlhTpw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=BVfmOJ9+; arc=none smtp.client-ip=209.85.210.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="BVfmOJ9+" Received: by mail-pf1-f178.google.com with SMTP id d2e1a72fcca58-82cf636dac8so5431897b3a.3 for ; Wed, 29 Apr 2026 06:23:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777468989; x=1778073789; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=60u99mHhTFmXU2vBmbXZTzoik2emfTfjOC7hf/f4LX0=; b=BVfmOJ9+YlHkKbVu54sKEb30VDVeFfA5aPiAIhdlajZ4Kn6Ai77RBaYpIHqyOofusP 6y0FJvlXBqyZK2h0Q6dIG9pBLriHUgEa0/Io8XmF4pPUJlYJYrwxwblyItbEzs6MQ3Tj oHHHaRDEUUOihl76sfQJx5V32mAXCChfrBbQd7t41KH5kcijZe8fqg/krAHiMrLxD/p7 OVw5n5mVtnndQxh7uPXkFO8fNDBfeHxttUD2sCQju7Hr92NEGpFTevo0gcn6l/GyWZ8W qQvhbLU/cK5GX5+wDLO+y/sWrK5QGto42oSUTbEs3TDXrr6ot5xLmAMCL/p7mjNEV3yI DnOw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777468989; x=1778073789; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=60u99mHhTFmXU2vBmbXZTzoik2emfTfjOC7hf/f4LX0=; b=SP+pc6TD8ydP34hjWvRU7GZ5tPukCJuUxLyrA/1iQ+eQLh7MG/4PLMLW7Rw/CVjkOi sn229VyMJPPKcNjm7x/xbeIkegGIupmsEML4E4wKqhUPZEvVqfQXpK8LPjZex8Q8MGqs j40PF9Eh4fa5YOKkum8xs7HSBZY3iQmn7Bs0peyDlLSHoItYsMifbebQRKrPl/+frq3b Z+CjZQ9+ZdE+d+8CSIpJ9Xo5vgwQyZ1lvcRUKdl5Xx5Wu1aPx0ZNmrzn3WH8+kU5vUJ5 0Pz61ZgS11UzUs3ZePupVXGRf/kcLQ+d2vePPrGEhTQcFz84hUBGpmy+zn3XGo24ybiw Dquw== X-Forwarded-Encrypted: i=1; AFNElJ/OjH39ksLi7YhjsGCWwyg0IlUQo2xHLLuY0k2xFzGscCjBpy/3Z9u9HUHjB4kKiWvDyQimJ/LiI4fO4U0=@vger.kernel.org X-Gm-Message-State: AOJu0Yx19q5xr1REwhFxwtMvaRPp4G5eP1PlE7JA5IDNyvZpNqUEpnRm /iVdrbapg+ACNUzMD+l+aEKKhGA72BHP1PLXRxohC7aJaIQzVumBBkMu X-Gm-Gg: AeBDietqEvgYeuSMWCt+MvKIgh/hf/1Px9BXBbptts8g4rgUW3Z8agu5fgXRCEY3n3p KJRMVI1QPWSph4BIdepaTISPEh8l3nvoqpnyOLRPGOz3uoLtjds8urnXW1/f1fcaUJ3JvPU3Clj Vgy66icggJbZT6lTDOI3aaYRZ04KRvsmwCfabsA03b2nDcSuZ0tevY9hPkUh3Bwb8vEN1BwR5wc QCSGn7+rpvZChRJIqESiCzKDTgnoe72NyiqknccZvjw2YS+oHSfpK4O63qWt9RxT+gm9cuCU49q fZ5fr3itnAwX5nYP8wWeQyTz8OAH1kzb1QfZluwDhc0V8WHOa3Ne9O+my3Np9lIhCTUdG3TKqW9 ZsjzUOK57Ulg15s7KT5p80DSlXxXNffk81Cs8636Cr888e3hYrjflIURLdVg6aRdvumH7BmGMe+ zA5MWNUhkfsI9ILONlHJkidkuuVE0ozGrwtbyuSJngqW7qKZLyPhRxhkkH4oKhQAG9em0IWv/Q0 KZnrokLBCCUIyc= X-Received: by 2002:a05:6a00:1911:b0:82a:6b97:34ae with SMTP id d2e1a72fcca58-834ddbefef5mr7957990b3a.32.1777468988794; Wed, 29 Apr 2026 06:23:08 -0700 (PDT) Received: from localhost.localdomain ([2001:448a:2002:4381:3859:fd0d:505e:362c]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-834ed5cd407sm2091372b3a.13.2026.04.29.06.23.05 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Wed, 29 Apr 2026 06:23:08 -0700 (PDT) From: Muchamad Coirul Anwar To: jic23@kernel.org, linux-iio@vger.kernel.org, rust-for-linux@vger.kernel.org, devicetree@vger.kernel.org Cc: branstj@gmail.com, lars@metafoo.de, ojeda@kernel.org, robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org, igor.korotin.linux@gmail.com, linux-kernel@vger.kernel.org, Muchamad Coirul Anwar Subject: [RFC PATCH v2 3/4] dt-bindings: iio: position: add ams,as5600 Date: Wed, 29 Apr 2026 20:22:29 +0700 Message-ID: <20260429132234.30514-4-muchamadcoirulanwar@gmail.com> X-Mailer: git-send-email 2.50.0 In-Reply-To: <20260429132234.30514-1-muchamadcoirulanwar@gmail.com> References: <20260429132234.30514-1-muchamadcoirulanwar@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Signed-off-by: Muchamad Coirul Anwar --- .../bindings/iio/position/ams,as5600.yaml | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/position/ams,as56= 00.yaml diff --git a/Documentation/devicetree/bindings/iio/position/ams,as5600.yaml= b/Documentation/devicetree/bindings/iio/position/ams,as5600.yaml new file mode 100644 index 000000000000..d29543d85d1a --- /dev/null +++ b/Documentation/devicetree/bindings/iio/position/ams,as5600.yaml @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/position/ams,as5600.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: ams AS5600 Magnetic Rotary Position Sensor + +maintainers: + - Muchamad Coirul Anwar + +description: | + The ams AS5600 is a 12-bit programmable contactless + magnetic rotary position sensor communicating over I2C. + The device address is fixed at 0x36. + +properties: + compatible: + const: ams,as5600 + + reg: + const: 0x36 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + i2c { + #address-cells =3D <1>; + #size-cells =3D <0>; + + position-sensor@36 { + compatible =3D "ams,as5600"; + reg =3D <0x36>; + }; + }; --=20 2.50.0 From nobody Tue Jun 16 19:33:46 2026 Received: from mail-pf1-f173.google.com (mail-pf1-f173.google.com [209.85.210.173]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E17BC3FF892 for ; Wed, 29 Apr 2026 13:23:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777468998; cv=none; b=N2uS5Nf/8oCS5Mk2EhYNjEWdUP/kB6GfkxAduyoa7AgLoGnkVc0NKklsqcXsj9rVjXOFkV0l82jOAgWc+MSNunzunjXFnWCW5bS9DtRobfa/mD7VXCr4fH4fnmYH7DuhxBuGBVmTvmlUgD9H+moz9k3BMfz3du4Hib9i7VpqO3M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777468998; c=relaxed/simple; bh=4onuEvPaP2yvZAtOC+F4BCT1UwRW5DkR/lNZprGqXK0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=gZsZvJFe3Nm0B/l9KgXxOlvzgyEM/0+DTlmWXRXLacqUBlLsQ1TMn92Nl/p9juc76kIJQsOchijBqRjq4aqTQPNFdlNNmM8YS0jI/8vHq2hfQo6rgslyZrT6mXs6IUBVxznbZiwmlJNOlKnNXzQiomqxs7utSy6GIS4PMift3X0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=V90m/fjb; arc=none smtp.client-ip=209.85.210.173 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="V90m/fjb" Received: by mail-pf1-f173.google.com with SMTP id d2e1a72fcca58-82f8b60e54dso8431613b3a.2 for ; Wed, 29 Apr 2026 06:23:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777468995; x=1778073795; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=WCpqWEaMYg3UZ5FWd6Kx+fvUYh//nkS7obYuvELKMmY=; b=V90m/fjbKTuPjqlw5QgrqvYOosLYhl2YBonDELiwUVpWnSvCmJrazCko7GjU+Skcmc v8TKoX73DHAKUs2xi4DMdg4rObLVvQGCE3xwnpHXLQPaOPur+NwL4ha07hh/5MYdq6Le +BQaDUOBeubCtOvsbx4YbVpohIUAsQmE+7ssTscHgaPwKrHLj3N7MnBXQDYfVKywgh2T lbs0nI0nULv+maQ7lKCI4yW5G2dcI1oi79SsZYe0iG3NCYhBn/oIghngqgn/s56aqy1/ HmxnKgiu7MOYqp63nnyX0khOtwfdCXAvH67HqRmusEzPx3oLRSMqbgYwVWzioK47o9y2 EkKA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777468995; x=1778073795; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=WCpqWEaMYg3UZ5FWd6Kx+fvUYh//nkS7obYuvELKMmY=; b=jkTRW9aRtfA3HSUQwRuJAC03bRLKblieGOf7XEF2Zjrexh1d6CdLGO2K17DF+DDssU yOCSkB9pMofoDcBIJJSsGFQL64EFLUFER29grq6G4ft8v6jmQzGSa3quKI/lStjo79c8 7Ue4e9+g0OUxlxb32Wq1n0gXldweKWSTnGFssQ8+r6nxmtISo3oYfK2A7ml4VAal72E9 qDMk/sowtTJvcLVwNFqLH71Mu0WVPRkcnNME4naDRbK+N5fRN+r5I3BJWD0T3oQO0QYr SAvOnxYXut+cpePudtrQmdwHsfHqbeAGdyo59ZN6oND7QePGMqvteAfE4/N5smOYLkfS sCZw== X-Forwarded-Encrypted: i=1; AFNElJ/+giux94KyyRhDhz9OWxWoQYic5kGhSYWRZtqX+sRs+UWSt7ch0lEwoxrUjGzC8vmr/UZicYaOc6Xbkts=@vger.kernel.org X-Gm-Message-State: AOJu0YwartLD2geG7hCtC9g0ikdghtmsMpAiXOcEhROP/vgw9lddcRGB FXvTloe/5TgmYdI+Wf/+IOU8HziXyHJFEM7ycQVsm5qEF0Jv4nv/7ITm X-Gm-Gg: AeBDietBSSRMPf4FW/WaeXGBOlJgVpZmGt3n77sCvkx3srKuHdIgHg8lNnkT7SUmF/X capzl+RyQTnSQD5cv7f+M72/3EqBYuoPHrUyC69uH2IO51sXcLOXWnMBI2RqRCkJXGu+PkxI5Ys krMNb8KsXYZC+caZ5iHab5yUlu2eAqQy1/9u6WRRs22rReVb/B4VUf8ZrejjmF0WUmWDELidWTk 9J887wP6sTasEzEXjcOMV/MWo4eVEf0KnF/b/k78nWrinaMkPdzGnMhbBpA5MwOVtpwe2880qlz uDt2kNCX4Yx+ySieiKRyudx4A/E2dbqn12uswv6NOvjpC5K/cQThB83jJjHzJtlxdpvxmhZrTZh vmQTfebPz9P75QocVRBUer7l1fksXERe5/W4iNuMxZqDP/LgyC0PED0jbQ0uz8YtrMVxi8voX14 BpUlPqRHebWzwrO+jcPmtTKVKN0dSxVoGhytRFbIo3bGSr3uyAWyzrPBvu1Q5XP9uaInZwWi15j VelyjWEbLeE2UQ= X-Received: by 2002:a05:6a00:69a3:b0:834:df57:9d6b with SMTP id d2e1a72fcca58-834df57af63mr5180255b3a.24.1777468994395; Wed, 29 Apr 2026 06:23:14 -0700 (PDT) Received: from localhost.localdomain ([2001:448a:2002:4381:3859:fd0d:505e:362c]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-834ed5cd407sm2091372b3a.13.2026.04.29.06.23.10 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Wed, 29 Apr 2026 06:23:13 -0700 (PDT) From: Muchamad Coirul Anwar To: jic23@kernel.org, linux-iio@vger.kernel.org, rust-for-linux@vger.kernel.org, devicetree@vger.kernel.org Cc: branstj@gmail.com, lars@metafoo.de, ojeda@kernel.org, robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org, igor.korotin.linux@gmail.com, linux-kernel@vger.kernel.org, Muchamad Coirul Anwar Subject: [RFC PATCH v2 4/4] iio: position: add Rust driver for ams AS5600 Date: Wed, 29 Apr 2026 20:22:30 +0700 Message-ID: <20260429132234.30514-5-muchamadcoirulanwar@gmail.com> X-Mailer: git-send-email 2.50.0 In-Reply-To: <20260429132234.30514-1-muchamadcoirulanwar@gmail.com> References: <20260429132234.30514-1-muchamadcoirulanwar@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Signed-off-by: Muchamad Coirul Anwar --- drivers/iio/position/Kconfig | 14 ++++ drivers/iio/position/Makefile | 1 + drivers/iio/position/as5600.rs | 129 +++++++++++++++++++++++++++++++++ 3 files changed, 144 insertions(+) create mode 100644 drivers/iio/position/as5600.rs diff --git a/drivers/iio/position/Kconfig b/drivers/iio/position/Kconfig index 1576a6380b53..dab9310e8079 100644 --- a/drivers/iio/position/Kconfig +++ b/drivers/iio/position/Kconfig @@ -6,6 +6,20 @@ =20 menu "Linear and angular position sensors" =20 +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 with IIO channel support + (in_angl_raw and in_angl_scale). + + This is a Rust driver that exposes the 12-bit raw angle + and radian scale via the IIO subsystem. + + 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 @@ =20 # When adding new entries keep the list in alphabetical order =20 +obj-$(CONFIG_AS5600) +=3D as5600.o obj-$(CONFIG_HID_SENSOR_CUSTOM_INTEL_HINGE) +=3D hid-sensor-custom-intel-h= inge.o obj-$(CONFIG_IQS624_POS) +=3D iqs624-pos.o diff --git a/drivers/iio/position/as5600.rs b/drivers/iio/position/as5600.rs new file mode 100644 index 000000000000..0cbf8be58b64 --- /dev/null +++ b/drivers/iio/position/as5600.rs @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (C) 2026 Muchamad Coirul Anwar +//! Driver for ams AS5600 12-bit magnetic rotary position sensor. +//! +//! Datasheet: https://ams.com/documents/20143/36005/AS5600_DS000365_5-00.= pdf + +use kernel::{ + bindings::{ + iio_chan_info_enum_IIO_CHAN_INFO_RAW, iio_chan_info_enum_IIO_CHAN_= INFO_SCALE, + iio_chan_spec, iio_chan_type_IIO_ANGL, ENODATA, + }, + bits::bit_u8, + device::Core, + i2c::{DeviceId, Driver, I2cClient, IdTable}, + i2c_device_table, + iio::{Device, IioDriver, IioVal}, + module_i2c_driver, of, of_device_table, + prelude::*, +}; + +const AS5600_REG_STATUS: u8 =3D 0x0B; +const AS5600_REG_RAW_ANGLE_H: u8 =3D 0x0C; +const AS5600_REG_RAW_ANGLE_L: u8 =3D 0x0D; + +const AS5600_STATUS_MD: u8 =3D bit_u8(5); + +module_i2c_driver! { + type: As5600, + name: "as5600", + authors: ["Muchamad Coirul Anwar"], + description: "I2C Driver for ams OSRAM AS5600 Magnetic Rotary Position= Sensor", + license: "GPL", +} + +i2c_device_table!( + I2C_TABLE, + MODULE_I2C_TABLE, + ::IdInfo, + [(DeviceId::new(c"as5600"), ())] +); + +of_device_table!( + OF_TABLE, + MODULE_OF_TABLE, + ::IdInfo, + [(of::DeviceId::new(c"ams,as5600"), ())] +); + +struct As5600Priv { + client_ptr: *const I2cClient, + channels: [iio_chan_spec; 1], +} + +// SAFETY: `client_ptr` points to an `I2cClient` that is owned by the I2C +// subsystem and outlives the driver binding. `iio_device_unregister` in +// `Device::PinnedDrop` drains pending callbacks before this struct is +// dropped, so `client_ptr` is valid for every `read_raw` invocation. +// Concurrent access is safe because the I2C adapter lock serializes all +// SMBus transactions. +unsafe impl Send for As5600Priv {} +unsafe impl Sync for As5600Priv {} + +impl IioDriver for As5600Priv { + fn read_raw(&self, _chan: *const iio_chan_spec, mask: isize) -> Result= { + // SAFETY: `client_ptr` was set from a valid `&I2cClient` in `prob= e()`. + // The I2C client outlives the driver binding, and `read_raw` is o= nly + // called while the driver is bound. + let client =3D unsafe { &*self.client_ptr }; + + #[allow(non_upper_case_globals)] + match mask as u32 { + // IIO_CHAN_INFO_RAW + iio_chan_info_enum_IIO_CHAN_INFO_RAW =3D> { + let status =3D client.smbus_read_byte_data(AS5600_REG_STAT= US)?; + if (status & AS5600_STATUS_MD) =3D=3D 0 { + return Err(Error::from_errno(-(ENODATA as i32))); + } + + let angle_h =3D client.smbus_read_byte_data(AS5600_REG_RAW= _ANGLE_H)? as u16; + let angle_l =3D client.smbus_read_byte_data(AS5600_REG_RAW= _ANGLE_L)? as u16; + + let angle =3D (angle_h << 8 | angle_l) & 0x0FFF; + Ok(IioVal::Int(angle as i32)) + } + // IIO_CHAN_INFO_SCALE + iio_chan_info_enum_IIO_CHAN_INFO_SCALE =3D> Ok(IioVal::IntPlus= Nano(0, 1533981)), + _ =3D> Err(EINVAL), + } + } + + fn channels(&self) -> &[iio_chan_spec] { + &self.channels + } +} + +struct As5600 { + _iio_dev: Device, +} + +impl Driver for As5600 { + type IdInfo =3D (); + const I2C_ID_TABLE: Option> =3D Some(&I2C_TABLE); + const OF_ID_TABLE: Option> =3D Some(&OF_TABL= E); + + fn probe(dev: &I2cClient, _id_info: Option<&Self::IdInfo>) -> im= pl PinInit { + let _status =3D dev.smbus_read_byte_data(AS5600_REG_STATUS)?; + + // SAFETY: `iio_chan_spec` is a C struct whose fields are all inte= gers + // and pointers. Zero is a valid initialization for all of them. + let mut channels: [iio_chan_spec; 1] =3D unsafe { core::mem::zeroe= d() }; + channels[0].info_mask_separate =3D (1 << iio_chan_info_enum_IIO_CH= AN_INFO_RAW) + | (1 << iio_chan_info_enum_IIO_CHAN_INFO_SCALE); + channels[0].type_ =3D iio_chan_type_IIO_ANGL; + + let priv_data =3D As5600Priv { + client_ptr: dev as *const _, + channels, + }; + + let mut iio_dev =3D Device::new(dev.as_ref(), priv_data, c"as5600"= )?; + + iio_dev.register(dev.as_ref(), &crate::THIS_MODULE)?; + + dev_dbg!(dev.as_ref(), "AS5600: Sensor probed, driver ready\n"); + Ok::<_, Error>(As5600 { _iio_dev: iio_dev }) + } + + fn unbind(_dev: &I2cClient, _this: Pin<&Self>) {} +} --=20 2.50.0