Skip to contentSkip to conversation

rust: Add basic I2C driver abstractions

PATCH Superseded Igor Korotin 1 participant 5 messages Jun 26, 2025

Subsystems (3)

v1 of 8 Superseded Latest is v8 →

lore
Share & tools
lore
#0 lore raw

cover rust: Add basic I2C driver abstractions

This patch series introduces basic Rust I2C driver abstractions and optional ACPI match-table support and provides a sample driver demonstrating both OF and ACPI binding

Currently Rust I2C abstractions support only Open Firmware OF device matching. This series splits the work into four patches so that the core abstractions and sample driver can land immediately while ACPI integration may be reviewed once the ACPI macros are upstream

Changes include
- core I2C abstractions i2c::Device i2c::Driver i2c::Adapter built on struct i2c_client and struct i2c_driver
- a standalone Rust sample driver exercising Legacy I2C ID and OF ID matching
- optional ACPI ID-table support in the i2c::Driver abstraction
- ACPI-enabled sample driver showing kernel::acpi_device_table! usage

This separation lets maintainers review and merge the non-ACPI portions immediately while patches 3 and 4 both depending on the ACPI infrastructure can be queued once the ACPI macros are upstream

Patch series:

1 rust: i2c: add basic I2C device and driver abstractions 2 samples: rust: add I2C sample driver (OF only)
3 rust: i2c: support ACPI match-table in driver abstractions
Depends-on: [email protected] 4 samples: rust: show ACPI ID-table in I2C sample driver
Depends-on: [email protected]

Igor Korotin (4):
rust: i2c: add basic I2C device and driver abstractions
samples: rust: add Rust I2C sample driver
rust: i2c: ACPI ID-table support for I2C abstractions
samples: rust: show ACPI ID-table in I2C sample driver

 MAINTAINERS                     |   3 +
 rust/bindings/bindings_helper.h |   1 +
 rust/helpers/helpers.c          |   1 +
 rust/helpers/i2c.c              |  15 ++
 rust/kernel/i2c.rs              | 386 ++++++++++++++++++++++++++++++++
 rust/kernel/lib.rs              |   2 +
 samples/rust/Kconfig            |  11 +
 samples/rust/Makefile           |   1 +
 samples/rust/rust_driver_i2c.rs |  69 ++++++
 9 files changed, 489 insertions(+)
 create mode 100644 rust/helpers/i2c.c
 create mode 100644 rust/kernel/i2c.rs
 create mode 100644 samples/rust/rust_driver_i2c.rs

base-commit: 63dafeb392139b893a73b6331f347613f0929702

Signature · 1 line
2.43.0
#1 lore raw

PATCH 1/4 rust: i2c: add basic I2C device and driver abstractions

Implement the core abstractions needed for I2C drivers, including:

* i2c::Driver — the trait drivers must implement, including probe

* i2c::Device — a safe wrapper around struct i2c_client

* i2c::Adapter — implements driver::RegistrationOps to hook into the generic driver::Registration machinery

* i2c::DeviceId — a RawDeviceId implementation for I2C device IDs

---
 MAINTAINERS                     |   2 +
 rust/bindings/bindings_helper.h |   1 +
 rust/helpers/helpers.c          |   1 +
 rust/helpers/i2c.c              |  15 ++
 rust/kernel/i2c.rs              | 363 ++++++++++++++++++++++++++++++++
 rust/kernel/lib.rs              |   2 +
 6 files changed, 384 insertions(+)
 create mode 100644 rust/helpers/i2c.c
 create mode 100644 rust/kernel/i2c.rs
MAINTAINERS +2 -0
index 68d2a32759ec..2b7a24586c19 100644
@@ -11362,6 +11362,8 @@ F:	include/linux/i2c-smbus.h
 F:	include/linux/i2c.h
 F:	include/uapi/linux/i2c-*.h
 F:	include/uapi/linux/i2c.h
+F:	rust/helpers/i2c.c
+F:	rust/kernel/i2c.rs
 
 I2C SUBSYSTEM HOST DRIVERS
 M:	Andi Shyti <[email protected]>
rust/bindings/bindings_helper.h +1 -0
index 8cbb660e2ec2..0c7b3cbb8918 100644
@@ -52,6 +52,7 @@
 #include <linux/file.h>
 #include <linux/firmware.h>
 #include <linux/fs.h>
+#include <linux/i2c.h>
 #include <linux/jiffies.h>
 #include <linux/jump_label.h>
 #include <linux/mdio.h>
rust/helpers/helpers.c +1 -0
index 393ad201befb..63afd35205da 100644
@@ -23,6 +23,7 @@
 #include "drm.c"
 #include "err.c"
 #include "fs.c"
+#include "i2c.c"
 #include "io.c"
 #include "jump_label.c"
 #include "kunit.c"
rust/helpers/i2c.c new file +15 -0
new file mode 100644
index 000000000000..5f384f8f560e
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/i2c.h>
+
+void* rust_helper_i2c_get_clientdata(struct i2c_client *client)
+{
+	return i2c_get_clientdata(client);
+}
+
+void rust_helper_i2c_set_clientdata(struct i2c_client *client, void *data)
+{
+	i2c_set_clientdata(client, data);
+}
+
+
rust/kernel/i2c.rs new file +363 -0

363 lines not on this page · raw message

rust/kernel/lib.rs +2 -0
index 6b4774b2b1c3..30a0fc20dfee 100644
@@ -78,6 +78,8 @@
 #[cfg(CONFIG_RUST_FW_LOADER_ABSTRACTIONS)]
 pub mod firmware;
 pub mod fs;
+#[cfg(CONFIG_I2C)]
+pub mod i2c;
 pub mod init;
 pub mod io;
 pub mod ioctl;
Signature · 1 line
2.43.0
#2 lore raw

PATCH 2/4 samples: rust: add Rust I2C sample driver

In reply to Igor Korotin

Add a new rust_driver_i2c sample, showing how to bind an I2C client in Rust via legacy I2C-ID or OF compatible tables.

---
 MAINTAINERS                     |  1 +
 samples/rust/Kconfig            | 11 ++++++
 samples/rust/Makefile           |  1 +
 samples/rust/rust_driver_i2c.rs | 61 +++++++++++++++++++++++++++++++++
 4 files changed, 74 insertions(+)
 create mode 100644 samples/rust/rust_driver_i2c.rs
MAINTAINERS +1 -0
index 2b7a24586c19..a64570dda05e 100644
@@ -11364,6 +11364,7 @@ F:	include/uapi/linux/i2c-*.h
 F:	include/uapi/linux/i2c.h
 F:	rust/helpers/i2c.c
 F:	rust/kernel/i2c.rs
+F:	samples/rust/rust_driver_i2c.rs
 
 I2C SUBSYSTEM HOST DRIVERS
 M:	Andi Shyti <[email protected]>
samples/rust/Kconfig +11 -0
index 7f7371a004ee..55aeb12cd7f7 100644
@@ -62,6 +62,17 @@ config SAMPLE_RUST_DMA
 
 	  If unsure, say N.
 
+config SAMPLE_RUST_DRIVER_I2C
+	tristate "I2C Driver"
+	depends on I2C
+	help
+	  This option builds the Rust I2C driver sample.
+
+	  To compile this as a module, choose M here:
+	  the module will be called rust_driver_i2c.
+
+	  If unsure, say N.
+
 config SAMPLE_RUST_DRIVER_PCI
 	tristate "PCI Driver"
 	depends on PCI
samples/rust/Makefile +1 -0
index bd2faad63b4f..141d8f078248 100644
@@ -5,6 +5,7 @@ obj-$(CONFIG_SAMPLE_RUST_MINIMAL)		+= rust_minimal.o
 obj-$(CONFIG_SAMPLE_RUST_MISC_DEVICE)		+= rust_misc_device.o
 obj-$(CONFIG_SAMPLE_RUST_PRINT)			+= rust_print.o
 obj-$(CONFIG_SAMPLE_RUST_DMA)			+= rust_dma.o
+obj-$(CONFIG_SAMPLE_RUST_DRIVER_I2C)		+= rust_driver_i2c.o
 obj-$(CONFIG_SAMPLE_RUST_DRIVER_PCI)		+= rust_driver_pci.o
 obj-$(CONFIG_SAMPLE_RUST_DRIVER_PLATFORM)	+= rust_driver_platform.o
 obj-$(CONFIG_SAMPLE_RUST_DRIVER_FAUX)		+= rust_driver_faux.o
samples/rust/rust_driver_i2c.rs new file +61 -0

61 lines not on this page · raw message

Signature · 1 line
2.43.0
#3 lore raw

PATCH 3/4 rust: i2c: ACPI ID-table support for I2C abstractions

In reply to Igor Korotin

Populate driver.acpi_match_table from T::ACPI_ID_TABLE (defaults to None).

Depends-on: <[email protected]>

---
 rust/kernel/i2c.rs | 27 +++++++++++++++++++++++++--
 1 file changed, 25 insertions(+), 2 deletions(-)
rust/kernel/i2c.rs +25 -2
index 051f4f2bd38a..c242f1d3921f 100644
@@ -4,7 +4,7 @@
 
 // I2C Driver abstractions.
 use crate::{
-    container_of, device,
+    acpi, container_of, device,
     device_id::RawDeviceId,
     driver,
     error::*,
@@ -96,6 +96,11 @@ unsafe fn register(
             None => core::ptr::null(),
         };
 
+        let acpi_table = match T::ACPI_ID_TABLE {
+            Some(table) => table.as_ptr(),
+            None => core::ptr::null(),
+        };
+
         // SAFETY: It's safe to set the fields of `struct i2c_client` on initialization.
         unsafe {
             (*pdrv.get()).driver.name = name.as_char_ptr();
@@ -104,6 +109,7 @@ unsafe fn register(
             (*pdrv.get()).shutdown = Some(Self::shutdown_callback);
             (*pdrv.get()).id_table = i2c_table;
             (*pdrv.get()).driver.of_match_table = of_table;
+            (*pdrv.get()).driver.acpi_match_table = acpi_table;
         }
 
         // SAFETY: `pdrv` is guaranteed to be a valid `RegType`.
@@ -187,6 +193,10 @@ impl<T: Driver + 'static> driver::Adapter for Adapter<T> {
     fn of_id_table() -> Option<of::IdTable<Self::IdInfo>> {
         T::OF_ID_TABLE
     }
+
+    fn acpi_id_table() -> Option<acpi::IdTable<Self::IdInfo>> {
+        T::ACPI_ID_TABLE
+    }
 }
 
 /// Declares a kernel module that exposes a single i2c driver.
@@ -216,10 +226,19 @@ macro_rules! module_i2c_driver {
 /// # Example
 ///
 ///```
-/// # use kernel::{bindings, c_str, device::Core, i2c, of};
+/// # use kernel::{acpi, bindings, c_str, device::Core, i2c, of};
 ///
 /// struct MyDriver;
 ///
+/// kernel::acpi_device_table!(
+///     ACPI_TABLE,
+///     MODULE_ACPI_TABLE,
+///     <MyDriver as i2c::Driver>::IdInfo,
+///     [
+///         (acpi::DeviceId::new(b"TST0001"), ())
+///     ]
+/// );
+///
 /// kernel::i2c_device_table!(
 ///     I2C_TABLE,
 ///     MODULE_I2C_TABLE,
@@ -242,6 +261,7 @@ macro_rules! module_i2c_driver {
 ///     type IdInfo = ();
 ///     const I2C_ID_TABLE: Option<i2c::IdTable<Self::IdInfo>> = Some(&I2C_TABLE);
 ///     const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE);
+///     const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = Some(&ACPI_TABLE);
 ///
 ///     fn probe(
 ///         _pdev: &i2c::Device<Core>,
@@ -269,6 +289,9 @@ pub trait Driver: Send {
     /// The table of OF device ids supported by the driver.
     const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = None;
 
+    /// The table of ACPI device ids supported by the driver.
+    const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = None;
+
     /// I2C driver probe.
     ///
     /// Called when a new i2c device is added or discovered.
Signature · 1 line
2.43.0
#4 lore raw

PATCH 4/4 samples: rust: show ACPI ID-table in I2C sample driver

In reply to Igor Korotin

Add an acpi_device_table! example and set SampleDriver::ACPI_ID_TABLE to demonstrate ACPI usage.

Depends-on: <[email protected]>

---
 samples/rust/rust_driver_i2c.rs | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)
samples/rust/rust_driver_i2c.rs +9 -1
index 7c5def930fe0..98bda18fd098 100644
@@ -2,12 +2,19 @@
 
 //! Rust I2C driver sample.
 
-use kernel::{c_str, device::Core, i2c, of, prelude::*, types::ARef};
+use kernel::{acpi, c_str, device::Core, i2c, of, prelude::*, types::ARef};
 
 struct SampleDriver {
     pdev: ARef<i2c::Device>,
 }
 
+kernel::acpi_device_table! {
+    ACPI_TABLE,
+    MODULE_ACPI_TABLE,
+    <SampleDriver as i2c::Driver>::IdInfo,
+    [(acpi::DeviceId::new(b"TST0001"), 0)]
+}
+
 kernel::i2c_device_table! {
     I2C_TABLE,
     MODULE_I2C_TABLE,
@@ -25,6 +32,7 @@ struct SampleDriver {
 impl i2c::Driver for SampleDriver {
     type IdInfo = u32;
 
+    const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = Some(&ACPI_TABLE);
     const I2C_ID_TABLE: Option<i2c::IdTable<Self::IdInfo>> = Some(&I2C_TABLE);
     const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE);
 
Signature · 1 line
2.43.0