lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250819-qcom-socinfo-v1-4-e8d32cc81270@google.com>
Date: Tue, 19 Aug 2025 23:12:35 +0000
From: Matthew Maurer <mmaurer@...gle.com>
To: Miguel Ojeda <ojeda@...nel.org>, Alex Gaynor <alex.gaynor@...il.com>, 
	Boqun Feng <boqun.feng@...il.com>, Gary Guo <gary@...yguo.net>, 
	"Björn Roy Baron" <bjorn3_gh@...tonmail.com>, Andreas Hindborg <a.hindborg@...nel.org>, 
	Alice Ryhl <aliceryhl@...gle.com>, Trevor Gross <tmgross@...ch.edu>, 
	Danilo Krummrich <dakr@...nel.org>, Greg Kroah-Hartman <gregkh@...uxfoundation.org>, 
	"Rafael J. Wysocki" <rafael@...nel.org>, Sami Tolvanen <samitolvanen@...gle.com>, 
	Timur Tabi <ttabi@...dia.com>, Benno Lossin <lossin@...nel.org>, 
	Dirk Beheme <dirk.behme@...bosch.com>
Cc: linux-kernel@...r.kernel.org, rust-for-linux@...r.kernel.org, 
	Matthew Maurer <mmaurer@...gle.com>
Subject: [PATCH WIP 4/5] soc: qcom: socinfo: `File`-based example

Re-implements qcom-socinfo driver in Rust, using `File`-based DebugFS
bindings.

Signed-off-by: Matthew Maurer <mmaurer@...gle.com>
---
 drivers/soc/qcom/Kconfig                           |  12 +
 drivers/soc/qcom/Makefile                          |   1 +
 drivers/soc/qcom/smem.c                            |   4 +
 drivers/soc/qcom/socinfo_rust/bindings.rs          | 126 +++++
 drivers/soc/qcom/socinfo_rust/data.rs              | 387 +++++++++++++++
 drivers/soc/qcom/socinfo_rust/socinfo_rust_file.rs | 538 +++++++++++++++++++++
 rust/bindings/bindings_helper.h                    |   6 +
 7 files changed, 1074 insertions(+)

diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 2caadbbcf8307ff94f5afbdd1481e5e5e291749f..362ea8c1a18a24a06bb5456e7d1ac8a0cb1003b5 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -227,6 +227,18 @@ config QCOM_SOCINFO
 	 Say yes here to support the Qualcomm socinfo driver, providing
 	 information about the SoC to user space.
 
+config QCOM_SOCINFO_RUST
+	tristate "Qualcomm socinfo driver"
+	depends on QCOM_SMEM && RUST
+	select SOC_BUS
+	help
+	 Say yes here to support the Qualcomm socinfo driver, providing
+	 information about the SoC to user space.
+
+	 This is a draft Rust re-implementation which will enable two
+	 additional copies of the driver to registered alongside the
+	 original.
+
 config QCOM_SPM
 	tristate "Qualcomm Subsystem Power Manager (SPM)"
 	depends on ARCH_QCOM || COMPILE_TEST
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index b7f1d2a5736748b8772c090fd24462fa91f321c6..6453a4f4f7da89d4e1677ad8f75257e94cec90f4 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -40,3 +40,4 @@ qcom_ice-objs			+= ice.o
 obj-$(CONFIG_QCOM_INLINE_CRYPTO_ENGINE)	+= qcom_ice.o
 obj-$(CONFIG_QCOM_PBS) +=	qcom-pbs.o
 obj-$(CONFIG_QCOM_UBWC_CONFIG) += ubwc_config.o
+obj-$(CONFIG_QCOM_SOCINFO_RUST) += socinfo_rust/socinfo_rust_file.o
diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c
index cf425930539e406fb81307a17803955371545f32..5279db46a1e0dd7b2994b79d131367175e35290f 100644
--- a/drivers/soc/qcom/smem.c
+++ b/drivers/soc/qcom/smem.c
@@ -1230,7 +1230,11 @@ static int qcom_smem_probe(struct platform_device *pdev)
 
 	__smem = smem;
 
+	// TODO don't double load, this is just to diff the debugfs
 	smem->socinfo = platform_device_register_data(&pdev->dev, "qcom-socinfo",
+						      PLATFORM_DEVID_NONE, NULL, 0);
+	// TODO MODULE_ALIAS
+	smem->socinfo = platform_device_register_data(&pdev->dev, "qcom_socinfo_driver_file_rust",
 						      PLATFORM_DEVID_NONE, NULL,
 						      0);
 	if (IS_ERR(smem->socinfo))
diff --git a/drivers/soc/qcom/socinfo_rust/bindings.rs b/drivers/soc/qcom/socinfo_rust/bindings.rs
new file mode 100644
index 0000000000000000000000000000000000000000..8c2b5cecbfdde05e1a81ad0c78be0e7b6432afc5
--- /dev/null
+++ b/drivers/soc/qcom/socinfo_rust/bindings.rs
@@ -0,0 +1,126 @@
+// SPDX-License-Identifier: GPL-2.0
+
+// Copyright (C) 2025 Google LLC.
+
+use core::ops::Deref;
+use kernel::error::from_err_ptr;
+use kernel::ffi::c_char;
+use kernel::prelude::*;
+use kernel::transmute::{sized_from_bytes, sized_from_bytes_mut, AsBytes, FromBytes};
+
+pub(crate) fn qcom_smem_get(host: i32, item: u32) -> Result<&'static [u8]> {
+    let mut size = 0;
+    // SAFETY: qcom_smem_get only requires that the size pointer be a writable size_t,
+    // host and item are error checked in the qcom_smem module.
+    let err_ptr = unsafe { kernel::bindings::qcom_smem_get(host as u32, item, &mut size) };
+    let ptr = from_err_ptr(err_ptr)?;
+    // SAFETY: If qcom_smem_get does not return an error, the returned pointer points to a readable
+    // byte buffer with its size written into size. Because these buffers are derived from the
+    // static ranges in the DT, this buffer remains accessible even if the qcom_smem module is
+    // unloaded, so 'static is appropriate. The underlying buffer cannot mutate, so upgrading it
+    // to a reference is allowed.
+    Ok(unsafe { core::slice::from_raw_parts(ptr as *const u8, size) })
+}
+
+pub(crate) const SMEM_IMAGE_VERSION_TABLE: u32 = 469;
+
+// bindgen does not know that struct socinfo is AsBytes, so we implement it here
+#[derive(Default, Copy, Clone)]
+#[repr(transparent)]
+pub(crate) struct RawSocInfo(kernel::bindings::socinfo);
+// SAFETY: Transparent wrapper for the socinfo struct, which is a padding-free
+// C-origin type
+unsafe impl AsBytes for RawSocInfo {}
+// SAFETY: Transparent wrapper for the socinfo struct, a C-origin type
+unsafe impl FromBytes for RawSocInfo {
+    fn from_bytes(bytes: &[u8]) -> Option<&Self> {
+        sized_from_bytes(bytes)
+    }
+    fn from_bytes_mut(bytes: &mut [u8]) -> Option<&mut Self> {
+        sized_from_bytes_mut(bytes)
+    }
+}
+
+impl Deref for RawSocInfo {
+    type Target = kernel::bindings::socinfo;
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}
+
+impl RawSocInfo {
+    /// Produce RawSocInfo by initializing from a byte buffer that may be too small.
+    /// Code using the resulting value is expected to use the info_fmt field to determine
+    /// which fields have meaningful values.
+    pub(crate) fn from_partial_bytes(soc_info_mem: &[u8]) -> Self {
+        let mut soc_info = RawSocInfo::default();
+        let byte_view = soc_info.as_mut_bytes();
+        let len = core::cmp::min(soc_info_mem.len(), byte_view.len());
+        byte_view[..len].copy_from_slice(&soc_info_mem[..len]);
+        soc_info
+    }
+}
+
+#[repr(C)]
+pub(crate) struct PmicEntry {
+    pub(crate) model: u32,
+    pub(crate) die_rev: u32,
+}
+
+// SAFETY: All bit patterns are valid for all fields, and C layout for two u32s
+// does not require padding
+unsafe impl AsBytes for PmicEntry {}
+// SAFETY: All bit patterns are valid for all fields
+unsafe impl FromBytes for PmicEntry {
+    fn from_bytes(bytes: &[u8]) -> Option<&Self> {
+        sized_from_bytes(bytes)
+    }
+    fn from_bytes_mut(bytes: &mut [u8]) -> Option<&mut Self> {
+        sized_from_bytes_mut(bytes)
+    }
+}
+
+#[derive(Default)]
+#[repr(transparent)]
+pub(crate) struct PmicArray(pub(crate) &'static [PmicEntry]);
+
+impl PmicArray {
+    pub(crate) fn from_bytes(bytes: &'static [u8]) -> Option<Self> {
+        Some(Self(FromBytes::from_bytes(bytes)?))
+    }
+}
+
+const SMEM_IMAGE_VERSION_NAME_SIZE: usize = 75;
+const SMEM_IMAGE_VERSION_VARIANT_SIZE: usize = 20;
+const SMEM_IMAGE_VERSION_OEM_SIZE: usize = 32;
+
+#[repr(C)]
+pub(crate) struct ImageVersion {
+    pub(crate) name: [c_char; SMEM_IMAGE_VERSION_NAME_SIZE],
+    pub(crate) variant: [c_char; SMEM_IMAGE_VERSION_VARIANT_SIZE],
+    pub(crate) pad: c_char,
+    pub(crate) oem: [c_char; SMEM_IMAGE_VERSION_OEM_SIZE],
+}
+
+// SAFETY: All bit patterns are valid for all fields, and C layout for two u32s
+// does not require padding
+unsafe impl AsBytes for ImageVersion {}
+// SAFETY: All bit patterns are valid for all fields
+unsafe impl FromBytes for ImageVersion {
+    fn from_bytes(bytes: &[u8]) -> Option<&Self> {
+        sized_from_bytes(bytes)
+    }
+    fn from_bytes_mut(bytes: &mut [u8]) -> Option<&mut Self> {
+        sized_from_bytes_mut(bytes)
+    }
+}
+
+#[derive(Default)]
+#[repr(transparent)]
+pub(crate) struct ImageVersions(pub(crate) &'static [ImageVersion]);
+
+impl ImageVersions {
+    pub(crate) fn from_bytes(bytes: &'static [u8]) -> Option<Self> {
+        Some(Self(FromBytes::from_bytes(bytes)?))
+    }
+}
diff --git a/drivers/soc/qcom/socinfo_rust/data.rs b/drivers/soc/qcom/socinfo_rust/data.rs
new file mode 100644
index 0000000000000000000000000000000000000000..1575d3c5452f801ae27c2c67ea71410e36521846
--- /dev/null
+++ b/drivers/soc/qcom/socinfo_rust/data.rs
@@ -0,0 +1,387 @@
+// SPDX-License-Identifier: GPL-2.0
+
+// Copyright (C) 2025 Google LLC.
+
+//! Data tables for QCom SocInfo driver
+use kernel::c_str;
+use kernel::prelude::*;
+
+macro_rules! id_entry {
+    ($id:ident) => {
+        kernel::macros::paste! {
+            SocId {
+                id: kernel::bindings::[<QCOM_ID_ $id>],
+                name: c_str!(stringify!($id)),
+            }
+        }
+    };
+    ($id:ident, $name:tt) => {
+        SocId {
+            id: kernel::macros::paste!(kernel::bindings::[<QCOM_ID_ $id>]), name: c_str!($name),
+        }
+    }
+}
+
+pub(crate) struct SocId {
+    pub(crate) id: u32,
+    pub(crate) name: &'static CStr,
+}
+
+pub(crate) static SOC_IDS: &[SocId] = &[
+    { id_entry!(MSM8260) },
+    { id_entry!(MSM8660) },
+    { id_entry!(APQ8060) },
+    { id_entry!(MSM8960) },
+    { id_entry!(APQ8064) },
+    { id_entry!(MSM8930) },
+    { id_entry!(MSM8630) },
+    { id_entry!(MSM8230) },
+    { id_entry!(APQ8030) },
+    { id_entry!(MSM8627) },
+    { id_entry!(MSM8227) },
+    { id_entry!(MSM8660A) },
+    { id_entry!(MSM8260A) },
+    { id_entry!(APQ8060A) },
+    { id_entry!(MSM8974) },
+    { id_entry!(MSM8225) },
+    { id_entry!(MSM8625) },
+    { id_entry!(MPQ8064) },
+    { id_entry!(MSM8960AB) },
+    { id_entry!(APQ8060AB) },
+    { id_entry!(MSM8260AB) },
+    { id_entry!(MSM8660AB) },
+    { id_entry!(MSM8930AA) },
+    { id_entry!(MSM8630AA) },
+    { id_entry!(MSM8230AA) },
+    { id_entry!(MSM8626) },
+    { id_entry!(MSM8610) },
+    { id_entry!(APQ8064AB) },
+    { id_entry!(MSM8930AB) },
+    { id_entry!(MSM8630AB) },
+    { id_entry!(MSM8230AB) },
+    { id_entry!(APQ8030AB) },
+    { id_entry!(MSM8226) },
+    { id_entry!(MSM8526) },
+    { id_entry!(APQ8030AA) },
+    { id_entry!(MSM8110) },
+    { id_entry!(MSM8210) },
+    { id_entry!(MSM8810) },
+    { id_entry!(MSM8212) },
+    { id_entry!(MSM8612) },
+    { id_entry!(MSM8112) },
+    { id_entry!(MSM8125) },
+    { id_entry!(MSM8225Q) },
+    { id_entry!(MSM8625Q) },
+    { id_entry!(MSM8125Q) },
+    { id_entry!(APQ8064AA) },
+    { id_entry!(APQ8084) },
+    { id_entry!(MSM8130) },
+    { id_entry!(MSM8130AA) },
+    { id_entry!(MSM8130AB) },
+    { id_entry!(MSM8627AA) },
+    { id_entry!(MSM8227AA) },
+    { id_entry!(APQ8074) },
+    { id_entry!(MSM8274) },
+    { id_entry!(MSM8674) },
+    { id_entry!(MDM9635) },
+    { id_entry!(MSM8974PRO_AC, "MSM8974PRO-AC") },
+    { id_entry!(MSM8126) },
+    { id_entry!(APQ8026) },
+    { id_entry!(MSM8926) },
+    { id_entry!(IPQ8062) },
+    { id_entry!(IPQ8064) },
+    { id_entry!(IPQ8066) },
+    { id_entry!(IPQ8068) },
+    { id_entry!(MSM8326) },
+    { id_entry!(MSM8916) },
+    { id_entry!(MSM8994) },
+    { id_entry!(APQ8074PRO_AA, "APQ8074PRO-AA") },
+    { id_entry!(APQ8074PRO_AB, "APQ8074PRO-AB") },
+    { id_entry!(APQ8074PRO_AC, "APQ8074PRO-AC") },
+    { id_entry!(MSM8274PRO_AA, "MSM8274PRO-AA") },
+    { id_entry!(MSM8274PRO_AB, "MSM8274PRO-AB") },
+    { id_entry!(MSM8274PRO_AC, "MSM8274PRO-AC") },
+    { id_entry!(MSM8674PRO_AA, "MSM8674PRO-AA") },
+    { id_entry!(MSM8674PRO_AB, "MSM8674PRO-AB") },
+    { id_entry!(MSM8674PRO_AC, "MSM8674PRO-AC") },
+    { id_entry!(MSM8974PRO_AA, "MSM8974PRO-AA") },
+    { id_entry!(MSM8974PRO_AB, "MSM8974PRO-AB") },
+    { id_entry!(APQ8028) },
+    { id_entry!(MSM8128) },
+    { id_entry!(MSM8228) },
+    { id_entry!(MSM8528) },
+    { id_entry!(MSM8628) },
+    { id_entry!(MSM8928) },
+    { id_entry!(MSM8510) },
+    { id_entry!(MSM8512) },
+    { id_entry!(MSM8936) },
+    { id_entry!(MDM9640) },
+    { id_entry!(MSM8939) },
+    { id_entry!(APQ8036) },
+    { id_entry!(APQ8039) },
+    { id_entry!(MSM8236) },
+    { id_entry!(MSM8636) },
+    { id_entry!(MSM8909) },
+    { id_entry!(MSM8996) },
+    { id_entry!(APQ8016) },
+    { id_entry!(MSM8216) },
+    { id_entry!(MSM8116) },
+    { id_entry!(MSM8616) },
+    { id_entry!(MSM8992) },
+    { id_entry!(APQ8092) },
+    { id_entry!(APQ8094) },
+    { id_entry!(MSM8209) },
+    { id_entry!(MSM8208) },
+    { id_entry!(MDM9209) },
+    { id_entry!(MDM9309) },
+    { id_entry!(MDM9609) },
+    { id_entry!(MSM8239) },
+    { id_entry!(MSM8952) },
+    { id_entry!(APQ8009) },
+    { id_entry!(MSM8956) },
+    { id_entry!(MSM8929) },
+    { id_entry!(MSM8629) },
+    { id_entry!(MSM8229) },
+    { id_entry!(APQ8029) },
+    { id_entry!(APQ8056) },
+    { id_entry!(MSM8609) },
+    { id_entry!(APQ8076) },
+    { id_entry!(MSM8976) },
+    { id_entry!(IPQ8065) },
+    { id_entry!(IPQ8069) },
+    { id_entry!(MDM9650) },
+    { id_entry!(MDM9655) },
+    { id_entry!(MDM9250) },
+    { id_entry!(MDM9255) },
+    { id_entry!(MDM9350) },
+    { id_entry!(APQ8052) },
+    { id_entry!(MDM9607) },
+    { id_entry!(APQ8096) },
+    { id_entry!(MSM8998) },
+    { id_entry!(MSM8953) },
+    { id_entry!(MSM8937) },
+    { id_entry!(APQ8037) },
+    { id_entry!(MDM8207) },
+    { id_entry!(MDM9207) },
+    { id_entry!(MDM9307) },
+    { id_entry!(MDM9628) },
+    { id_entry!(MSM8909W) },
+    { id_entry!(APQ8009W) },
+    { id_entry!(MSM8996L) },
+    { id_entry!(MSM8917) },
+    { id_entry!(APQ8053) },
+    { id_entry!(MSM8996SG) },
+    { id_entry!(APQ8017) },
+    { id_entry!(MSM8217) },
+    { id_entry!(MSM8617) },
+    { id_entry!(MSM8996AU) },
+    { id_entry!(APQ8096AU) },
+    { id_entry!(APQ8096SG) },
+    { id_entry!(MSM8940) },
+    { id_entry!(SDX201) },
+    { id_entry!(SDM660) },
+    { id_entry!(SDM630) },
+    { id_entry!(APQ8098) },
+    { id_entry!(MSM8920) },
+    { id_entry!(SDM845) },
+    { id_entry!(MDM9206) },
+    { id_entry!(IPQ8074) },
+    { id_entry!(SDA660) },
+    { id_entry!(SDM658) },
+    { id_entry!(SDA658) },
+    { id_entry!(SDA630) },
+    { id_entry!(MSM8905) },
+    { id_entry!(SDX202) },
+    { id_entry!(SDM670) },
+    { id_entry!(SDM450) },
+    { id_entry!(SM8150) },
+    { id_entry!(SDA845) },
+    { id_entry!(IPQ8072) },
+    { id_entry!(IPQ8076) },
+    { id_entry!(IPQ8078) },
+    { id_entry!(SDM636) },
+    { id_entry!(SDA636) },
+    { id_entry!(SDM632) },
+    { id_entry!(SDA632) },
+    { id_entry!(SDA450) },
+    { id_entry!(SDM439) },
+    { id_entry!(SDM429) },
+    { id_entry!(SM8250) },
+    { id_entry!(SA8155) },
+    { id_entry!(SDA439) },
+    { id_entry!(SDA429) },
+    { id_entry!(SM7150) },
+    { id_entry!(SM7150P) },
+    { id_entry!(IPQ8070) },
+    { id_entry!(IPQ8071) },
+    { id_entry!(QM215) },
+    { id_entry!(IPQ8072A) },
+    { id_entry!(IPQ8074A) },
+    { id_entry!(IPQ8076A) },
+    { id_entry!(IPQ8078A) },
+    { id_entry!(SM6125) },
+    { id_entry!(IPQ8070A) },
+    { id_entry!(IPQ8071A) },
+    { id_entry!(IPQ8172) },
+    { id_entry!(IPQ8173) },
+    { id_entry!(IPQ8174) },
+    { id_entry!(IPQ6018) },
+    { id_entry!(IPQ6028) },
+    { id_entry!(SDM429W) },
+    { id_entry!(SM4250) },
+    { id_entry!(IPQ6000) },
+    { id_entry!(IPQ6010) },
+    { id_entry!(SC7180) },
+    { id_entry!(SM6350) },
+    { id_entry!(QCM2150) },
+    { id_entry!(SDA429W) },
+    { id_entry!(SM8350) },
+    { id_entry!(QCM2290) },
+    { id_entry!(SM7125) },
+    { id_entry!(SM6115) },
+    { id_entry!(IPQ5010) },
+    { id_entry!(IPQ5018) },
+    { id_entry!(IPQ5028) },
+    { id_entry!(SC8280XP) },
+    { id_entry!(IPQ6005) },
+    { id_entry!(QRB5165) },
+    { id_entry!(SM8450) },
+    { id_entry!(SM7225) },
+    { id_entry!(SA8295P) },
+    { id_entry!(SA8540P) },
+    { id_entry!(QCM4290) },
+    { id_entry!(QCS4290) },
+    { id_entry!(SM7325) },
+    { id_entry!(SM8450_2, "SM8450") },
+    { id_entry!(SM8450_3, "SM8450") },
+    { id_entry!(SC7280) },
+    { id_entry!(SC7180P) },
+    { id_entry!(QCM6490) },
+    { id_entry!(SM7325P) },
+    { id_entry!(IPQ5000) },
+    { id_entry!(IPQ0509) },
+    { id_entry!(IPQ0518) },
+    { id_entry!(SM6375) },
+    { id_entry!(IPQ9514) },
+    { id_entry!(IPQ9550) },
+    { id_entry!(IPQ9554) },
+    { id_entry!(IPQ9570) },
+    { id_entry!(IPQ9574) },
+    { id_entry!(SM8550) },
+    { id_entry!(IPQ5016) },
+    { id_entry!(IPQ9510) },
+    { id_entry!(QRB4210) },
+    { id_entry!(QRB2210) },
+    { id_entry!(SAR2130P) },
+    { id_entry!(SM8475) },
+    { id_entry!(SM8475P) },
+    { id_entry!(SA8255P) },
+    { id_entry!(SA8775P) },
+    { id_entry!(QRU1000) },
+    { id_entry!(SM8475_2) },
+    { id_entry!(QDU1000) },
+    { id_entry!(X1E80100) },
+    { id_entry!(SM8650) },
+    { id_entry!(SM4450) },
+    { id_entry!(SAR1130P) },
+    { id_entry!(QDU1010) },
+    { id_entry!(QRU1032) },
+    { id_entry!(QRU1052) },
+    { id_entry!(QRU1062) },
+    { id_entry!(IPQ5332) },
+    { id_entry!(IPQ5322) },
+    { id_entry!(IPQ5312) },
+    { id_entry!(IPQ5302) },
+    { id_entry!(QCS8550) },
+    { id_entry!(QCM8550) },
+    { id_entry!(IPQ5300) },
+    { id_entry!(IPQ5321) },
+    { id_entry!(IPQ5424) },
+    { id_entry!(IPQ5404) },
+    { id_entry!(QCS9100) },
+    { id_entry!(QCS8300) },
+    { id_entry!(QCS8275) },
+    { id_entry!(QCS9075) },
+    { id_entry!(QCS615) },
+];
+
+pub(crate) const PMIC_MODELS: [Option<&str>; 84] = {
+    let mut models = [None; 84];
+    models[0] = Some("Unknown PMIC model");
+    models[1] = Some("PM8941");
+    models[2] = Some("PM8841");
+    models[3] = Some("PM8019");
+    models[4] = Some("PM8226");
+    models[5] = Some("PM8110");
+    models[6] = Some("PMA8084");
+    models[7] = Some("PMI8962");
+    models[8] = Some("PMD9635");
+    models[9] = Some("PM8994");
+    models[10] = Some("PMI8994");
+    models[11] = Some("PM8916");
+    models[12] = Some("PM8004");
+    models[13] = Some("PM8909/PM8058");
+    models[14] = Some("PM8028");
+    models[15] = Some("PM8901");
+    models[16] = Some("PM8950/PM8027");
+    models[17] = Some("PMI8950/ISL9519");
+    models[18] = Some("PMK8001/PM8921");
+    models[19] = Some("PMI8996/PM8018");
+    models[20] = Some("PM8998/PM8015");
+    models[21] = Some("PMI8998/PM8014");
+    models[22] = Some("PM8821");
+    models[23] = Some("PM8038");
+    models[24] = Some("PM8005/PM8922");
+    models[25] = Some("PM8917/PM8937");
+    models[26] = Some("PM660L");
+    models[27] = Some("PM660");
+    models[30] = Some("PM8150");
+    models[31] = Some("PM8150L");
+    models[32] = Some("PM8150B");
+    models[33] = Some("PMK8002");
+    models[36] = Some("PM8009");
+    models[37] = Some("PMI632");
+    models[38] = Some("PM8150C");
+    models[40] = Some("PM6150");
+    models[41] = Some("SMB2351");
+    models[44] = Some("PM8008");
+    models[45] = Some("PM6125");
+    models[46] = Some("PM7250B");
+    models[47] = Some("PMK8350");
+    models[48] = Some("PM8350");
+    models[49] = Some("PM8350C");
+    models[50] = Some("PM8350B");
+    models[51] = Some("PMR735A");
+    models[52] = Some("PMR735B");
+    models[54] = Some("PM6350");
+    models[55] = Some("PM4125");
+    models[58] = Some("PM8450");
+    models[65] = Some("PM8010");
+    models[69] = Some("PM8550VS");
+    models[70] = Some("PM8550VE");
+    models[71] = Some("PM8550B");
+    models[72] = Some("PMR735D");
+    models[73] = Some("PM8550");
+    models[74] = Some("PMK8550");
+    models[82] = Some("PMC8380");
+    models[83] = Some("SMB2360");
+    models
+};
+
+pub(crate) const IMAGE_NAMES: &[(&CStr, usize)] = &[
+    (c_str!("adsp"), 12),
+    (c_str!("apps"), 10),
+    (c_str!("appsbl"), 9),
+    (c_str!("boot"), 0),
+    (c_str!("cnss"), 13),
+    (c_str!("mpss"), 11),
+    (c_str!("rpm"), 3),
+    (c_str!("tz"), 1),
+    (c_str!("video"), 14),
+    (c_str!("dsps"), 15),
+    (c_str!("cdsp"), 16),
+    (c_str!("cdsp1"), 19),
+    (c_str!("gpdsp"), 20),
+    (c_str!("gpdsp1"), 21),
+    (c_str!("tme"), 28),
+];
diff --git a/drivers/soc/qcom/socinfo_rust/socinfo_rust_file.rs b/drivers/soc/qcom/socinfo_rust/socinfo_rust_file.rs
new file mode 100644
index 0000000000000000000000000000000000000000..6a7f7af807b53341325dd3e5c5318f36efc52b1d
--- /dev/null
+++ b/drivers/soc/qcom/socinfo_rust/socinfo_rust_file.rs
@@ -0,0 +1,538 @@
+// SPDX-License-Identifier: GPL-2.0
+
+// Copyright (C) 2025 Google LLC.
+
+#![recursion_limit = "256"]
+
+//! Re-implementation of Qualcomm's Socinfo driver in Rust
+use core::convert::From;
+use core::fmt;
+use core::fmt::{Debug, Formatter};
+use core::mem::MaybeUninit;
+use kernel::c_str;
+use kernel::debugfs::{Dir, File, Render};
+use kernel::device::Core;
+use kernel::module_platform_driver;
+use kernel::platform::{self, Device};
+use kernel::prelude::*;
+use kernel::soc;
+use kernel::str::CString;
+
+use pin_init::pin_init_from_closure;
+
+mod bindings;
+mod data;
+
+use bindings::{qcom_smem_get, ImageVersion, ImageVersions, PmicArray, PmicEntry, RawSocInfo};
+use data::{IMAGE_NAMES, PMIC_MODELS, SOC_IDS};
+
+module_platform_driver! {
+    type: QcomSocInfo,
+    name: "qcom_socinfo_driver_file_rust",
+    authors: ["Matthew Maurer"],
+    description: "Rust re-implementation of Qualcomm's Socinfo driver",
+    license: "GPL",
+}
+
+#[pin_data]
+struct QcomSocInfo {
+    #[pin]
+    registration: soc::DeviceRegistration,
+    #[pin]
+    _debugfs: QcomSocInfoDebugFs,
+}
+
+#[derive(Default)]
+#[repr(transparent)]
+struct PmicModel(u32);
+
+impl From<u32> for PmicModel {
+    fn from(x: u32) -> Self {
+        Self(x)
+    }
+}
+
+impl Debug for PmicModel {
+    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+        let model = SocInfo::version_split(self.0).1;
+        if let Some(Some(model)) = PMIC_MODELS.get(model as usize) {
+            write!(f, "{model}")
+        } else {
+            write!(f, "unknown ({})", model)
+        }
+    }
+}
+
+#[derive(Default)]
+#[repr(transparent)]
+struct PmicDieRev(u32);
+
+impl From<u32> for PmicDieRev {
+    fn from(x: u32) -> Self {
+        Self(x)
+    }
+}
+
+impl Debug for PmicDieRev {
+    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+        let (major, minor) = SocInfo::version_split(self.0);
+        write!(f, "{major}.{minor}")
+    }
+}
+
+impl Render for PmicArray {
+    fn render(&self, f: &mut Formatter<'_>) -> fmt::Result {
+        for pmic_entry in self.0 {
+            let (die_rev_major, die_rev_minor) =
+                SocInfo::version_split(u32::from_le(pmic_entry.die_rev));
+            let model_idx = SocInfo::version_split(pmic_entry.model).1 as usize;
+            if let Some(Some(model)) = PMIC_MODELS.get(model_idx) {
+                writeln!(f, "{model} {die_rev_major}.{die_rev_minor}")?
+            } else {
+                writeln!(f, "unknown ({})", pmic_entry.model)?
+            }
+        }
+        Ok(())
+    }
+}
+
+struct Params {
+    info_fmt: u32,
+    build_id: [u8; 32],
+    raw_version: Option<u32>,
+    hardware_platform: Option<u32>,
+    platform_version: Option<u32>,
+    accessory_chip: Option<u32>,
+    hardware_platform_subtype: Option<u32>,
+    pmic_model: Option<PmicModel>,
+    pmic_die_rev: Option<PmicDieRev>,
+    foundry_id: Option<u32>,
+    pmic_model_array: Option<PmicArray>,
+    chip_family: Option<u32>,       // x32
+    raw_device_family: Option<u32>, // x32
+    raw_device_number: Option<u32>, // x32
+    nproduct_id: Option<u32>,
+    chip_id: Option<[u8; 32]>,
+    num_clusters: Option<u32>,
+    ncluster_array_offset: Option<u32>,
+    num_subset_parts: Option<u32>,
+    nsubset_parts_array_offset: Option<u32>,
+    nmodem_supported: Option<u32>,
+    feature_code: Option<u32>,
+    pcode: Option<u32>,
+    oem_variant: Option<u32>,
+    boot_core: Option<u32>,
+    boot_cluster: Option<u32>,
+    num_func_clusters: Option<u32>,
+    versions: Option<ImageVersions>,
+}
+
+#[derive(Copy, Clone)]
+struct SocInfo<'a> {
+    soc_info: RawSocInfo,
+    soc_info_mem: &'a [u8],
+    version_mem: &'a [u8],
+}
+
+impl<'a> SocInfo<'a> {
+    fn from_mem(soc_info_mem: &'a [u8], version_mem: &'a [u8]) -> Self {
+        Self {
+            soc_info: RawSocInfo::from_partial_bytes(soc_info_mem),
+            soc_info_mem,
+            version_mem,
+        }
+    }
+    fn id(&self) -> u32 {
+        u32::from_le(self.soc_info.id)
+    }
+    fn version_split(ver: u32) -> (u16, u16) {
+        let major = (ver >> 16) as u16;
+        let minor = (ver & 0xFFFF) as u16;
+        (major, minor)
+    }
+    fn version_fuse(major: u16, minor: u16) -> u32 {
+        (u32::from(major) << 16) | u32::from(minor)
+    }
+    fn version(&self) -> (u16, u16) {
+        Self::version_split(self.soc_info.ver)
+    }
+    fn serial(&self) -> u32 {
+        u32::from_le(self.soc_info.id)
+    }
+    fn machine(&self) -> Result<Option<CString>> {
+        for soc in SOC_IDS {
+            if soc.id == self.id() {
+                return Ok(Some(soc.name.to_cstring()?));
+            }
+        }
+        Ok(None)
+    }
+    fn device_attribute(&self) -> Result<soc::DeviceAttribute> {
+        Ok(soc::DeviceAttribute {
+            family: Some(c_str!("Snapdragon").to_cstring()?),
+            machine: self.machine()?,
+            revision: Some(CString::try_from_fmt(fmt!(
+                "{}.{}",
+                self.version().0,
+                self.version().1
+            ))?),
+            serial_number: Some(CString::try_from_fmt(fmt!("{}", self.serial()))?),
+            soc_id: Some(CString::try_from_fmt(fmt!("{}", self.id()))?),
+        })
+    }
+}
+
+macro_rules! u32_le_versioned {
+    { $params:expr, $self:ident,
+        [ $( { $major:expr, $minor:expr, { $( $dst:ident: $src:ident ),* } } ),*  ] } => {$(
+        if $params.info_fmt >= SocInfo::version_fuse($major, $minor) {
+            $( $params.$dst = Some(u32::from_le($self.soc_info.$src).into()) );*
+        }
+    )*}
+}
+
+impl SocInfo<'static> {
+    fn build_params(&self) -> Result<Params> {
+        let mut params = Params {
+            build_id: self.soc_info.build_id,
+            info_fmt: u32::from_le(self.soc_info.fmt),
+            raw_version: None,
+            hardware_platform: None,
+            platform_version: None,
+            accessory_chip: None,
+            hardware_platform_subtype: None,
+            pmic_model: None,
+            pmic_die_rev: None,
+            foundry_id: None,
+            pmic_model_array: None,
+            chip_family: None,
+            raw_device_family: None,
+            raw_device_number: None,
+            nproduct_id: None,
+            chip_id: None,
+            num_clusters: None,
+            ncluster_array_offset: None,
+            num_subset_parts: None,
+            nsubset_parts_array_offset: None,
+            nmodem_supported: None,
+            feature_code: None,
+            pcode: None,
+            oem_variant: None,
+            boot_core: None,
+            boot_cluster: None,
+            num_func_clusters: None,
+            versions: None,
+        };
+        u32_le_versioned! { params, self, [
+            {0, 2, { raw_version: raw_ver }},
+            {0, 3, { hardware_platform: hw_plat }},
+            {0, 4, { platform_version: plat_ver }},
+            {0, 5, { accessory_chip: accessory_chip }},
+            {0, 6, { hardware_platform_subtype: hw_plat_subtype }},
+            {0, 7, { pmic_model: pmic_model, pmic_die_rev: pmic_die_rev }},
+            {0, 9, { foundry_id: foundry_id }},
+            {0, 12, {
+                chip_family: chip_family,
+                raw_device_family: raw_device_family,
+                raw_device_number: raw_device_num
+            }},
+            {0, 13, { nproduct_id: nproduct_id }},
+            {0, 14, {
+                num_clusters: num_clusters,
+                ncluster_array_offset: ncluster_array_offset,
+                num_subset_parts: num_subset_parts,
+                nsubset_parts_array_offset: nsubset_parts_array_offset
+            }},
+            {0, 15, { nmodem_supported: nmodem_supported }},
+            {0, 16, { feature_code: feature_code, pcode: pcode }},
+            {0, 17, { oem_variant: oem_variant }},
+            {0, 19, {
+                boot_core: boot_core,
+                boot_cluster: boot_cluster,
+                num_func_clusters: num_func_clusters
+            }}
+        ]};
+        if params.info_fmt >= SocInfo::version_fuse(0, 11) {
+            let offset = u32::from_le(self.soc_info.pmic_array_offset) as usize;
+            let num_pmics = u32::from_le(self.soc_info.num_pmics) as usize;
+            let size = num_pmics * core::mem::size_of::<PmicEntry>();
+            params.pmic_model_array =
+                PmicArray::from_bytes(&self.soc_info_mem[offset..offset + size]);
+        }
+        if params.info_fmt >= SocInfo::version_fuse(0, 13) {
+            params.chip_id = Some(self.soc_info.chip_id);
+        }
+        params.versions = ImageVersions::from_bytes(self.version_mem);
+        Ok(params)
+    }
+}
+
+fn no_quirk<const SIZE: usize>(buf: &[u8; SIZE], f: &mut Formatter<'_>) -> fmt::Result {
+    if buf[0] == 0 {
+        writeln!(f)
+    } else {
+        nul_array(buf, f)
+    }
+}
+
+fn nul_array<const SIZE: usize>(buf: &[u8; SIZE], f: &mut Formatter<'_>) -> fmt::Result {
+    if let Some(end) = buf.iter().position(|x| *x == 0) {
+        if end == 0 {
+            // Match original driver quirk - empty strings don't have a trailing newline
+            return Ok(());
+        }
+        let Ok(c_str) = CStr::from_bytes_with_nul(&buf[0..=end]) else {
+            pr_warn!("Creating CStr from bytes with known first NUL failed?");
+            return Ok(());
+        };
+        writeln!(f, "{c_str}")
+    } else {
+        writeln!(f, "Missing NUL: {buf:?}")
+    }
+}
+
+fn hex(x: &u32, f: &mut Formatter<'_>) -> fmt::Result {
+    writeln!(f, "{x:#010x}")
+}
+
+#[pin_data]
+struct ImageVersionFiles {
+    _dir: Dir,
+    #[pin]
+    name: File<[u8; 75]>,
+    #[pin]
+    variant: File<[u8; 20]>,
+    #[pin]
+    oem: File<[u8; 32]>,
+}
+
+impl ImageVersionFiles {
+    fn create<'a>(
+        parent: &'a Dir,
+        image_name: &'a CStr,
+        version: &'a ImageVersion,
+    ) -> impl PinInit<Self> + 'a {
+        let dir = parent.subdir(image_name);
+        pin_init! {
+            Self {
+                _dir: dir.clone(),
+                name <- dir.read_callback_file(c_str!("name"), version.name, &nul_array),
+                variant <- dir.read_callback_file(c_str!("variant"), version.variant, &nul_array),
+                oem <- dir.read_callback_file(c_str!("oem"), version.oem, &nul_array),
+            }
+        }
+    }
+}
+
+#[pin_data]
+struct QcomSocInfoDebugFs {
+    _dir: Dir,
+    #[pin]
+    info_fmt: File<u32>,
+    #[pin]
+    build_id: File<[u8; 32]>,
+    #[pin]
+    raw_version: Option<File<u32>>,
+    #[pin]
+    hardware_platform: Option<File<u32>>,
+    #[pin]
+    platform_version: Option<File<u32>>,
+    #[pin]
+    accessory_chip: Option<File<u32>>,
+    #[pin]
+    hardware_platform_subtype: Option<File<u32>>,
+    #[pin]
+    pmic_model: Option<File<PmicModel>>,
+    #[pin]
+    pmic_die_rev: Option<File<PmicDieRev>>,
+    #[pin]
+    foundry_id: Option<File<u32>>,
+    #[pin]
+    pmic_model_array: Option<File<PmicArray>>,
+    #[pin]
+    chip_family: Option<File<u32>>,
+    #[pin]
+    raw_device_family: Option<File<u32>>,
+    #[pin]
+    raw_device_number: Option<File<u32>>,
+    #[pin]
+    nproduct_id: Option<File<u32>>,
+    #[pin]
+    chip_id: Option<File<[u8; 32]>>,
+    #[pin]
+    num_clusters: Option<File<u32>>,
+    #[pin]
+    ncluster_array_offset: Option<File<u32>>,
+    #[pin]
+    num_subset_parts: Option<File<u32>>,
+    #[pin]
+    nsubset_parts_array_offset: Option<File<u32>>,
+    #[pin]
+    nmodem_supported: Option<File<u32>>,
+    #[pin]
+    feature_code: Option<File<u32>>,
+    #[pin]
+    pcode: Option<File<u32>>,
+    #[pin]
+    oem_variant: Option<File<u32>>,
+    #[pin]
+    boot_core: Option<File<u32>>,
+    #[pin]
+    boot_cluster: Option<File<u32>>,
+    #[pin]
+    num_func_clusters: Option<File<u32>>,
+    versions: KVec<Pin<KBox<ImageVersionFiles>>>,
+}
+
+// TODO this doesn't seem like we should be defining it here, but without it,
+// it's hard to construct an `Option<File<u32>>`, which is required for this driver.
+fn pin_init_option<T, R, F, E, PI>(val: Option<T>, f: F) -> impl PinInit<Option<R>, E>
+where
+    F: FnOnce(T) -> PI,
+    PI: PinInit<R, E>,
+{
+    let init = move |slot: *mut Option<R>| -> Result<(), E> {
+        let Some(val) = val else {
+            // SAFETY: The constructor guarantees we're called with a writable pointer
+            unsafe { core::ptr::write(slot, None) };
+            return Ok(());
+        };
+
+        let slot_uninit: *mut Option<MaybeUninit<R>> = slot.cast();
+        // SAFETY: The constructor guarantees we're called with a writable pointer
+        // *mut Option<MaybeUninit<R>> is layout compatible with `Option<R>`
+        unsafe { core::ptr::write(slot_uninit, Some(MaybeUninit::uninit())) };
+        // SAFETY: We just initialized it, and we have unique access
+        let inner_slot: *mut R = unsafe { (*slot_uninit).as_mut().unwrap().as_mut_ptr() };
+        // SAFETY: `inner_slot` is a pointer to the uninitialized portion of the option.
+        if let Err(e) = unsafe { f(val).__pinned_init(inner_slot) } {
+            // Wipe out slot with a safe default
+            // SAFETY: The slot is still writable, and the other initializer has cleared out
+            // the payload.
+            unsafe { core::ptr::write(slot, None) };
+            return Err(e);
+        }
+
+        // Since we've initialized the `MaybeUninit` portion, we're fully initialized.
+        Ok(())
+    };
+
+    // SAFETY: If val is None, we always fully initialize it. If we successfully run the
+    // initializer, we fully initialize the Some arm. If we fail to run the initializer, we wipe it
+    // out with None before returning.
+    unsafe { pin_init_from_closure(init) }
+}
+
+macro_rules! create_optional_file {
+    ($dir:expr, $name:expr, $value:expr) => {
+        pin_init_option($value, |v| $dir.read_only_file(c_str!($name), v))
+    };
+    ($dir:expr, $name:expr, $value:expr, $callback:expr) => {
+        pin_init_option($value, |v| {
+            $dir.read_callback_file(c_str!($name), v, $callback)
+        })
+    };
+}
+
+fn create_version_files(
+    parent: &Dir,
+    versions: Option<ImageVersions>,
+) -> Result<KVec<Pin<KBox<ImageVersionFiles>>>> {
+    let mut res = KVec::new();
+    if let Some(v) = versions.as_ref() {
+        for (image_name, idx) in IMAGE_NAMES {
+            if let Some(version) = v.0.get(*idx) {
+                res.push(
+                    KBox::pin_init(
+                        ImageVersionFiles::create(parent, image_name, version),
+                        GFP_KERNEL,
+                    )?,
+                    GFP_KERNEL,
+                )?;
+            }
+        }
+    }
+    Ok(res)
+}
+
+impl QcomSocInfoDebugFs {
+    fn create(mut params: Params) -> impl PinInit<Self, Error> {
+        let dir = Dir::new(c_str!("qcom_socinfo_rs_file"));
+        let versions_data = params.versions.take();
+        try_pin_init! {
+            Self {
+                _dir: dir.clone(),
+                info_fmt <- dir.read_callback_file(c_str!("info_fmt"), params.info_fmt, &hex),
+                build_id <- dir.read_callback_file(c_str!("build_id"), params.build_id, &no_quirk),
+                raw_version <- create_optional_file!(dir, "raw_version", params.raw_version),
+                hardware_platform <- create_optional_file!(dir, "hardware_platform",
+                    params.hardware_platform),
+                platform_version <- create_optional_file!(dir, "platform_version",
+                    params.platform_version),
+                accessory_chip <- create_optional_file!(dir, "accessory_chip",
+                    params.accessory_chip),
+                hardware_platform_subtype <- create_optional_file!(dir,
+                    "hardware_platform_subtype", params.hardware_platform_subtype),
+                raw_device_number <- create_optional_file!(dir, "raw_device_number",
+                    params.raw_device_number, &hex),
+                raw_device_family <- create_optional_file!(dir, "raw_device_family",
+                    params.raw_device_family, &hex),
+                chip_family <- create_optional_file!(dir, "chip_family", params.chip_family, &hex),
+                chip_id <- create_optional_file!(dir, "chip_id", params.chip_id, &nul_array),
+                nproduct_id <- create_optional_file!(dir, "nproduct_id", params.nproduct_id),
+                nsubset_parts_array_offset <- create_optional_file!(dir,
+                    "nsubset_parts_array_offset", params.nsubset_parts_array_offset),
+                num_subset_parts <- create_optional_file!(dir, "num_subset_parts",
+                    params.num_subset_parts),
+                ncluster_array_offset <- create_optional_file!(dir, "ncluster_array_offset",
+                    params.ncluster_array_offset),
+                num_clusters <- create_optional_file!(dir, "num_clusters", params.num_clusters),
+                nmodem_supported <- create_optional_file!(dir, "nmodem_supported",
+                    params.nmodem_supported),
+                pcode <- create_optional_file!(dir, "pcode", params.pcode),
+                feature_code <- create_optional_file!(dir, "feature_code", params.feature_code),
+                oem_variant <- create_optional_file!(dir, "oem_variant", params.oem_variant),
+                boot_core <- create_optional_file!(dir, "boot_core", params.boot_core),
+                boot_cluster <- create_optional_file!(dir, "boot_cluster", params.boot_cluster),
+                num_func_clusters <- create_optional_file!(dir, "num_func_clusters",
+                    params.num_func_clusters),
+                foundry_id <- create_optional_file!(dir, "foundry_id", params.foundry_id),
+                pmic_model <- create_optional_file!(dir, "pmic_model", params.pmic_model),
+                pmic_die_rev <- create_optional_file!(dir, "pmic_die_rev", params.pmic_die_rev),
+                pmic_model_array <- create_optional_file!(dir, "pmic_model_array",
+                    params.pmic_model_array),
+                versions: create_version_files(&dir, versions_data)?,
+            } ? Error
+        }
+    }
+}
+
+impl platform::Driver for QcomSocInfo {
+    type IdInfo = ();
+    const OF_ID_TABLE: Option<kernel::of::IdTable<Self::IdInfo>> = None;
+    fn probe(_dev: &Device<Core>, _id_info: Option<&Self::IdInfo>) -> Result<Pin<KBox<Self>>> {
+        let soc_info_mem = qcom_smem_get(
+            kernel::bindings::QCOM_SMEM_HOST_ANY,
+            kernel::bindings::SMEM_HW_SW_BUILD_ID,
+        )?;
+        let version_mem = qcom_smem_get(
+            kernel::bindings::QCOM_SMEM_HOST_ANY,
+            bindings::SMEM_IMAGE_VERSION_TABLE,
+        )?;
+        let info = SocInfo::from_mem(soc_info_mem, version_mem);
+        let params = info.build_params()?;
+        let soc_info = KBox::pin_init(
+            try_pin_init!(
+                    Self {
+                        registration <- soc::DeviceRegistration::register(info.device_attribute()?),
+                        _debugfs <- QcomSocInfoDebugFs::create(params),
+                    } ? Error
+            ),
+            GFP_KERNEL,
+        )?;
+
+        kernel::rand::add_device_randomness(soc_info_mem);
+
+        Ok(soc_info)
+    }
+}
diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h
index afe8be55a6db1d29706c19a91dc51c1ae3494ed4..f22320757e76a77df0e95bdb5bb43afc8cd51616 100644
--- a/rust/bindings/bindings_helper.h
+++ b/rust/bindings/bindings_helper.h
@@ -80,6 +80,12 @@
 #include <linux/xarray.h>
 #include <trace/events/rust_sample.h>
 
+#if defined(CONFIG_QCOM_SOCINFO_RUST)
+#include <dt-bindings/arm/qcom,ids.h>
+#include <linux/soc/qcom/smem.h>
+#include <linux/soc/qcom/socinfo.h>
+#endif
+
 #if defined(CONFIG_DRM_PANIC_SCREEN_QR_CODE)
 // Used by `#[export]` in `drivers/gpu/drm/drm_panic_qr.rs`.
 #include <drm/drm_panic.h>

-- 
2.51.0.rc1.167.g924127e9c0-goog


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ