File Index
Files and directories
Sign in
FILE

rust_i2c_client.rs

File preview with syntax highlighting.

linux-6.19.14/samples/rust/rust_i2c_client.rs RUST
  1// SPDX-License-Identifier: GPL-2.0
  2
  3//! Rust I2C client registration sample.
  4//!
  5//! An I2C client in Rust cannot exist on its own. To register a new I2C client,
  6//! it must be bound to a parent device. In this sample driver, a platform device
  7//! is used as the parent.
  8//!
  9
 10//! ACPI match table test
 11//!
 12//! This demonstrates how to test an ACPI-based Rust I2C client registration driver
 13//! using QEMU with a custom SSDT.
 14//!
 15//! Steps:
 16//!
 17//! 1. **Create an SSDT source file** (`ssdt.dsl`) with the following content:
 18//!
 19//!     ```asl
 20//!     DefinitionBlock ("", "SSDT", 2, "TEST", "VIRTACPI", 0x00000001)
 21//!     {
 22//!         Scope (\_SB)
 23//!         {
 24//!             Device (T432)
 25//!             {
 26//!                 Name (_HID, "LNUXBEEF")  // ACPI hardware ID to match
 27//!                 Name (_UID, 1)
 28//!                 Name (_STA, 0x0F)        // Device present, enabled
 29//!                 Name (_CRS, ResourceTemplate ()
 30//!                 {
 31//!                     Memory32Fixed (ReadWrite, 0xFED00000, 0x1000)
 32//!                 })
 33//!             }
 34//!         }
 35//!     }
 36//!     ```
 37//!
 38//! 2. **Compile the table**:
 39//!
 40//!     ```sh
 41//!     iasl -tc ssdt.dsl
 42//!     ```
 43//!
 44//!     This generates `ssdt.aml`
 45//!
 46//! 3. **Run QEMU** with the compiled AML file:
 47//!
 48//!     ```sh
 49//!     qemu-system-x86_64 -m 512M \
 50//!         -enable-kvm \
 51//!         -kernel path/to/bzImage \
 52//!         -append "root=/dev/sda console=ttyS0" \
 53//!         -hda rootfs.img \
 54//!         -serial stdio \
 55//!         -acpitable file=ssdt.aml
 56//!     ```
 57//!
 58//!     Requirements:
 59//!     - The `rust_driver_platform` must be present either:
 60//!         - built directly into the kernel (`bzImage`), or
 61//!         - available as a `.ko` file and loadable from `rootfs.img`
 62//!
 63//! 4. **Verify it worked** by checking `dmesg`:
 64//!
 65//!     ```
 66//!     rust_driver_platform LNUXBEEF:00: Probed with info: '0'.
 67//!     ```
 68//!
 69
 70use kernel::{
 71    acpi,
 72    c_str,
 73    device,
 74    devres::Devres,
 75    i2c,
 76    of,
 77    platform,
 78    prelude::*,
 79    sync::aref::ARef, //
 80};
 81
 82#[pin_data]
 83struct SampleDriver {
 84    parent_dev: ARef<platform::Device>,
 85    #[pin]
 86    _reg: Devres<i2c::Registration>,
 87}
 88
 89kernel::of_device_table!(
 90    OF_TABLE,
 91    MODULE_OF_TABLE,
 92    <SampleDriver as platform::Driver>::IdInfo,
 93    [(of::DeviceId::new(c_str!("test,rust-device")), ())]
 94);
 95
 96kernel::acpi_device_table!(
 97    ACPI_TABLE,
 98    MODULE_ACPI_TABLE,
 99    <SampleDriver as platform::Driver>::IdInfo,
100    [(acpi::DeviceId::new(c_str!("LNUXBEEF")), ())]
101);
102
103const SAMPLE_I2C_CLIENT_ADDR: u16 = 0x30;
104const SAMPLE_I2C_ADAPTER_INDEX: i32 = 0;
105const BOARD_INFO: i2c::I2cBoardInfo =
106    i2c::I2cBoardInfo::new(c_str!("rust_driver_i2c"), SAMPLE_I2C_CLIENT_ADDR);
107
108impl platform::Driver for SampleDriver {
109    type IdInfo = ();
110    const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE);
111    const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = Some(&ACPI_TABLE);
112
113    fn probe(
114        pdev: &platform::Device<device::Core>,
115        _info: Option<&Self::IdInfo>,
116    ) -> impl PinInit<Self, Error> {
117        dev_info!(
118            pdev.as_ref(),
119            "Probe Rust I2C Client registration sample.\n"
120        );
121
122        kernel::try_pin_init!( Self {
123            parent_dev: pdev.into(),
124
125            _reg <- {
126                let adapter = i2c::I2cAdapter::get(SAMPLE_I2C_ADAPTER_INDEX)?;
127
128                i2c::Registration::new(&adapter, &BOARD_INFO, pdev.as_ref())
129            }
130        })
131    }
132
133    fn unbind(pdev: &platform::Device<device::Core>, _this: Pin<&Self>) {
134        dev_info!(
135            pdev.as_ref(),
136            "Unbind Rust I2C Client registration sample.\n"
137        );
138    }
139}
140
141kernel::module_platform_driver! {
142    type: SampleDriver,
143    name: "rust_device_i2c",
144    authors: ["Danilo Krummrich", "Igor Korotin"],
145    description: "Rust I2C client registration",
146    license: "GPL v2",
147}
~/ Read-only file preview.