Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at 4c2ed2a3dbda5cad4d7b2f5f394c91522abbaa92 146 lines 3.9 kB view raw
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 device, 73 devres::Devres, 74 i2c, 75 of, 76 platform, 77 prelude::*, 78 sync::aref::ARef, // 79}; 80 81#[pin_data] 82struct SampleDriver { 83 parent_dev: ARef<platform::Device>, 84 #[pin] 85 _reg: Devres<i2c::Registration>, 86} 87 88kernel::of_device_table!( 89 OF_TABLE, 90 MODULE_OF_TABLE, 91 <SampleDriver as platform::Driver>::IdInfo, 92 [(of::DeviceId::new(c"test,rust-device"), ())] 93); 94 95kernel::acpi_device_table!( 96 ACPI_TABLE, 97 MODULE_ACPI_TABLE, 98 <SampleDriver as platform::Driver>::IdInfo, 99 [(acpi::DeviceId::new(c"LNUXBEEF"), ())] 100); 101 102const SAMPLE_I2C_CLIENT_ADDR: u16 = 0x30; 103const SAMPLE_I2C_ADAPTER_INDEX: i32 = 0; 104const BOARD_INFO: i2c::I2cBoardInfo = 105 i2c::I2cBoardInfo::new(c"rust_driver_i2c", SAMPLE_I2C_CLIENT_ADDR); 106 107impl platform::Driver for SampleDriver { 108 type IdInfo = (); 109 const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE); 110 const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = Some(&ACPI_TABLE); 111 112 fn probe( 113 pdev: &platform::Device<device::Core>, 114 _info: Option<&Self::IdInfo>, 115 ) -> impl PinInit<Self, Error> { 116 dev_info!( 117 pdev.as_ref(), 118 "Probe Rust I2C Client registration sample.\n" 119 ); 120 121 kernel::try_pin_init!( Self { 122 parent_dev: pdev.into(), 123 124 _reg <- { 125 let adapter = i2c::I2cAdapter::get(SAMPLE_I2C_ADAPTER_INDEX)?; 126 127 i2c::Registration::new(&adapter, &BOARD_INFO, pdev.as_ref()) 128 } 129 }) 130 } 131 132 fn unbind(pdev: &platform::Device<device::Core>, _this: Pin<&Self>) { 133 dev_info!( 134 pdev.as_ref(), 135 "Unbind Rust I2C Client registration sample.\n" 136 ); 137 } 138} 139 140kernel::module_platform_driver! { 141 type: SampleDriver, 142 name: "rust_device_i2c", 143 authors: ["Danilo Krummrich", "Igor Korotin"], 144 description: "Rust I2C client registration", 145 license: "GPL v2", 146}