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.

rust: Add soc_device support

Allow SoC drivers in Rust to present metadata about their devices to
userspace through /sys/devices/socX and other drivers to identify their
properties through `soc_device_match`.

Signed-off-by: Matthew Maurer <mmaurer@google.com>
Link: https://patch.msgid.link/20251226-soc-bindings-v4-1-2c2fac08f820@google.com
Signed-off-by: Danilo Krummrich <dakr@kernel.org>

authored by

Matthew Maurer and committed by
Danilo Krummrich
057d44b0 43e35185

+139
+1
MAINTAINERS
··· 7700 7700 F: rust/kernel/driver.rs 7701 7701 F: rust/kernel/faux.rs 7702 7702 F: rust/kernel/platform.rs 7703 + F: rust/kernel/soc.rs 7703 7704 F: samples/rust/rust_debugfs.rs 7704 7705 F: samples/rust/rust_debugfs_scoped.rs 7705 7706 F: samples/rust/rust_driver_platform.rs
+1
rust/bindings/bindings_helper.h
··· 80 80 #include <linux/sched.h> 81 81 #include <linux/security.h> 82 82 #include <linux/slab.h> 83 + #include <linux/sys_soc.h> 83 84 #include <linux/task_work.h> 84 85 #include <linux/tracepoint.h> 85 86 #include <linux/usb.h>
+2
rust/kernel/lib.rs
··· 138 138 pub mod seq_file; 139 139 pub mod sizes; 140 140 pub mod slice; 141 + #[cfg(CONFIG_SOC_BUS)] 142 + pub mod soc; 141 143 mod static_assert; 142 144 #[doc(hidden)] 143 145 pub mod std_vendor;
+135
rust/kernel/soc.rs
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + // Copyright (C) 2025 Google LLC. 4 + 5 + //! SoC Driver Abstraction. 6 + //! 7 + //! C header: [`include/linux/sys_soc.h`](srctree/include/linux/sys_soc.h) 8 + 9 + use crate::{ 10 + bindings, 11 + error, 12 + prelude::*, 13 + str::CString, 14 + types::Opaque, // 15 + }; 16 + use core::ptr::NonNull; 17 + 18 + /// Attributes for a SoC device. 19 + /// 20 + /// These are both exported to userspace under /sys/devices/socX and provided to other drivers to 21 + /// match against via `soc_device_match` (not yet available in Rust) to enable quirks or 22 + /// device-specific support where necessary. 23 + /// 24 + /// All fields are freeform - they have no specific formatting, just defined meanings. 25 + /// For example, the [`machine`](`Attributes::machine`) field could be "DB8500" or 26 + /// "Qualcomm Technologies, Inc. SM8560 HDK", but regardless it should identify a board or product. 27 + pub struct Attributes { 28 + /// Should generally be a board ID or product ID. Examples 29 + /// include DB8500 (ST-Ericsson) or "Qualcomm Technologies, inc. SM8560 HDK". 30 + /// 31 + /// If this field is not populated, the SoC infrastructure will try to populate it from 32 + /// `/model` in the device tree. 33 + pub machine: Option<CString>, 34 + /// The broader class this SoC belongs to. Examples include ux500 35 + /// (for DB8500) or Snapdragon (for SM8650). 36 + /// 37 + /// On chips with ARM firmware supporting SMCCC v1.2+, this may be a JEDEC JEP106 manufacturer 38 + /// identification. 39 + pub family: Option<CString>, 40 + /// The manufacturing revision of the part. Frequently this is MAJOR.MINOR, but not always. 41 + pub revision: Option<CString>, 42 + /// Serial Number - uniquely identifies a specific SoC. If present, should be unique (buying a 43 + /// replacement part should change it if present). This field cannot be matched on and is 44 + /// solely present to export through /sys. 45 + pub serial_number: Option<CString>, 46 + /// SoC ID - identifies a specific SoC kind in question, sometimes more specifically than 47 + /// `machine` if the same SoC is used in multiple products. Some devices use this to specify a 48 + /// SoC name, e.g. "I.MX??", and others just print an ID number (e.g. Tegra and Qualcomm). 49 + /// 50 + /// On chips with ARM firmware supporting SMCCC v1.2+, this may be a JEDEC JEP106 manufacturer 51 + /// identification (the family value) followed by a colon and then a 4-digit ID value. 52 + pub soc_id: Option<CString>, 53 + } 54 + 55 + struct BuiltAttributes { 56 + // While `inner` has pointers to `_backing`, it is to the interior of the `CStrings`, not 57 + // `backing` itself, so it does not need to be pinned. 58 + _backing: Attributes, 59 + // `Opaque` makes us `!Unpin`, as the registration holds a pointer to `inner` when used. 60 + inner: Opaque<bindings::soc_device_attribute>, 61 + } 62 + 63 + fn cstring_to_c(mcs: &Option<CString>) -> *const kernel::ffi::c_char { 64 + mcs.as_ref() 65 + .map(|cs| cs.as_char_ptr()) 66 + .unwrap_or(core::ptr::null()) 67 + } 68 + 69 + impl BuiltAttributes { 70 + fn as_mut_ptr(&self) -> *mut bindings::soc_device_attribute { 71 + self.inner.get() 72 + } 73 + } 74 + 75 + impl Attributes { 76 + fn build(self) -> BuiltAttributes { 77 + BuiltAttributes { 78 + inner: Opaque::new(bindings::soc_device_attribute { 79 + machine: cstring_to_c(&self.machine), 80 + family: cstring_to_c(&self.family), 81 + revision: cstring_to_c(&self.revision), 82 + serial_number: cstring_to_c(&self.serial_number), 83 + soc_id: cstring_to_c(&self.soc_id), 84 + data: core::ptr::null(), 85 + custom_attr_group: core::ptr::null(), 86 + }), 87 + _backing: self, 88 + } 89 + } 90 + } 91 + 92 + #[pin_data(PinnedDrop)] 93 + /// Registration handle for your soc_dev. If you let it go out of scope, your soc_dev will be 94 + /// unregistered. 95 + pub struct Registration { 96 + #[pin] 97 + attr: BuiltAttributes, 98 + soc_dev: NonNull<bindings::soc_device>, 99 + } 100 + 101 + // SAFETY: We provide no operations through `&Registration`. 102 + unsafe impl Sync for Registration {} 103 + 104 + // SAFETY: All pointers are normal allocations, not thread-specific. 105 + unsafe impl Send for Registration {} 106 + 107 + #[pinned_drop] 108 + impl PinnedDrop for Registration { 109 + fn drop(self: Pin<&mut Self>) { 110 + // SAFETY: Device always contains a live pointer to a soc_device that can be unregistered 111 + unsafe { bindings::soc_device_unregister(self.soc_dev.as_ptr()) } 112 + } 113 + } 114 + 115 + impl Registration { 116 + /// Register a new SoC device 117 + pub fn new(attr: Attributes) -> impl PinInit<Self, Error> { 118 + try_pin_init!(Self { 119 + attr: attr.build(), 120 + soc_dev: { 121 + // SAFETY: 122 + // * The struct provided through attr is backed by pinned data next to it, 123 + // so as long as attr lives, the strings pointed to by the struct will too. 124 + // * `attr` is pinned, so the pinned data won't move. 125 + // * If it returns a device, and so others may try to read this data, by 126 + // caller invariant, `attr` won't be released until the device is. 127 + let raw_soc = error::from_err_ptr(unsafe { 128 + bindings::soc_device_register(attr.as_mut_ptr()) 129 + })?; 130 + 131 + NonNull::new(raw_soc).ok_or(EINVAL)? 132 + }, 133 + }? Error) 134 + } 135 + }