From nobody Sun Feb 8 02:56:22 2026 Received: from mail-dy1-f201.google.com (mail-dy1-f201.google.com [74.125.82.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8ADEF3BFE43 for ; Tue, 3 Feb 2026 15:46:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770133600; cv=none; b=bnDDp3v4Z4ZY/bIyVYYepjqBT2r0FW8YTIYk14NS7mPZu3ncwLPlRLX0vpX6/1MJSYBmIOVP9x1CYa+RQooS7PysHgALndHkeWfbpBFa/wjHfNSguM6sESrWkrw1PK2JHjwTu3I7nL0FyEWZ7iIcI4ydojVtfV/5E96t1pQklDc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770133600; c=relaxed/simple; bh=toV72FONVd+c77Jdi9/X05RZt7qiox3e/hnCpHZii2E=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=EMJhStlFeiXyu5ADzDIpzL34lWf2oCHwUwiCiqAWz20QYUAUph55aYk0n5ZFV82EQaVasOEwKxN6lZDObaG9SW5UkGo76g8qmkowHrbdicbbx3keMXZGwZQXCCAYgCKnkg8Ff0jVzpHTx69f6KHiqUxb4eveo1Ovx5k4qVU9cKM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--mmaurer.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=ZbFNFk2g; arc=none smtp.client-ip=74.125.82.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--mmaurer.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="ZbFNFk2g" Received: by mail-dy1-f201.google.com with SMTP id 5a478bee46e88-2b7ef896edcso14447382eec.0 for ; Tue, 03 Feb 2026 07:46:38 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1770133597; x=1770738397; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=h/wJPUnQVMCcHAFscBghK0MQ8yiIElHndU1rZLXdeks=; b=ZbFNFk2gSwMTms9IgyqABz1Tfmdd70Jk9hs6D8rXVhNnDQYCX4qhfqmhECBZTceWcR 4f1dESGCKHR3g2cDj9DE/x2reuG4HACMs/B0BeCtkvByHsOJzNmahqr8++Qy2/85I5rB 0G3MnhIW55WPfcfNhuZiTU6KhoKn64Ci3CeRNc8yVzovWg6kdb/gRgrGGp5RY+R28IPn eR0wgZ+vCgRkh6+T14q1HU16VnX7C+78Wao8XP4nNS7vfCtBF3cjZ8aVPc1XW5+AEklt 6nr1Q2aKhTyCyDrRa6UfJJ+9wZ7qDHGHogTjMhd9K8R+6l/jJh6oDh6TqkuE7W5qQgKz 6IEQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770133597; x=1770738397; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=h/wJPUnQVMCcHAFscBghK0MQ8yiIElHndU1rZLXdeks=; b=Cwif1l8py9RVSjZ/c3jNeqiV/azfRGdz6z5nBSlrhnHO2Tz7LKf2JsP8XgmcRCf/HG Uey0f5E6KOnvuHH5RnauseQNliJviKa9nLPdBnxLRlFLjycuZxWnQvFe/+YuoAmf8RNS 1jOBT9mIvOCcKLrwIAdLsA7toSieiR46PODMMIWPpGlvvCSfnS+dTPm+Qb+lHDHqNADh fgjU2WXWCXLv0gWlH0Hw8vmCBOF/Ryy+D06ZcA5AGdnyH7B+1JJSw6TUskOIr+9c3JL5 9q3gRfX8oay8ym3rtTCJQNus+v3eDoqrhFZdtixtcNF3rVX0W6WUw8Eq9KjyiYrZpjPO 0Gyg== X-Forwarded-Encrypted: i=1; AJvYcCWmwOGbQSB/d4EyfKHAwlq0hnB8BIGQRKlHCbsZdJg9FFeY5AVPQD+eN6R8uRoVy88m6HkZONMlm5sG3WY=@vger.kernel.org X-Gm-Message-State: AOJu0YzeLu3lUx+uRY9HBbgxlbODm2hpnYg+jJm8JGArom2ZcPTWWv50 4ZBKkALIjtFcjll1EdTSxf470ozPGxcovQx0CsREBT+KopWJliFsMcL2Oj4sFW3k5ClA2RE3Kdb s7YCWqqYPNg== X-Received: from dybny37.prod.google.com ([2002:a05:7300:e825:b0:2ae:51e3:c162]) (user=mmaurer job=prod-delivery.src-stubby-dispatcher) by 2002:a05:7301:7bc2:b0:2b7:20c6:36dc with SMTP id 5a478bee46e88-2b7c8960b21mr6824371eec.42.1770133597088; Tue, 03 Feb 2026 07:46:37 -0800 (PST) Date: Tue, 03 Feb 2026 15:46:30 +0000 In-Reply-To: <20260203-qcom-socinfo-v2-0-d6719db85637@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260203-qcom-socinfo-v2-0-d6719db85637@google.com> X-Developer-Key: i=mmaurer@google.com; a=ed25519; pk=2Ezhl7+fEjTOMVFpplDeak2AdQ8cjJieLRVJdNzrW+E= X-Developer-Signature: v=1; a=ed25519-sha256; t=1770133593; l=1885; i=mmaurer@google.com; s=20250429; h=from:subject:message-id; bh=toV72FONVd+c77Jdi9/X05RZt7qiox3e/hnCpHZii2E=; b=HmKT9Wjpe5u2hTdJ2Tcoag2Ev49Zm6fhsS7eX/dQiAxY/wxuUniXmJdhtGMd67QiHayfpx34L 0bkddcnyzhZATSmzQBb6PghYphGlfrft9E9n7goPvqOGq6riqINeZyj X-Mailer: b4 0.14.2 Message-ID: <20260203-qcom-socinfo-v2-1-d6719db85637@google.com> Subject: [PATCH v2 1/6] rust: Add sparse_array! helper macro From: Matthew Maurer To: Bjorn Andersson , Konrad Dybcio , Satya Durga Srinivasu Prabhala , Miguel Ojeda , Boqun Feng , Gary Guo , "=?utf-8?q?Bj=C3=B6rn_Roy_Baron?=" , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Daniel Almeida , Greg Kroah-Hartman , "Rafael J. Wysocki" , David Airlie , Simona Vetter , Michal Wilczynski , Dave Ertman , Ira Weiny , Leon Romanovsky Cc: Trilok Soni , linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, rust-for-linux@vger.kernel.org, driver-core@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pwm@vger.kernel.org, Matthew Maurer Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable An idiom in C code is to have an array of nullable values which is partially initialized via `{ [0] =3D x, [7] =3D y}`. Because Rust expects everything to be fully initialized, it does not have this idiom by default. `sparse_array!` allows declaration of `[Option; _]` constants to allow Rust code to more easily mimic the safe version of this pattern. Signed-off-by: Matthew Maurer Co-developed-by: Gary Guo Signed-off-by: Gary Guo --- rust/kernel/slice.rs | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/rust/kernel/slice.rs b/rust/kernel/slice.rs index ca2cde13506196d46c9169aa6e4ab2ac42af6f5b..826b6f77f0d07775bd22837cc17= 73b59ec96936c 100644 --- a/rust/kernel/slice.rs +++ b/rust/kernel/slice.rs @@ -47,3 +47,40 @@ fn as_flattened_mut(&mut self) -> &mut [T] { self.flatten_mut() } } + +/// Create a sparse array of `[Option; _]`. +/// +/// This is intended for use when C code would write `{ [0] =3D x, [7] =3D= y}` to perform partial +/// initialization of an array. +/// +/// # Example +/// ``` +/// use kernel::sparse_array; +/// const FOO: &[Option] =3D &sparse_array! { +/// 0: 10, +/// 7: 16, +/// }; +/// assert_eq!(FOO[0], Some(10)); +/// assert_eq!(FOO[1], None); +/// assert_eq!(FOO[7], Some(16)); +/// ``` +#[macro_export] +macro_rules! sparse_array { + ($( + $index:literal: $value:expr + ),* $(,)?) =3D> {{ + const SIZE: usize =3D { + let mut size =3D 0; + $(if $index >=3D size { + size =3D $index + 1; + })* + size + }; + + const { + let mut arr =3D [None; SIZE]; + $(arr[$index] =3D Some($value);)* + arr + } + }} +} --=20 2.53.0.rc2.204.g2597b5adb4-goog From nobody Sun Feb 8 02:56:22 2026 Received: from mail-dy1-f201.google.com (mail-dy1-f201.google.com [74.125.82.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A2F873BFE46 for ; Tue, 3 Feb 2026 15:46:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770133601; cv=none; b=ABltvYkJeqRZ5I62EMaVIGdicF014iRdczHf1LJr1lZTT98SpeXAFypCi9ttY+WeXLwz7vQHo3IWXwKFLV1oDKu2CtXJNrue9DMFkf0ED6dgchkLlmzSeoiZ5ENaSuFSNbQDW+/DwQF72bfg4uppKlieQ2y4acvPzQeweX3ChSs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770133601; c=relaxed/simple; bh=B6pUx1j5pFgygp5i69R4pVf7HKotofgGAbGCOoefnlg=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=kxh8QaEtuHxqJ/OJT0vVdUL6AmTO2hhC84wpcPvtUkNmdfXfWXvn5T8DvRCsBt7PIM/LIGPSGnVs7iaN2KXNUx7mzcYD/nGlW/4Jw5m6oUH5Ip84jBTWJGmKBBj/4NwQezOnjo3GI1qigm12hM3rziEGnarNWOj5rEBB6DGGB60= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--mmaurer.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=y2uRjLBv; arc=none smtp.client-ip=74.125.82.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--mmaurer.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="y2uRjLBv" Received: by mail-dy1-f201.google.com with SMTP id 5a478bee46e88-2b72b6fc371so11046462eec.0 for ; Tue, 03 Feb 2026 07:46:39 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1770133599; x=1770738399; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=3QkppxUftz38QVidHBNdTmT2F8VCX5EZWUQmqLBEfqQ=; b=y2uRjLBvfn8tU0Fib3HMepDwJoWScAED2Z8NPq3Gb/KgpISVXuSCYzTnz44Ub/2RsT D7U6ytX5exnDF/M5d7XJTOfIWO1jSLzkHCKJ760z/84PHHyNZ/xNXj+hldbCx7CVdEf6 bLTsvzBrKbsN3uczsLy3EEvMn7+YhLgQ2UHG8vcPTfGZWVVHkVqe/5Be3uRQgFo/CWrW 2iPF4pmBY0lK62lO+0QGAOD0CRipFxc7Wfjvd7ScQlgpmL53VrRbgkwa4gbqAiKTnbYY ceIbuvIvnTo/s9H4QcwXhX8bsXOzXT+mjWn1TBzC2aVWXFSNwZXizt4LLuN7ou3SJWMo HNqw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770133599; x=1770738399; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=3QkppxUftz38QVidHBNdTmT2F8VCX5EZWUQmqLBEfqQ=; b=v2urIiiuXxyxXbfsB5nkhD+ICMniWZgZvk1AphIeCHBP8iY6zppgFb0W3AGMpHs1lp ootXGknxSEQUM7vcDlukxZKmHA0tB/4ZuaJpcUTYXdg3JJlyBZbiUkZqBygdhtqI7h32 4e5D4EYD/neCekoz/UkuGJsZLnIYajJV0D8bgEgLGRTkYDkUsYNqkXZWEgi2325pyT46 L216JntfL09f96FR2iAnzR1TnroFvtcqXyiJ5ISP5uApYV8XcimddVys8vNvcnHfT8kR n0YJGwwlh8A+NILzzL+cnMf+xbEu7HdcniaSyOQMk/+RlOM+mQsJb0P1pYwWsgr6Z0J8 csLA== X-Forwarded-Encrypted: i=1; AJvYcCU3nJhF+xEB6sr01NhEs4WgKQpgoR6xfP57BLZ6DL242LPO2aJ+7dKOIw1ZzgFth9Ejg+zmCZi40neM5Bk=@vger.kernel.org X-Gm-Message-State: AOJu0Yx2/LCP7jgHIrrpxoudaLRNyrqpSXAUJQ5St43ZkdVBl7tsrBiQ I/J0V6sy0f3tiwGCHnOFD+WJbcdPuSMHbYO2E4U5p4//yBNDDNiy65WuphCuKZbr/ptbpkugL7Y 7Ax8FyW0EdA== X-Received: from dydb13.prod.google.com ([2002:a05:7300:80cd:b0:2b6:b139:8515]) (user=mmaurer job=prod-delivery.src-stubby-dispatcher) by 2002:a05:7300:c8d:b0:2b7:f415:53da with SMTP id 5a478bee46e88-2b7f41562demr4507487eec.39.1770133598871; Tue, 03 Feb 2026 07:46:38 -0800 (PST) Date: Tue, 03 Feb 2026 15:46:31 +0000 In-Reply-To: <20260203-qcom-socinfo-v2-0-d6719db85637@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260203-qcom-socinfo-v2-0-d6719db85637@google.com> X-Developer-Key: i=mmaurer@google.com; a=ed25519; pk=2Ezhl7+fEjTOMVFpplDeak2AdQ8cjJieLRVJdNzrW+E= X-Developer-Signature: v=1; a=ed25519-sha256; t=1770133593; l=4973; i=mmaurer@google.com; s=20250429; h=from:subject:message-id; bh=B6pUx1j5pFgygp5i69R4pVf7HKotofgGAbGCOoefnlg=; b=fxAPn9jEKutvpJgCWN9uhdCYYPvpNSAPYUiC58vFHXa9srmJAEVvTYAI4ltyhlDhosBAKf3Rg E9oiUBNs6ZcCvvrOXXHz6bHCDz2FOMAAS2YvT7aTHhFBqLoubFyOfDq X-Mailer: b4 0.14.2 Message-ID: <20260203-qcom-socinfo-v2-2-d6719db85637@google.com> Subject: [PATCH v2 2/6] rust: io: Support copying arrays and slices From: Matthew Maurer To: Bjorn Andersson , Konrad Dybcio , Satya Durga Srinivasu Prabhala , Miguel Ojeda , Boqun Feng , Gary Guo , "=?utf-8?q?Bj=C3=B6rn_Roy_Baron?=" , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Daniel Almeida , Greg Kroah-Hartman , "Rafael J. Wysocki" , David Airlie , Simona Vetter , Michal Wilczynski , Dave Ertman , Ira Weiny , Leon Romanovsky Cc: Trilok Soni , linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, rust-for-linux@vger.kernel.org, driver-core@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pwm@vger.kernel.org, Matthew Maurer Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Adds support for doing array copies of data in and out of IO regions. Fixed size arrays allow for compile-time bound checking, while slice arguments allow for dynamically checked copies. Signed-off-by: Matthew Maurer --- rust/kernel/io.rs | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++= +++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/rust/kernel/io.rs b/rust/kernel/io.rs index 056a3ec71647b866a9a4b4c9abe9a0844f126930..6e74245eced2c267ba3b5b744ea= b3bc2db670e71 100644 --- a/rust/kernel/io.rs +++ b/rust/kernel/io.rs @@ -266,8 +266,9 @@ macro_rules! define_write { #[inline] const fn offset_valid(offset: usize, size: usize) -> bool { let type_size =3D core::mem::size_of::(); + let type_align =3D core::mem::align_of::(); if let Some(end) =3D offset.checked_add(type_size) { - end <=3D size && offset % type_size =3D=3D 0 + end <=3D size && offset % type_align =3D=3D 0 } else { false } @@ -323,6 +324,25 @@ fn io_addr(&self, offset: usize) -> Result { self.addr().checked_add(offset).ok_or(EINVAL) } =20 + /// Returns the absolute I/O address for a given `offset`, performing = runtime bounds checks + /// to ensure the entire range is available. + #[inline] + fn io_addr_range(&self, offset: usize, count: usize) -> Result { + if count !=3D 0 { + // These ranges are contiguous, so we can just check the first= and last elements. + let bytes =3D (count - 1) + .checked_mul(core::mem::size_of::()) + .ok_or(EINVAL)?; + let end =3D offset.checked_add(bytes).ok_or(EINVAL)?; + if !offset_valid::(offset, self.maxsize()) || !offset_valid= ::(end, self.maxsize()) + { + return Err(EINVAL); + } + } + + self.addr().checked_add(offset).ok_or(EINVAL) + } + /// Returns the absolute I/O address for a given `offset`, /// performing compile-time bound checks. // Always inline to optimize out error path of `build_assert`. @@ -605,4 +625,54 @@ pub unsafe fn from_raw(raw: &MmioRaw) -> &Self { pub try_write64_relaxed, call_mmio_write(writeq_relaxed) <- u64 ); + + /// Write a known size buffer to an offset known at compile time. + /// + /// Bound checks are performed at compile time, hence if the offset is= not known at compile + /// time, the build will fail, and the buffer size must be statically = known. + #[inline] + pub fn copy_from(&self, src: &[u8; N], offset: usize) { + let addr =3D self.io_addr_assert::<[u8; N]>(offset); + // SAFETY: By the type invariant `addr` is a valid address for MMI= O operations, and by the + // assertion it's valid for `N` bytes. + unsafe { bindings::memcpy_toio(addr as *mut c_void, src.as_ptr().c= ast(), N) } + } + + /// Write the contents of a slice to an offset. + /// + /// Bound checks are performed at runtime and will fail if the offset = (plus the slice size) is + /// out of bounds. + #[inline] + pub fn try_copy_from(&self, src: &[u8], offset: usize) -> Result<()> { + let addr =3D self.io_addr_range::(offset, src.len())?; + // SAFETY: By the type invariant `addr` is a valid address for MMI= O operations, and by the + // range check it's valid for `src.len()` bytes. + unsafe { bindings::memcpy_toio(addr as *mut c_void, src.as_ptr().c= ast(), src.len()) }; + Ok(()) + } + + /// Read a known size buffer from an offset known at compile time. + /// + /// Bound checks are performed at compile time, hence if the offset is= not known at compile + /// time, the build will fail, and the buffer size must be statically = known. + #[inline] + pub fn copy_to(&self, dst: &mut [u8; N], offset: usize= ) { + let addr =3D self.io_addr_assert::<[u8; N]>(offset); + // SAFETY: By the type invariant `addr` is a valid address for MMI= O operations, and by the + // assertion it's valid for `N` bytes. + unsafe { bindings::memcpy_fromio(dst.as_mut_ptr().cast(), addr as = *mut c_void, N) } + } + + /// Read into a slice from an offset. + /// + /// Bound checks are performed at runtime and will fail if the offset = (plus the slice size) is + /// out of bounds. + #[inline] + pub fn try_copy_to(&self, dst: &mut [u8], offset: usize) -> Result<()>= { + let addr =3D self.io_addr_range::(offset, dst.len())?; + // SAFETY: By the type invariant `addr` is a valid address for MMI= O operations, and by the + // range check, it's valid for `dst.len()` bytes. + unsafe { bindings::memcpy_fromio(dst.as_mut_ptr().cast(), addr as = *mut c_void, dst.len()) } + Ok(()) + } } --=20 2.53.0.rc2.204.g2597b5adb4-goog From nobody Sun Feb 8 02:56:22 2026 Received: from mail-dy1-f201.google.com (mail-dy1-f201.google.com [74.125.82.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 61C373AE6FE for ; Tue, 3 Feb 2026 15:46:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770133603; cv=none; b=pijY2K7M9Rxjh1NHCkY1xxy9mvHVn0pOXZG3UQA+5IUxNzl1mJ5nkFf+N3FtTXWKYLBsj4jSDbwsAH/DMojcYLx6tTGPQOuq0fHo2UKlcIv7ZhEj0gnb74E4ahLldASqQdl3wSL9p3Iz5sXfsRcZ8AGyeJlz1cfsxwdYnVsHsto= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770133603; c=relaxed/simple; bh=RwCJ/xEwqbjligRdRo7donBAUlsdrVxdbuTW9DJLV3g=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=n2Idcy9UrPGPpd0cgUDwTkqqI5OUG2SUdA7YhEmIw2vsiKacKgUEDam4DvxRxGddla8Sdm6Ltxb2/Oj48CkLbQZyyo2cyAVVlSWTprzx/9f6DU3Qt0O3N/2tuliFTkLfXSbgfTMjdxTr39eVHqNuKoiIWouCIFnNdHreK0dgoSo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--mmaurer.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=QWWpbDi+; arc=none smtp.client-ip=74.125.82.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--mmaurer.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="QWWpbDi+" Received: by mail-dy1-f201.google.com with SMTP id 5a478bee46e88-2b72b6fc371so11046825eec.0 for ; Tue, 03 Feb 2026 07:46:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1770133600; x=1770738400; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=KdXVf1jtiVVdnaqb+rLnoB8/QmUjcxzniTwKjo2bXrU=; b=QWWpbDi+07DEGZt/vbKJ4gHNZQvQ9xKkTh6732LHW4Pw7iLWmQPaPw40lm/jK1iXFv RsaY+EyR9ugT8iRjNWYsQIz1WYyFkALVnbRps2rNI4MePXVn+R3HTfn0sd47SAYRESmm VdM68Uzak3YXOm3T1MiTs9pny8iOXHAQNiiR7Bh2L17xpL4bISRbqjE8xe8bNPD/bimA q/3aMkFxtIKqOqH49AuO4K/nB7Hwzc7iyMgpG40QINdvujP6h3q2gDd1SxJ0DR4OehQW YlWFgqYRM8NgxMibh9YHCkNx1FQ84lHH14/keobHJFY1ilaYorqUT27KXV8kqoFJVS7N W85A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770133600; x=1770738400; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=KdXVf1jtiVVdnaqb+rLnoB8/QmUjcxzniTwKjo2bXrU=; b=HP0oGkEo8OU2gThmN01DtZtsnAffVdnIZic9RtEv8z6d8HAnj2Ch1JvbG2g3OySEdH 2YhZw1/tKBwYW3B7YNiO4bmuWHAfvxn1IfG9NHyKGaDf8AvnR/gKpDHpoPyQTC60g25B fVR45xOQq6IjbseedTegCdEj1w2zpt2cGggfysb6oSH6qt8Arp54YVWGfKE7gTbeBG7X mO81Gnjba+xY/eiJ93J2bIpi/EAu9jq45ViYN+RIC57a/CzHC8zTHcYcsKW6z7OjyG0A xRrKH5tmSQigSy4ECCuERjPlqYRYsyGWiXJl6Y53bfUvc/oHpecitX8DIGyzOCI6adWU 8cVg== X-Forwarded-Encrypted: i=1; AJvYcCVJrK8t9VAVSOW/x0pGNB2PO1FamBzDRhVzq+m86key4tQRHH1we0693XxgMh1RwCj0bgLjfXnoIRYQ5nI=@vger.kernel.org X-Gm-Message-State: AOJu0YzsbyK8qZIx3dLc+YZOXtOJvjAoP/q6aUHsxliWQHVVf3Jn1jV/ 8N6/F7TBY57n71Hd8hydcKpTw+BjrP0VlgNz6I/3fBaLvhCXmEQsL/++SKYHPEu3sQhlMDimPQh zKPCK242UrQ== X-Received: from dycrt20.prod.google.com ([2002:a05:693c:2d94:b0:2b6:c6a7:636a]) (user=mmaurer job=prod-delivery.src-stubby-dispatcher) by 2002:a05:693c:3002:b0:2b6:c617:f795 with SMTP id 5a478bee46e88-2b7c86663c1mr7418033eec.17.1770133600442; Tue, 03 Feb 2026 07:46:40 -0800 (PST) Date: Tue, 03 Feb 2026 15:46:32 +0000 In-Reply-To: <20260203-qcom-socinfo-v2-0-d6719db85637@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260203-qcom-socinfo-v2-0-d6719db85637@google.com> X-Developer-Key: i=mmaurer@google.com; a=ed25519; pk=2Ezhl7+fEjTOMVFpplDeak2AdQ8cjJieLRVJdNzrW+E= X-Developer-Signature: v=1; a=ed25519-sha256; t=1770133593; l=2963; i=mmaurer@google.com; s=20250429; h=from:subject:message-id; bh=RwCJ/xEwqbjligRdRo7donBAUlsdrVxdbuTW9DJLV3g=; b=SQdCmaIOesp2nNqbcmI1qfM3G5NEMlAiTI7JoMUcwHSNW8vyq+fqK1lL17+OwnTzARN5rGU+z 9PyU4DL3NSyDmB3rGdnOpkIMgMGTW/9HGTk/h/gqJgPbPfyQrUyBmYk X-Mailer: b4 0.14.2 Message-ID: <20260203-qcom-socinfo-v2-3-d6719db85637@google.com> Subject: [PATCH v2 3/6] rust: device: Support testing devices for equality From: Matthew Maurer To: Bjorn Andersson , Konrad Dybcio , Satya Durga Srinivasu Prabhala , Miguel Ojeda , Boqun Feng , Gary Guo , "=?utf-8?q?Bj=C3=B6rn_Roy_Baron?=" , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Daniel Almeida , Greg Kroah-Hartman , "Rafael J. Wysocki" , David Airlie , Simona Vetter , Michal Wilczynski , Dave Ertman , Ira Weiny , Leon Romanovsky Cc: Trilok Soni , linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, rust-for-linux@vger.kernel.org, driver-core@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pwm@vger.kernel.org, Matthew Maurer Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable This allows device drivers to check if, for example, an auxiliary devices is one of its children by comparing the parent field, or checking if a device parameter is its own device. Also convert existing `.as_raw() !=3D .as_raw()` to use this new implementation. Signed-off-by: Matthew Maurer Acked-by: Danilo Krummrich Reviewed-by: Gary Guo --- rust/kernel/device.rs | 8 ++++++++ rust/kernel/devres.rs | 2 +- rust/kernel/drm/driver.rs | 2 +- rust/kernel/pwm.rs | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/rust/kernel/device.rs b/rust/kernel/device.rs index 94e0548e76871d8b7de309c1f1c7b77bb49738ed..aa10359d3ebdd1c99cc567a35b8= 9f52ddb2ee050 100644 --- a/rust/kernel/device.rs +++ b/rust/kernel/device.rs @@ -516,6 +516,14 @@ unsafe impl Send for Device {} // synchronization in `struct device`. unsafe impl Sync for Device {} =20 +impl PartialEq> for = Device { + fn eq(&self, other: &Device) -> bool { + self.as_raw() =3D=3D other.as_raw() + } +} + +impl Eq for Device {} + /// Marker trait for the context or scope of a bus specific device. /// /// [`DeviceContext`] is a marker trait for types representing the context= of a bus specific diff --git a/rust/kernel/devres.rs b/rust/kernel/devres.rs index cdc49677022a6b466e771d9d8cf3818ab9b9112d..20126daad193370868661b94129= 37937eda6d3c4 100644 --- a/rust/kernel/devres.rs +++ b/rust/kernel/devres.rs @@ -281,7 +281,7 @@ pub fn device(&self) -> &Device { /// } /// ``` pub fn access<'a>(&'a self, dev: &'a Device) -> Result<&'a T> { - if self.dev.as_raw() !=3D dev.as_raw() { + if self.dev.as_ref() !=3D dev { return Err(EINVAL); } =20 diff --git a/rust/kernel/drm/driver.rs b/rust/kernel/drm/driver.rs index f30ee4c6245cda72ac72852bf9362736d8fe992f..497ef46028d560bc9649dbbdf69= 316ce4fce8199 100644 --- a/rust/kernel/drm/driver.rs +++ b/rust/kernel/drm/driver.rs @@ -139,7 +139,7 @@ pub fn new_foreign_owned( where T: 'static, { - if drm.as_ref().as_raw() !=3D dev.as_raw() { + if drm.as_ref() !=3D dev { return Err(EINVAL); } =20 diff --git a/rust/kernel/pwm.rs b/rust/kernel/pwm.rs index cb00f8a8765c8ec58ed78a73275b022b02bf7aa3..033f778909a2633acbc25d5a21a= 1c8a7b8e41a70 100644 --- a/rust/kernel/pwm.rs +++ b/rust/kernel/pwm.rs @@ -680,7 +680,7 @@ impl Registration= { /// calling `pwmchip_remove`. This function should be called from the = driver's `probe`. pub fn register(dev: &device::Device, chip: ARef>) -> R= esult { let chip_parent =3D chip.device().parent().ok_or(EINVAL)?; - if dev.as_raw() !=3D chip_parent.as_raw() { + if dev !=3D chip_parent { return Err(EINVAL); } =20 --=20 2.53.0.rc2.204.g2597b5adb4-goog From nobody Sun Feb 8 02:56:22 2026 Received: from mail-dy1-f202.google.com (mail-dy1-f202.google.com [74.125.82.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E05753BFE42 for ; Tue, 3 Feb 2026 15:46:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770133605; cv=none; b=Py0InDxs/3sjhFxZft8PS21Z2Xm2TfN3psYW1Pk/q8IR4OTd/tHl9Hx8aGnXhSCXnWUjhM9LYxub7RCF1nHBgi2Xw56KwUG4uUc7Fa7iA4hVivx6HRZRQRGd5/bGfVCwIpWG8XJCDQXKQp2zYgXT6B2I54CVh7qOFJjVCedB0No= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770133605; c=relaxed/simple; bh=sLbxFTX2mTYV2vSHOwak0YCZYcQva6hVw82FQCeYKlk=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=oSGgwmzn+TAquK8jG100JWyF7yXXaf6+bUamVmP8NZo4BJYJtMOJF8BO+h7h0v1UAbLAnj0WezqcBsyeNOkj7jSjFXlEEYIf5VRHicaeKh4gfJxNPu5ethdNPBAaAEx8htCEE3N+pUJeYTuWi5NUY5l5HW1F2NLIf8AxG8JATJ8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--mmaurer.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=o47zouml; arc=none smtp.client-ip=74.125.82.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--mmaurer.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="o47zouml" Received: by mail-dy1-f202.google.com with SMTP id 5a478bee46e88-2b795cff830so18085154eec.1 for ; Tue, 03 Feb 2026 07:46:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1770133602; x=1770738402; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=yriD2nT/Os7MHztKIgeqU92FBaPsLQ1akZyLJCP9KTY=; b=o47zoumlJdrRlPy6ZNnwUnLc/OELYrP8hjk4+NsdIelT0dGOyfVWUtWoByfnCo+ubt U6Nvufmiict84IsqfV/SmComuIvgXZu/ywEpnNzbL8RyThvn3LgaK5sgfV3cVSyl/B6k jbPXn/q8cMFIC+8bQMQ6AWijqDRKi6bIekaJxx1JzexituXxJ+lISMQDNKPFhwPuA9UY cnwKY5ZtsQCukha4vODVvtUiYDsCSJBmK0Iz/eyPOkBjsHEec96kfOT3rLMfhUTk3+M7 3V0zMVa28w+kNPLgRBpS3oPHUbyUrAqKK/IUAPN6zhino3tzd6q3famHirNjIWgDKxnz CIXw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770133602; x=1770738402; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=yriD2nT/Os7MHztKIgeqU92FBaPsLQ1akZyLJCP9KTY=; b=u9R11rqlMBVElCqWvrlom+H0D+WNniHrN0najguAmZPbAl2ZhtEtDuWNlqTs6LmJOg cPb3J/YLey5v3BuU22coPWT7Qc6PiNAITOI78ALpDdZXCGBh5cgSEuSTotUO+ELRGOOs jrey5hX0uMW61r7SpVqVh3EPyMBmWWpD1xMWVzxveAY/xN5Yw9pTyoXTFx/FdigKHmrc yKn8BRGL+457qWH+hOzG8e9dRqEvIaMdvY1aFc3gML4ZzFK+SnS3C74wPDJUVG4BGvES 96nqrBOWkyLd/8xvO0uJb66uGJNWeEb2P4HVjwIHYYy0gW/BF86fEm8PQkbuWdrPF9ev 3Mzg== X-Forwarded-Encrypted: i=1; AJvYcCVwqiomZcEIWqI6DWhiu/bhVwazKfwI/NUF2SyW02U44p/WyMBVO/SQlBYwkCuIRTg7T0lajsg2vJD48r0=@vger.kernel.org X-Gm-Message-State: AOJu0YwiM2RVzpS+GtrlFibWjLzept1/j9dCc5oToa3d2weDGkODFr9x mU8Tt36Lcpzy1KJ26kyT67jwqeapQEnmZITO+z1P2eLLm9gPsjOeZoDM8ruLE2vhDaeZxcyy+qk xhvAJs3QifQ== X-Received: from dybhk18.prod.google.com ([2002:a05:7301:2892:b0:2b7:d91:b4a2]) (user=mmaurer job=prod-delivery.src-stubby-dispatcher) by 2002:a05:7300:7491:b0:2b7:f28d:c8c1 with SMTP id 5a478bee46e88-2b8327328c7mr4126eec.0.1770133601984; Tue, 03 Feb 2026 07:46:41 -0800 (PST) Date: Tue, 03 Feb 2026 15:46:33 +0000 In-Reply-To: <20260203-qcom-socinfo-v2-0-d6719db85637@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260203-qcom-socinfo-v2-0-d6719db85637@google.com> X-Developer-Key: i=mmaurer@google.com; a=ed25519; pk=2Ezhl7+fEjTOMVFpplDeak2AdQ8cjJieLRVJdNzrW+E= X-Developer-Signature: v=1; a=ed25519-sha256; t=1770133593; l=1096; i=mmaurer@google.com; s=20250429; h=from:subject:message-id; bh=sLbxFTX2mTYV2vSHOwak0YCZYcQva6hVw82FQCeYKlk=; b=lrUfeO8BzxGoH2q0cLzXZitIHc5mxhrmhIP1EvIGlTolROpSubzosdu4ukDgERhXMbVdgqt6B hy4MuPfZ3YMDwryq+n6Z7b1/52uJBUTXJBD7xC/OlPQKkhC26hmI+cu X-Mailer: b4 0.14.2 Message-ID: <20260203-qcom-socinfo-v2-4-d6719db85637@google.com> Subject: [PATCH v2 4/6] rust: auxiliary: Support accessing raw aux pointer From: Matthew Maurer To: Bjorn Andersson , Konrad Dybcio , Satya Durga Srinivasu Prabhala , Miguel Ojeda , Boqun Feng , Gary Guo , "=?utf-8?q?Bj=C3=B6rn_Roy_Baron?=" , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Daniel Almeida , Greg Kroah-Hartman , "Rafael J. Wysocki" , David Airlie , Simona Vetter , Michal Wilczynski , Dave Ertman , Ira Weiny , Leon Romanovsky Cc: Trilok Soni , linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, rust-for-linux@vger.kernel.org, driver-core@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pwm@vger.kernel.org, Matthew Maurer Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable While it's preferable to add bindings in the kernel crate rather than using raw pointers where possible, access to the raw aux pointer is required to pass it to C interfaces provided by a driver. Signed-off-by: Matthew Maurer --- rust/kernel/auxiliary.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/rust/kernel/auxiliary.rs b/rust/kernel/auxiliary.rs index 93c0db1f66555c97ec7dc58825e97c47c0154e54..1a88277f0fd9ea5ff32cc534dfe= 5682009de94c2 100644 --- a/rust/kernel/auxiliary.rs +++ b/rust/kernel/auxiliary.rs @@ -237,7 +237,11 @@ pub struct Device( ); =20 impl Device { - fn as_raw(&self) -> *mut bindings::auxiliary_device { + /// Returns the underlying auxiliary device + /// + /// Prefer to add bindings in the kernel crate for any use other than = calling driver-specific + /// functions. + pub fn as_raw(&self) -> *mut bindings::auxiliary_device { self.0.get() } =20 --=20 2.53.0.rc2.204.g2597b5adb4-goog From nobody Sun Feb 8 02:56:22 2026 Received: from mail-dy1-f202.google.com (mail-dy1-f202.google.com [74.125.82.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 288103BFE3C for ; Tue, 3 Feb 2026 15:46:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770133609; cv=none; b=RMxHGp0rlHn7L0/yBhFproLp9jaBqsCOjLSSLEcsFb4jiVsuIWpIN37Zy+wda+vtNan4SJK8sulcmyZv4G5d2SMz4i8EGXudafq7L94fXi2+U71+vi5VV7m1RADIRbkCRKZfhjRiWYcZnbuTPjYPCe4oqrh64Tr4wm/5Oce7p3E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770133609; c=relaxed/simple; bh=WtZdKvjX12D2Jmn1kMkn/+vs+NvlqXqrgcd1O83Ixd4=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=TV3IJfpk6bVetBqrH+02k8WAoJ3pdytjQrwsV3yvsvuRLwu/6JRHkIwsOovo/sDF7cYg9B6OuwcOmUqdVbfSJ3cagv8vh38q/n6e/pO9jCCMCbnfT5VfBXf+7lN4fYYjVpICv9pQ9/BNUHtv5S/ITyrc/KdVO9woF5YxtsKlx6w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--mmaurer.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=JMhDliBQ; arc=none smtp.client-ip=74.125.82.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--mmaurer.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="JMhDliBQ" Received: by mail-dy1-f202.google.com with SMTP id 5a478bee46e88-2b71d3ac508so5518403eec.0 for ; Tue, 03 Feb 2026 07:46:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1770133604; x=1770738404; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=Wdhof5UcFa0LauNDEG7A5hw9JfGF2S2FIbHiIBJlkVI=; b=JMhDliBQdB401m4c4C0KNuAymBVfVm7HIC3RuXQTEm/8bbPFzsTTksVSBFYkqmOyas TXkhkwlbVMspSvdCp5nC0BM718ZtxV7B48osVyq9e1zAuefYTAuJogGA5DHYFgwoxQ6w xcMWnRMmRdSShoDOXPoQLtJ+C+H2dnQr6FndrE1wF7Ql7lTZ/kYzmsVGqNdTLUxlo0Ja a7QdvpZKPZnEUyFzXIvct+1HAHp+4atlbE5lFJJbF2SIgOCQ4MS5BAqTvbO1Q8VxgH4z u4EbCQjPrPxXbgmM+oVuRXGuHU84jceziqxUbHg2fIGaFLSa0+mB+oiPSypwmS2vmRCU MKmA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770133604; x=1770738404; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=Wdhof5UcFa0LauNDEG7A5hw9JfGF2S2FIbHiIBJlkVI=; b=h/6gaAYBzXMCLojhcAymgZUsFhbTgBrnJmXUFRGXXjkfNeYk3l2tX6n2ymPULntZBY cz+tb2Mdh/M2HcOAG1l3iQOB9veJ3cK6D3DmxQjt806DhQ2W5qo8/T6lZaZvPXQ8NZJM licEvyktkcGrO+lS24VV+f0kTjutXwoJg453yOWN1SmDpXYnxPTAYYdQonCOh9S19lNj i5sr5gUGQzpybidTa4b2zaEKOeJiOHg+uNe8iRtu9+2OMuHu3Dg1praGb0MSeD7OQOm9 ERsLBsjbTlyXXi8AGDFmV1SZcH9UBrt55YDn0hb6T9tZ1W1dDLHkq6X/9IQxLI+BPx8o 6RpQ== X-Forwarded-Encrypted: i=1; AJvYcCVaTNvQgcd8WTAjLbSQWlrt/KJFHTG/vz9jquctdx2G0rX37yjnxNxGJ5cJZoJis+a7nJfqVThctyKJ83M=@vger.kernel.org X-Gm-Message-State: AOJu0Yy6Y1mVUIcs1TI6+jCAIDBH72ZVhRtvr72AYr3txTvlEpAHzqir 9Yj4XjNba+JAuJ3WQbiX6D+Vh6m5OAD3wAdfyW0fIca9Qj6kZxUVjhMJoqsc34fvtCUbVQOXn4G MLy6JMmaX4w== X-Received: from dlcip4.prod.google.com ([2002:a05:7023:c084:b0:124:a6e8:e9eb]) (user=mmaurer job=prod-delivery.src-stubby-dispatcher) by 2002:a05:7022:6281:b0:11b:9386:8271 with SMTP id a92af1059eb24-125c10081bamr8120436c88.46.1770133603693; Tue, 03 Feb 2026 07:46:43 -0800 (PST) Date: Tue, 03 Feb 2026 15:46:34 +0000 In-Reply-To: <20260203-qcom-socinfo-v2-0-d6719db85637@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260203-qcom-socinfo-v2-0-d6719db85637@google.com> X-Developer-Key: i=mmaurer@google.com; a=ed25519; pk=2Ezhl7+fEjTOMVFpplDeak2AdQ8cjJieLRVJdNzrW+E= X-Developer-Signature: v=1; a=ed25519-sha256; t=1770133593; l=2442; i=mmaurer@google.com; s=20250429; h=from:subject:message-id; bh=WtZdKvjX12D2Jmn1kMkn/+vs+NvlqXqrgcd1O83Ixd4=; b=y1zunl2p/I9o6cmWUb2NnYfAPstnO8iv9BQaW1CxpWleUmklNBei8N2Of6dN4lKwNKIrkORJy w7+q2IWbzENDidaJ41cve7e/37dXsY/YHczM8JnE76IbaJ4tUPyi7qM X-Mailer: b4 0.14.2 Message-ID: <20260203-qcom-socinfo-v2-5-d6719db85637@google.com> Subject: [PATCH v2 5/6] rust: debugfs: Allow access to device in Devres-wrapped scopes From: Matthew Maurer To: Bjorn Andersson , Konrad Dybcio , Satya Durga Srinivasu Prabhala , Miguel Ojeda , Boqun Feng , Gary Guo , "=?utf-8?q?Bj=C3=B6rn_Roy_Baron?=" , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Daniel Almeida , Greg Kroah-Hartman , "Rafael J. Wysocki" , David Airlie , Simona Vetter , Michal Wilczynski , Dave Ertman , Ira Weiny , Leon Romanovsky Cc: Trilok Soni , linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, rust-for-linux@vger.kernel.org, driver-core@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pwm@vger.kernel.org, Matthew Maurer Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable This adds support for creating a DebugFS directory which is aware that it is bound to a device. As a result, callbacks under that directory have access to a bound device which gives them efficient access to other Devres, ability to use dev_err! and friends, etc. Signed-off-by: Matthew Maurer Acked-by: Danilo Krummrich Suggested-by: Danilo Krummrich --- rust/kernel/debugfs.rs | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/rust/kernel/debugfs.rs b/rust/kernel/debugfs.rs index d7b8014a6474698235203f2b7d8fec96f2bb43f8..ac614d693fa73929d095b669e9b= a61958bec609e 100644 --- a/rust/kernel/debugfs.rs +++ b/rust/kernel/debugfs.rs @@ -11,6 +11,11 @@ #[cfg(CONFIG_DEBUG_FS)] use crate::sync::Arc; use crate::{ + device::{ + Bound, + Device, // + }, + devres::Devres, fmt, prelude::*, str::CStr, @@ -722,3 +727,38 @@ fn new(name: &CStr) -> ScopedDir<'data, 'static> { } } } + +impl<'a, T: 'a + Send> Devres> { + /// Creates a new scope, which is a directory at the root of the debug= fs filesystem, + /// associated with some data `T`, enclosed in a [`Devres`] for the pr= ovided device. + /// + /// The `init` closure is called to populate the directory with files = and subdirectories. These + /// files can reference the data stored in the scope. Because it is st= ored inside a `Devres`, + /// the init method is granted access to a `&Device`. + /// + /// This can be used for cheaply accessing device-protected data insid= e DebugFS methods or + /// accessing device-specific methods (e.g. [`dev_err!`]). + /// + /// The entire directory tree created within the scope will be removed= when the returned + /// `Scope` handle is dropped. + pub fn dir( + dev: &'a Device, + data: impl PinInit + 'a, + name: &'a CStr, + init: F, + ) -> impl PinInit + 'a + where + F: for<'data, 'dir> FnOnce(&'data T, &'data Device, &'dir S= copedDir<'data, 'dir>) + + 'a, + Error: From, + { + Devres::new( + dev, + Scope::new(data, |data| { + let scoped =3D ScopedDir::new(name); + init(data, dev, &scoped); + scoped.into_entry() + }), + ) + } +} --=20 2.53.0.rc2.204.g2597b5adb4-goog From nobody Sun Feb 8 02:56:22 2026 Received: from mail-dy1-f201.google.com (mail-dy1-f201.google.com [74.125.82.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AA5DE3BFE44 for ; Tue, 3 Feb 2026 15:46:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770133614; cv=none; b=b354cODvnXmYk8SCvQOb8bLLqW9FVHepIMqSsgRyr6KdQwruMliHdCGBsjYMvH64t+k62zdu2J5tl081x4Wy+QFnap/Q/RT66AGcO4ACG+2m9OnntATeBO2fdTC/n4McXLcbaDlVgT1HcH8ArnCNioG3+ayg+0of9prvrsyhEiM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770133614; c=relaxed/simple; bh=tpkxutsskHxPVxS/OMjEWZr4mFHsomHylGbKna6UNf8=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=Nl+uUmyZWCPvF1iOGF7PnrSXUDS9kdO4aQ+er0K1XwNrJB4MQwAZHT58aOY58zccw3ASV9hwUjz/hZiBPkKY8yC7gWyUeelJgGcnpoVkDiuJMqDd9O8OKcYTfFk1fnmcgNjgwWDbzHm5GPqFpxjzPJvXxGh1/3PesqEwebGA574= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--mmaurer.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=J/DeQaxe; arc=none smtp.client-ip=74.125.82.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--mmaurer.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="J/DeQaxe" Received: by mail-dy1-f201.google.com with SMTP id 5a478bee46e88-2b6b9c1249fso8660393eec.1 for ; Tue, 03 Feb 2026 07:46:46 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1770133605; x=1770738405; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=5nsWBVPQvmR7GWncR53fb87wMVZ+bXZsmZ3b67gn7JA=; b=J/DeQaxeDFz6MPkxlc3GnfumWmD//bszUDWc0nLfgxK8npAAgeCQ9MCwSgkTyuWPnG ZvcPX/UC1YQZpeSKJX02DGM0f3/yzIBTVj0zqhU0ETjafQSijsamjPKhij2X4uIP27g3 XMPBfsHhrkDaZRSm5zI65gjpgMkbpXC2cr62KdNP8L0bLntO08Cr4LAEfucnbfsv1st0 +UcCJZI6Mgpk6odtMY/ZYBbgn9b4LlExIxbbYU/e8Pnd2eUGUJusArwrzThp7EKIlsVF sOh6t4j71RQSespHe16eMDPSIVjUe0mVfncQAwbjJCtI/spBxK19dzRT2nANvhRjAZo+ F4nQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770133605; x=1770738405; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=5nsWBVPQvmR7GWncR53fb87wMVZ+bXZsmZ3b67gn7JA=; b=xOUD3gGa78XjVZspMwYQCQ6vuh2x4o250cvCthad7ynWC00r8czW9grgCG+5isr9vv o6InMKPvjyVtWIE5jk3WDoP3SqNyoebSxy3x032fiGvSlTt1WtUzWd05yk0hCgsY0pP6 010qaaOWXFPwH0bKy+sEZytaIVcU84OchyJfK4dmsFY0evBAA7zFVF/tqL202LK3yC7x PCQhP4vcDVkiA8OVty4GVsLb/PmyeMPEVpZKnlysdiij5wlspc8EgxfzhshbGnUu9C+1 9RRAD4Zru6BAh8aY6SVZPSd3ZVZ6w8+l7cFaOmhuETG9mafNvZYupqyAlNuRgmr+3aen QYww== X-Forwarded-Encrypted: i=1; AJvYcCXbHuptbv2EObC8kJY3sBXeocJDXgxNIHnsuSlVp5vYMLSqPp3sQ9Qm6nul9j3foRGsGY0xsOzIjqwitXc=@vger.kernel.org X-Gm-Message-State: AOJu0YwprAJ2Q+XnIDcOFcgL/QvvGSTmt1rVmuVnogxo67ynEo92/bi7 Tn9F2w9kjSDlLVwIC/DzcCn3YWDgFpUtXzivObRy+3toS8rla3kY2m6DSSbTJgAeC2Hde20WbUC J/RB/nY3Ekg== X-Received: from dycnm10.prod.google.com ([2002:a05:7300:d18a:b0:2b8:1ff8:292f]) (user=mmaurer job=prod-delivery.src-stubby-dispatcher) by 2002:a05:7300:ed0d:b0:2ae:55f0:f2be with SMTP id 5a478bee46e88-2b7c88eaa7amr8617987eec.31.1770133605342; Tue, 03 Feb 2026 07:46:45 -0800 (PST) Date: Tue, 03 Feb 2026 15:46:35 +0000 In-Reply-To: <20260203-qcom-socinfo-v2-0-d6719db85637@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260203-qcom-socinfo-v2-0-d6719db85637@google.com> X-Developer-Key: i=mmaurer@google.com; a=ed25519; pk=2Ezhl7+fEjTOMVFpplDeak2AdQ8cjJieLRVJdNzrW+E= X-Developer-Signature: v=1; a=ed25519-sha256; t=1770133593; l=65293; i=mmaurer@google.com; s=20250429; h=from:subject:message-id; bh=tpkxutsskHxPVxS/OMjEWZr4mFHsomHylGbKna6UNf8=; b=/qIdKOrWZl0pksxB94j31YjJA+qeONPlUeCbwUZqaRutMf3EcIbmC1jjdq2uByBH2zi88NnNe e3tuWwiXDdUDtw4V0Bl2mwj6Qe75CYORC+RxJ9547LyNVjpAjAuGrE/ X-Mailer: b4 0.14.2 Message-ID: <20260203-qcom-socinfo-v2-6-d6719db85637@google.com> Subject: [PATCH v2 6/6] soc: qcom: socinfo: Convert to Rust From: Matthew Maurer To: Bjorn Andersson , Konrad Dybcio , Satya Durga Srinivasu Prabhala , Miguel Ojeda , Boqun Feng , Gary Guo , "=?utf-8?q?Bj=C3=B6rn_Roy_Baron?=" , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Daniel Almeida , Greg Kroah-Hartman , "Rafael J. Wysocki" , David Airlie , Simona Vetter , Michal Wilczynski , Dave Ertman , Ira Weiny , Leon Romanovsky Cc: Trilok Soni , linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, rust-for-linux@vger.kernel.org, driver-core@lists.linux.dev, dri-devel@lists.freedesktop.org, linux-pwm@vger.kernel.org, Matthew Maurer Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Convert the socinfo driver to Rust for a number of improvements: * Accessing IO mapped regions through the IO subsystem, rather than through regular memory accesses. * Binds the device as an auxiliary device rather than a platform device, ensuring the mapped IO regions cannot be accessed after the smem device is removed. * Adds bounds-checking to all accesses, hardening against a repeat of CVE-2024-58007 Signed-off-by: Matthew Maurer --- drivers/soc/qcom/Kconfig | 1 + drivers/soc/qcom/Makefile | 2 +- drivers/soc/qcom/smem.c | 42 +- drivers/soc/qcom/socinfo.c | 931 -------------------------------= ---- drivers/soc/qcom/socinfo/Makefile | 2 + drivers/soc/qcom/socinfo/bindings.rs | 123 +++++ drivers/soc/qcom/socinfo/data.rs | 438 ++++++++++++++++ drivers/soc/qcom/socinfo/socinfo.rs | 446 +++++++++++++++++ include/linux/soc/qcom/smem.h | 4 + rust/bindgen_parameters | 1 + rust/bindings/bindings_helper.h | 6 + 11 files changed, 1056 insertions(+), 940 deletions(-) diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 2caadbbcf8307ff94f5afbdd1481e5e5e291749f..16d553f66f0cf1101d3a8c7d401= d7c4d6a65dac7 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -222,6 +222,7 @@ config QCOM_SMSM config QCOM_SOCINFO tristate "Qualcomm socinfo driver" depends on QCOM_SMEM + depends on RUST select SOC_BUS help Say yes here to support the Qualcomm socinfo driver, providing diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index b7f1d2a5736748b8772c090fd24462fa91f321c6..6f6688c76a00a91ce99600f298a= 8e6e0fefed806 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -28,7 +28,7 @@ obj-$(CONFIG_QCOM_SMEM_STATE) +=3D smem_state.o CFLAGS_smp2p.o :=3D -I$(src) obj-$(CONFIG_QCOM_SMP2P) +=3D smp2p.o obj-$(CONFIG_QCOM_SMSM) +=3D smsm.o -obj-$(CONFIG_QCOM_SOCINFO) +=3D socinfo.o +obj-$(CONFIG_QCOM_SOCINFO) +=3D socinfo/ obj-$(CONFIG_QCOM_SPM) +=3D spm.o obj-$(CONFIG_QCOM_STATS) +=3D qcom_stats.o obj-$(CONFIG_QCOM_WCNSS_CTRL) +=3D wcnss_ctrl.o diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c index fef840b5457407a85051ded0e835430dbebfe8bb..dcea2d7f37067b0b6f801b3d2b4= 57422ad9f342c 100644 --- a/drivers/soc/qcom/smem.c +++ b/drivers/soc/qcom/smem.c @@ -4,6 +4,7 @@ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. */ =20 +#include #include #include #include @@ -279,7 +280,6 @@ struct qcom_smem { struct hwspinlock *hwlock; =20 u32 item_count; - struct platform_device *socinfo; struct smem_ptable *ptable; struct smem_partition global_partition; struct smem_partition partitions[SMEM_HOST_COUNT]; @@ -675,6 +675,32 @@ static void *qcom_smem_get_private(struct qcom_smem *s= mem, return ERR_PTR(-EINVAL); } =20 +/** + * qcom_smem_get_aux() - resolve ptr of size of a smem item + * @aux: an aux device that should be our child + * @host: the remote processor, or -1 + * @item: smem item handle + * @size: pointer to be filled out with size of the item + * + * Looks up smem item and returns pointer to it. Size of smem + * item is returned in @size. + * + * The caller may take the loaded state of the provided aux device as + * an acceptable proxy for this memory being valid. + * + * Return: a pointer to an SMEM item on success, ERR_PTR() on failure. + */ +void *qcom_smem_get_aux(struct auxiliary_device *aux, unsigned int host, + unsigned int item, size_t *size) +{ + if (IS_ERR(__smem)) + return __smem; + if (aux->dev.parent !=3D __smem->dev) + return ERR_PTR(-EINVAL); + return qcom_smem_get(host, item, size); +} +EXPORT_SYMBOL_GPL(qcom_smem_get_aux); + /** * qcom_smem_get() - resolve ptr of size of a smem item * @host: the remote processor, or -1 @@ -684,6 +710,9 @@ static void *qcom_smem_get_private(struct qcom_smem *sm= em, * Looks up smem item and returns pointer to it. Size of smem * item is returned in @size. * + * It is up to the caller to ensure that the qcom_smem device remains + * loaded by some mechanism when accessing returned memory. + * * Return: a pointer to an SMEM item on success, ERR_PTR() on failure. */ void *qcom_smem_get(unsigned host, unsigned item, size_t *size) @@ -1127,6 +1156,7 @@ static int qcom_smem_probe(struct platform_device *pd= ev) struct smem_header *header; struct reserved_mem *rmem; struct qcom_smem *smem; + struct auxiliary_device *socinfo; unsigned long flags; int num_regions; int hwlock_id; @@ -1234,19 +1264,15 @@ static int qcom_smem_probe(struct platform_device *= pdev) =20 __smem =3D smem; =20 - smem->socinfo =3D platform_device_register_data(&pdev->dev, "qcom-socinfo= ", - PLATFORM_DEVID_NONE, NULL, - 0); - if (IS_ERR(smem->socinfo)) - dev_dbg(&pdev->dev, "failed to register socinfo device\n"); + socinfo =3D devm_auxiliary_device_create(&pdev->dev, "qcom-socinfo", NULL= ); + if (IS_ERR(socinfo)) + dev_dbg(&pdev->dev, "failed to create socinfo device\n"); =20 return 0; } =20 static void qcom_smem_remove(struct platform_device *pdev) { - platform_device_unregister(__smem->socinfo); - __smem =3D NULL; } =20 diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c deleted file mode 100644 index 003a2304d535c2655db566c644342dbc387e24a9..000000000000000000000000000= 0000000000000 --- a/drivers/soc/qcom/socinfo.c +++ /dev/null @@ -1,931 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (c) 2009-2017, The Linux Foundation. All rights reserved. - * Copyright (c) 2017-2019, Linaro Ltd. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -/* Helper macros to create soc_id table */ -#define qcom_board_id(id) QCOM_ID_ ## id, __stringify(id) -#define qcom_board_id_named(id, name) QCOM_ID_ ## id, (name) - -#ifdef CONFIG_DEBUG_FS -#define SMEM_IMAGE_VERSION_BLOCKS_COUNT 32 -#define SMEM_IMAGE_VERSION_SIZE 4096 -#define SMEM_IMAGE_VERSION_NAME_SIZE 75 -#define SMEM_IMAGE_VERSION_VARIANT_SIZE 20 -#define SMEM_IMAGE_VERSION_OEM_SIZE 32 - -/* - * SMEM Image table indices - */ -#define SMEM_IMAGE_TABLE_BOOT_INDEX 0 -#define SMEM_IMAGE_TABLE_TZ_INDEX 1 -#define SMEM_IMAGE_TABLE_TZSECAPP_INDEX 2 -#define SMEM_IMAGE_TABLE_RPM_INDEX 3 -#define SMEM_IMAGE_TABLE_SDI_INDEX 4 -#define SMEM_IMAGE_TABLE_HYP_INDEX 5 -#define SMEM_IMAGE_TABLE_ADSP1_INDEX 6 -#define SMEM_IMAGE_TABLE_ADSP2_INDEX 7 -#define SMEM_IMAGE_TABLE_CDSP2_INDEX 8 -#define SMEM_IMAGE_TABLE_APPSBL_INDEX 9 -#define SMEM_IMAGE_TABLE_APPS_INDEX 10 -#define SMEM_IMAGE_TABLE_MPSS_INDEX 11 -#define SMEM_IMAGE_TABLE_ADSP_INDEX 12 -#define SMEM_IMAGE_TABLE_CNSS_INDEX 13 -#define SMEM_IMAGE_TABLE_VIDEO_INDEX 14 -#define SMEM_IMAGE_TABLE_DSPS_INDEX 15 -#define SMEM_IMAGE_TABLE_CDSP_INDEX 16 -#define SMEM_IMAGE_TABLE_NPU_INDEX 17 -#define SMEM_IMAGE_TABLE_WPSS_INDEX 18 -#define SMEM_IMAGE_TABLE_CDSP1_INDEX 19 -#define SMEM_IMAGE_TABLE_GPDSP_INDEX 20 -#define SMEM_IMAGE_TABLE_GPDSP1_INDEX 21 -#define SMEM_IMAGE_TABLE_SENSORPD_INDEX 22 -#define SMEM_IMAGE_TABLE_AUDIOPD_INDEX 23 -#define SMEM_IMAGE_TABLE_OEMPD_INDEX 24 -#define SMEM_IMAGE_TABLE_CHARGERPD_INDEX 25 -#define SMEM_IMAGE_TABLE_OISPD_INDEX 26 -#define SMEM_IMAGE_TABLE_SOCCP_INDEX 27 -#define SMEM_IMAGE_TABLE_TME_INDEX 28 -#define SMEM_IMAGE_TABLE_GEARVM_INDEX 29 -#define SMEM_IMAGE_TABLE_UEFI_INDEX 30 -#define SMEM_IMAGE_TABLE_CDSP3_INDEX 31 -#define SMEM_IMAGE_TABLE_AUDIOPD_ADSP1_INDEX 32 -#define SMEM_IMAGE_TABLE_AUDIOPD_ADSP2_INDEX 33 -#define SMEM_IMAGE_TABLE_DCP_INDEX 34 -#define SMEM_IMAGE_TABLE_OOBS_INDEX 35 -#define SMEM_IMAGE_TABLE_OOBNS_INDEX 36 -#define SMEM_IMAGE_TABLE_DEVCFG_INDEX 37 -#define SMEM_IMAGE_TABLE_BTPD_INDEX 38 -#define SMEM_IMAGE_TABLE_QECP_INDEX 39 - -#define SMEM_IMAGE_VERSION_TABLE 469 -#define SMEM_IMAGE_VERSION_TABLE_2 667 - -/* - * SMEM Image table names - */ -static const char *const socinfo_image_names[] =3D { - [SMEM_IMAGE_TABLE_ADSP1_INDEX] =3D "adsp1", - [SMEM_IMAGE_TABLE_ADSP2_INDEX] =3D "adsp2", - [SMEM_IMAGE_TABLE_ADSP_INDEX] =3D "adsp", - [SMEM_IMAGE_TABLE_APPSBL_INDEX] =3D "appsbl", - [SMEM_IMAGE_TABLE_APPS_INDEX] =3D "apps", - [SMEM_IMAGE_TABLE_AUDIOPD_INDEX] =3D "audiopd", - [SMEM_IMAGE_TABLE_AUDIOPD_ADSP1_INDEX] =3D "audiopd_adsp1", - [SMEM_IMAGE_TABLE_AUDIOPD_ADSP2_INDEX] =3D "audiopd_adsp2", - [SMEM_IMAGE_TABLE_BOOT_INDEX] =3D "boot", - [SMEM_IMAGE_TABLE_BTPD_INDEX] =3D "btpd", - [SMEM_IMAGE_TABLE_CDSP1_INDEX] =3D "cdsp1", - [SMEM_IMAGE_TABLE_CDSP2_INDEX] =3D "cdsp2", - [SMEM_IMAGE_TABLE_CDSP3_INDEX] =3D "cdsp3", - [SMEM_IMAGE_TABLE_CDSP_INDEX] =3D "cdsp", - [SMEM_IMAGE_TABLE_CHARGERPD_INDEX] =3D "chargerpd", - [SMEM_IMAGE_TABLE_CNSS_INDEX] =3D "cnss", - [SMEM_IMAGE_TABLE_DCP_INDEX] =3D "dcp", - [SMEM_IMAGE_TABLE_DEVCFG_INDEX] =3D "devcfg", - [SMEM_IMAGE_TABLE_DSPS_INDEX] =3D "dsps", - [SMEM_IMAGE_TABLE_GEARVM_INDEX] =3D "gearvm", - [SMEM_IMAGE_TABLE_GPDSP1_INDEX] =3D "gpdsp1", - [SMEM_IMAGE_TABLE_GPDSP_INDEX] =3D "gpdsp", - [SMEM_IMAGE_TABLE_HYP_INDEX] =3D "hyp", - [SMEM_IMAGE_TABLE_MPSS_INDEX] =3D "mpss", - [SMEM_IMAGE_TABLE_NPU_INDEX] =3D "npu", - [SMEM_IMAGE_TABLE_OEMPD_INDEX] =3D "oempd", - [SMEM_IMAGE_TABLE_OISPD_INDEX] =3D "oispd", - [SMEM_IMAGE_TABLE_OOBNS_INDEX] =3D "oobns", - [SMEM_IMAGE_TABLE_OOBS_INDEX] =3D "oobs", - [SMEM_IMAGE_TABLE_QECP_INDEX] =3D "qecp", - [SMEM_IMAGE_TABLE_RPM_INDEX] =3D "rpm", - [SMEM_IMAGE_TABLE_SDI_INDEX] =3D "sdi", - [SMEM_IMAGE_TABLE_SENSORPD_INDEX] =3D "sensorpd", - [SMEM_IMAGE_TABLE_SOCCP_INDEX] =3D "soccp", - [SMEM_IMAGE_TABLE_TME_INDEX] =3D "tme", - [SMEM_IMAGE_TABLE_TZ_INDEX] =3D "tz", - [SMEM_IMAGE_TABLE_TZSECAPP_INDEX] =3D "tzsecapp", - [SMEM_IMAGE_TABLE_UEFI_INDEX] =3D "uefi", - [SMEM_IMAGE_TABLE_VIDEO_INDEX] =3D "video", - [SMEM_IMAGE_TABLE_WPSS_INDEX] =3D "wpss", -}; - -static const char *const pmic_models[] =3D { - [0] =3D "Unknown PMIC model", - [1] =3D "PM8941", - [2] =3D "PM8841", - [3] =3D "PM8019", - [4] =3D "PM8226", - [5] =3D "PM8110", - [6] =3D "PMA8084", - [7] =3D "PMI8962", - [8] =3D "PMD9635", - [9] =3D "PM8994", - [10] =3D "PMI8994", - [11] =3D "PM8916", - [12] =3D "PM8004", - [13] =3D "PM8909/PM8058", - [14] =3D "PM8028", - [15] =3D "PM8901", - [16] =3D "PM8950/PM8027", - [17] =3D "PMI8950/ISL9519", - [18] =3D "PMK8001/PM8921", - [19] =3D "PMI8996/PM8018", - [20] =3D "PM8998/PM8015", - [21] =3D "PMI8998/PM8014", - [22] =3D "PM8821", - [23] =3D "PM8038", - [24] =3D "PM8005/PM8922", - [25] =3D "PM8917/PM8937", - [26] =3D "PM660L", - [27] =3D "PM660", - [30] =3D "PM8150", - [31] =3D "PM8150L", - [32] =3D "PM8150B", - [33] =3D "PMK8002", - [36] =3D "PM8009", - [37] =3D "PMI632", - [38] =3D "PM8150C", - [40] =3D "PM6150", - [41] =3D "SMB2351", - [44] =3D "PM8008", - [45] =3D "PM6125", - [46] =3D "PM7250B", - [47] =3D "PMK8350", - [48] =3D "PM8350", - [49] =3D "PM8350C", - [50] =3D "PM8350B", - [51] =3D "PMR735A", - [52] =3D "PMR735B", - [54] =3D "PM6350", - [55] =3D "PM4125", - [58] =3D "PM8450", - [65] =3D "PM8010", - [69] =3D "PM8550VS", - [70] =3D "PM8550VE", - [71] =3D "PM8550B", - [72] =3D "PMR735D", - [73] =3D "PM8550", - [74] =3D "PMK8550", - [78] =3D "PMM8650AU", - [79] =3D "PMM8650AU_PSAIL", - [80] =3D "PM7550", - [82] =3D "PMC8380", - [83] =3D "SMB2360", - [91] =3D "PMIV0108", -}; - -struct socinfo_params { - u32 raw_device_family; - u32 hw_plat_subtype; - u32 accessory_chip; - u32 raw_device_num; - u32 chip_family; - u32 foundry_id; - u32 plat_ver; - u32 raw_ver; - u32 hw_plat; - u32 fmt; - u32 nproduct_id; - u32 num_clusters; - u32 ncluster_array_offset; - u32 num_subset_parts; - u32 nsubset_parts_array_offset; - u32 nmodem_supported; - u32 feature_code; - u32 pcode; - u32 oem_variant; - u32 num_func_clusters; - u32 boot_cluster; - u32 boot_core; - u32 raw_package_type; -}; - -struct smem_image_version { - char name[SMEM_IMAGE_VERSION_NAME_SIZE]; - char variant[SMEM_IMAGE_VERSION_VARIANT_SIZE]; - char pad; - char oem[SMEM_IMAGE_VERSION_OEM_SIZE]; -}; -#endif /* CONFIG_DEBUG_FS */ - -struct qcom_socinfo { - struct soc_device *soc_dev; - struct soc_device_attribute attr; -#ifdef CONFIG_DEBUG_FS - struct dentry *dbg_root; - struct socinfo_params info; -#endif /* CONFIG_DEBUG_FS */ -}; - -struct soc_id { - unsigned int id; - const char *name; -}; - -static const struct soc_id soc_id[] =3D { - { qcom_board_id(MSM8260) }, - { qcom_board_id(MSM8660) }, - { qcom_board_id(APQ8060) }, - { qcom_board_id(MSM8960) }, - { qcom_board_id(APQ8064) }, - { qcom_board_id(MSM8930) }, - { qcom_board_id(MSM8630) }, - { qcom_board_id(MSM8230) }, - { qcom_board_id(APQ8030) }, - { qcom_board_id(MSM8627) }, - { qcom_board_id(MSM8227) }, - { qcom_board_id(MSM8660A) }, - { qcom_board_id(MSM8260A) }, - { qcom_board_id(APQ8060A) }, - { qcom_board_id(MSM8974) }, - { qcom_board_id(MSM8225) }, - { qcom_board_id(MSM8625) }, - { qcom_board_id(MPQ8064) }, - { qcom_board_id(MSM8960AB) }, - { qcom_board_id(APQ8060AB) }, - { qcom_board_id(MSM8260AB) }, - { qcom_board_id(MSM8660AB) }, - { qcom_board_id(MSM8930AA) }, - { qcom_board_id(MSM8630AA) }, - { qcom_board_id(MSM8230AA) }, - { qcom_board_id(MSM8626) }, - { qcom_board_id(MSM8610) }, - { qcom_board_id(APQ8064AB) }, - { qcom_board_id(MSM8930AB) }, - { qcom_board_id(MSM8630AB) }, - { qcom_board_id(MSM8230AB) }, - { qcom_board_id(APQ8030AB) }, - { qcom_board_id(MSM8226) }, - { qcom_board_id(MSM8526) }, - { qcom_board_id(APQ8030AA) }, - { qcom_board_id(MSM8110) }, - { qcom_board_id(MSM8210) }, - { qcom_board_id(MSM8810) }, - { qcom_board_id(MSM8212) }, - { qcom_board_id(MSM8612) }, - { qcom_board_id(MSM8112) }, - { qcom_board_id(MSM8125) }, - { qcom_board_id(MSM8225Q) }, - { qcom_board_id(MSM8625Q) }, - { qcom_board_id(MSM8125Q) }, - { qcom_board_id(APQ8064AA) }, - { qcom_board_id(APQ8084) }, - { qcom_board_id(MSM8130) }, - { qcom_board_id(MSM8130AA) }, - { qcom_board_id(MSM8130AB) }, - { qcom_board_id(MSM8627AA) }, - { qcom_board_id(MSM8227AA) }, - { qcom_board_id(APQ8074) }, - { qcom_board_id(MSM8274) }, - { qcom_board_id(MSM8674) }, - { qcom_board_id(MDM9635) }, - { qcom_board_id_named(MSM8974PRO_AC, "MSM8974PRO-AC") }, - { qcom_board_id(MSM8126) }, - { qcom_board_id(APQ8026) }, - { qcom_board_id(MSM8926) }, - { qcom_board_id(IPQ8062) }, - { qcom_board_id(IPQ8064) }, - { qcom_board_id(IPQ8066) }, - { qcom_board_id(IPQ8068) }, - { qcom_board_id(MSM8326) }, - { qcom_board_id(MSM8916) }, - { qcom_board_id(MSM8994) }, - { qcom_board_id_named(APQ8074PRO_AA, "APQ8074PRO-AA") }, - { qcom_board_id_named(APQ8074PRO_AB, "APQ8074PRO-AB") }, - { qcom_board_id_named(APQ8074PRO_AC, "APQ8074PRO-AC") }, - { qcom_board_id_named(MSM8274PRO_AA, "MSM8274PRO-AA") }, - { qcom_board_id_named(MSM8274PRO_AB, "MSM8274PRO-AB") }, - { qcom_board_id_named(MSM8274PRO_AC, "MSM8274PRO-AC") }, - { qcom_board_id_named(MSM8674PRO_AA, "MSM8674PRO-AA") }, - { qcom_board_id_named(MSM8674PRO_AB, "MSM8674PRO-AB") }, - { qcom_board_id_named(MSM8674PRO_AC, "MSM8674PRO-AC") }, - { qcom_board_id_named(MSM8974PRO_AA, "MSM8974PRO-AA") }, - { qcom_board_id_named(MSM8974PRO_AB, "MSM8974PRO-AB") }, - { qcom_board_id(APQ8028) }, - { qcom_board_id(MSM8128) }, - { qcom_board_id(MSM8228) }, - { qcom_board_id(MSM8528) }, - { qcom_board_id(MSM8628) }, - { qcom_board_id(MSM8928) }, - { qcom_board_id(MSM8510) }, - { qcom_board_id(MSM8512) }, - { qcom_board_id(MSM8936) }, - { qcom_board_id(MDM9640) }, - { qcom_board_id(MSM8939) }, - { qcom_board_id(APQ8036) }, - { qcom_board_id(APQ8039) }, - { qcom_board_id(MSM8236) }, - { qcom_board_id(MSM8636) }, - { qcom_board_id(MSM8909) }, - { qcom_board_id(MSM8996) }, - { qcom_board_id(APQ8016) }, - { qcom_board_id(MSM8216) }, - { qcom_board_id(MSM8116) }, - { qcom_board_id(MSM8616) }, - { qcom_board_id(MSM8992) }, - { qcom_board_id(APQ8092) }, - { qcom_board_id(APQ8094) }, - { qcom_board_id(MSM8209) }, - { qcom_board_id(MSM8208) }, - { qcom_board_id(MDM9209) }, - { qcom_board_id(MDM9309) }, - { qcom_board_id(MDM9609) }, - { qcom_board_id(MSM8239) }, - { qcom_board_id(MSM8952) }, - { qcom_board_id(APQ8009) }, - { qcom_board_id(MSM8956) }, - { qcom_board_id(MSM8929) }, - { qcom_board_id(MSM8629) }, - { qcom_board_id(MSM8229) }, - { qcom_board_id(APQ8029) }, - { qcom_board_id(APQ8056) }, - { qcom_board_id(MSM8609) }, - { qcom_board_id(APQ8076) }, - { qcom_board_id(MSM8976) }, - { qcom_board_id(IPQ8065) }, - { qcom_board_id(IPQ8069) }, - { qcom_board_id(MDM9650) }, - { qcom_board_id(MDM9655) }, - { qcom_board_id(MDM9250) }, - { qcom_board_id(MDM9255) }, - { qcom_board_id(MDM9350) }, - { qcom_board_id(APQ8052) }, - { qcom_board_id(MDM9607) }, - { qcom_board_id(APQ8096) }, - { qcom_board_id(MSM8998) }, - { qcom_board_id(MSM8953) }, - { qcom_board_id(MSM8937) }, - { qcom_board_id(APQ8037) }, - { qcom_board_id(MDM8207) }, - { qcom_board_id(MDM9207) }, - { qcom_board_id(MDM9307) }, - { qcom_board_id(MDM9628) }, - { qcom_board_id(MSM8909W) }, - { qcom_board_id(APQ8009W) }, - { qcom_board_id(MSM8996L) }, - { qcom_board_id(MSM8917) }, - { qcom_board_id(APQ8053) }, - { qcom_board_id(MSM8996SG) }, - { qcom_board_id(APQ8017) }, - { qcom_board_id(MSM8217) }, - { qcom_board_id(MSM8617) }, - { qcom_board_id(MSM8996AU) }, - { qcom_board_id(APQ8096AU) }, - { qcom_board_id(APQ8096SG) }, - { qcom_board_id(MSM8940) }, - { qcom_board_id(SDX201) }, - { qcom_board_id(SDM660) }, - { qcom_board_id(SDM630) }, - { qcom_board_id(APQ8098) }, - { qcom_board_id(MSM8920) }, - { qcom_board_id(SDM845) }, - { qcom_board_id(MDM9206) }, - { qcom_board_id(IPQ8074) }, - { qcom_board_id(SDA660) }, - { qcom_board_id(SDM658) }, - { qcom_board_id(SDA658) }, - { qcom_board_id(SDA630) }, - { qcom_board_id(MSM8905) }, - { qcom_board_id(SDX202) }, - { qcom_board_id(SDM670) }, - { qcom_board_id(SDM450) }, - { qcom_board_id(SM8150) }, - { qcom_board_id(SDA845) }, - { qcom_board_id(IPQ8072) }, - { qcom_board_id(IPQ8076) }, - { qcom_board_id(IPQ8078) }, - { qcom_board_id(SDM636) }, - { qcom_board_id(SDA636) }, - { qcom_board_id(SDM632) }, - { qcom_board_id(SDA632) }, - { qcom_board_id(SDA450) }, - { qcom_board_id(SDM439) }, - { qcom_board_id(SDM429) }, - { qcom_board_id(SM8250) }, - { qcom_board_id(SA8155) }, - { qcom_board_id(SDA439) }, - { qcom_board_id(SDA429) }, - { qcom_board_id(SM7150) }, - { qcom_board_id(SM7150P) }, - { qcom_board_id(IPQ8070) }, - { qcom_board_id(IPQ8071) }, - { qcom_board_id(QM215) }, - { qcom_board_id(IPQ8072A) }, - { qcom_board_id(IPQ8074A) }, - { qcom_board_id(IPQ8076A) }, - { qcom_board_id(IPQ8078A) }, - { qcom_board_id(SM6125) }, - { qcom_board_id(IPQ8070A) }, - { qcom_board_id(IPQ8071A) }, - { qcom_board_id(IPQ8172) }, - { qcom_board_id(IPQ8173) }, - { qcom_board_id(IPQ8174) }, - { qcom_board_id(IPQ6018) }, - { qcom_board_id(IPQ6028) }, - { qcom_board_id(SDM429W) }, - { qcom_board_id(SM4250) }, - { qcom_board_id(IPQ6000) }, - { qcom_board_id(IPQ6010) }, - { qcom_board_id(SC7180) }, - { qcom_board_id(SM6350) }, - { qcom_board_id(QCM2150) }, - { qcom_board_id(SDA429W) }, - { qcom_board_id(SM8350) }, - { qcom_board_id(QCM2290) }, - { qcom_board_id(SM7125) }, - { qcom_board_id(SM6115) }, - { qcom_board_id(IPQ5010) }, - { qcom_board_id(IPQ5018) }, - { qcom_board_id(IPQ5028) }, - { qcom_board_id(SC8280XP) }, - { qcom_board_id(IPQ6005) }, - { qcom_board_id(QRB5165) }, - { qcom_board_id(SM8450) }, - { qcom_board_id(SM7225) }, - { qcom_board_id(SA8295P) }, - { qcom_board_id(SA8540P) }, - { qcom_board_id(QCM4290) }, - { qcom_board_id(QCS4290) }, - { qcom_board_id(SM7325) }, - { qcom_board_id_named(SM8450_2, "SM8450") }, - { qcom_board_id_named(SM8450_3, "SM8450") }, - { qcom_board_id(SC7280) }, - { qcom_board_id(SC7180P) }, - { qcom_board_id(QCM6490) }, - { qcom_board_id(QCS6490) }, - { qcom_board_id(SM7325P) }, - { qcom_board_id(IPQ5000) }, - { qcom_board_id(IPQ0509) }, - { qcom_board_id(IPQ0518) }, - { qcom_board_id(SM6375) }, - { qcom_board_id(IPQ9514) }, - { qcom_board_id(IPQ9550) }, - { qcom_board_id(IPQ9554) }, - { qcom_board_id(IPQ9570) }, - { qcom_board_id(IPQ9574) }, - { qcom_board_id(SM8550) }, - { qcom_board_id(IPQ5016) }, - { qcom_board_id(IPQ9510) }, - { qcom_board_id(QRB4210) }, - { qcom_board_id(QRB2210) }, - { qcom_board_id(SAR2130P) }, - { qcom_board_id(SM8475) }, - { qcom_board_id(SM8475P) }, - { qcom_board_id(SA8255P) }, - { qcom_board_id(SA8775P) }, - { qcom_board_id(QRU1000) }, - { qcom_board_id(SM8475_2) }, - { qcom_board_id(QDU1000) }, - { qcom_board_id(X1E80100) }, - { qcom_board_id(SM8650) }, - { qcom_board_id(SM4450) }, - { qcom_board_id(SAR1130P) }, - { qcom_board_id(QDU1010) }, - { qcom_board_id(QRU1032) }, - { qcom_board_id(QRU1052) }, - { qcom_board_id(QRU1062) }, - { qcom_board_id(IPQ5332) }, - { qcom_board_id(IPQ5322) }, - { qcom_board_id(IPQ5312) }, - { qcom_board_id(IPQ5302) }, - { qcom_board_id(QCS8550) }, - { qcom_board_id(QCM8550) }, - { qcom_board_id(SM8750) }, - { qcom_board_id(IPQ5300) }, - { qcom_board_id(SM7635) }, - { qcom_board_id(SM6650) }, - { qcom_board_id(SM6650P) }, - { qcom_board_id(IPQ5321) }, - { qcom_board_id(IPQ5424) }, - { qcom_board_id(QCM6690) }, - { qcom_board_id(QCS6690) }, - { qcom_board_id(SM8850) }, - { qcom_board_id(IPQ5404) }, - { qcom_board_id(QCS9100) }, - { qcom_board_id(QCS8300) }, - { qcom_board_id(QCS8275) }, - { qcom_board_id(QCS9075) }, - { qcom_board_id(QCS615) }, -}; - -static const char *socinfo_machine(struct device *dev, unsigned int id) -{ - int idx; - - for (idx =3D 0; idx < ARRAY_SIZE(soc_id); idx++) { - if (soc_id[idx].id =3D=3D id) - return soc_id[idx].name; - } - - return NULL; -} - -#ifdef CONFIG_DEBUG_FS - -#define QCOM_OPEN(name, _func) \ -static int qcom_open_##name(struct inode *inode, struct file *file) \ -{ \ - return single_open(file, _func, inode->i_private); \ -} \ - \ -static const struct file_operations qcom_ ##name## _ops =3D { \ - .open =3D qcom_open_##name, \ - .read =3D seq_read, \ - .llseek =3D seq_lseek, \ - .release =3D single_release, \ -} - -#define DEBUGFS_ADD(info, name) \ - debugfs_create_file(__stringify(name), 0444, \ - qcom_socinfo->dbg_root, \ - info, &qcom_ ##name## _ops) - - -static int qcom_show_build_id(struct seq_file *seq, void *p) -{ - struct socinfo *socinfo =3D seq->private; - - seq_printf(seq, "%s\n", socinfo->build_id); - - return 0; -} - -static int qcom_show_pmic_model(struct seq_file *seq, void *p) -{ - struct socinfo *socinfo =3D seq->private; - int model =3D SOCINFO_MINOR(le32_to_cpu(socinfo->pmic_model)); - - if (model < 0) - return -EINVAL; - - if (model < ARRAY_SIZE(pmic_models) && pmic_models[model]) - seq_printf(seq, "%s\n", pmic_models[model]); - else - seq_printf(seq, "unknown (%d)\n", model); - - return 0; -} - -static int qcom_show_pmic_model_array(struct seq_file *seq, void *p) -{ - struct socinfo *socinfo =3D seq->private; - unsigned int num_pmics =3D le32_to_cpu(socinfo->num_pmics); - unsigned int pmic_array_offset =3D le32_to_cpu(socinfo->pmic_array_offset= ); - int i; - void *ptr =3D socinfo; - - ptr +=3D pmic_array_offset; - - /* No need for bounds checking, it happened at socinfo_debugfs_init */ - for (i =3D 0; i < num_pmics; i++) { - unsigned int model =3D SOCINFO_MINOR(get_unaligned_le32(ptr + 2 * i * si= zeof(u32))); - unsigned int die_rev =3D get_unaligned_le32(ptr + (2 * i + 1) * sizeof(u= 32)); - - if (model < ARRAY_SIZE(pmic_models) && pmic_models[model]) - seq_printf(seq, "%s %u.%u\n", pmic_models[model], - SOCINFO_MAJOR(die_rev), - SOCINFO_MINOR(die_rev)); - else - seq_printf(seq, "unknown (%d)\n", model); - } - - return 0; -} - -static int qcom_show_pmic_die_revision(struct seq_file *seq, void *p) -{ - struct socinfo *socinfo =3D seq->private; - - seq_printf(seq, "%u.%u\n", - SOCINFO_MAJOR(le32_to_cpu(socinfo->pmic_die_rev)), - SOCINFO_MINOR(le32_to_cpu(socinfo->pmic_die_rev))); - - return 0; -} - -static int qcom_show_chip_id(struct seq_file *seq, void *p) -{ - struct socinfo *socinfo =3D seq->private; - - seq_printf(seq, "%s\n", socinfo->chip_id); - - return 0; -} - -QCOM_OPEN(build_id, qcom_show_build_id); -QCOM_OPEN(pmic_model, qcom_show_pmic_model); -QCOM_OPEN(pmic_model_array, qcom_show_pmic_model_array); -QCOM_OPEN(pmic_die_rev, qcom_show_pmic_die_revision); -QCOM_OPEN(chip_id, qcom_show_chip_id); - -#define DEFINE_IMAGE_OPS(type) \ -static int show_image_##type(struct seq_file *seq, void *p) \ -{ \ - struct smem_image_version *image_version =3D seq->private; \ - if (image_version->type[0] !=3D '\0') \ - seq_printf(seq, "%s\n", image_version->type); \ - return 0; \ -} \ -static int open_image_##type(struct inode *inode, struct file *file) \ -{ \ - return single_open(file, show_image_##type, inode->i_private); \ -} \ - \ -static const struct file_operations qcom_image_##type##_ops =3D { \ - .open =3D open_image_##type, \ - .read =3D seq_read, \ - .llseek =3D seq_lseek, \ - .release =3D single_release, \ -} - -DEFINE_IMAGE_OPS(name); -DEFINE_IMAGE_OPS(variant); -DEFINE_IMAGE_OPS(oem); - -static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo, - struct socinfo *info, size_t info_size) -{ - struct smem_image_version *versions; - struct dentry *dentry; - size_t size; - int i, j; - unsigned int num_pmics; - unsigned int pmic_array_offset; - - qcom_socinfo->dbg_root =3D debugfs_create_dir("qcom_socinfo", NULL); - - qcom_socinfo->info.fmt =3D __le32_to_cpu(info->fmt); - - debugfs_create_x32("info_fmt", 0444, qcom_socinfo->dbg_root, - &qcom_socinfo->info.fmt); - - switch (qcom_socinfo->info.fmt) { - case SOCINFO_VERSION(0, 23): - case SOCINFO_VERSION(0, 22): - case SOCINFO_VERSION(0, 21): - case SOCINFO_VERSION(0, 20): - qcom_socinfo->info.raw_package_type =3D __le32_to_cpu(info->raw_package_= type); - debugfs_create_u32("raw_package_type", 0444, qcom_socinfo->dbg_root, - &qcom_socinfo->info.raw_package_type); - fallthrough; - case SOCINFO_VERSION(0, 19): - qcom_socinfo->info.num_func_clusters =3D __le32_to_cpu(info->num_func_cl= usters); - qcom_socinfo->info.boot_cluster =3D __le32_to_cpu(info->boot_cluster); - qcom_socinfo->info.boot_core =3D __le32_to_cpu(info->boot_core); - - debugfs_create_u32("num_func_clusters", 0444, qcom_socinfo->dbg_root, - &qcom_socinfo->info.num_func_clusters); - debugfs_create_u32("boot_cluster", 0444, qcom_socinfo->dbg_root, - &qcom_socinfo->info.boot_cluster); - debugfs_create_u32("boot_core", 0444, qcom_socinfo->dbg_root, - &qcom_socinfo->info.boot_core); - fallthrough; - case SOCINFO_VERSION(0, 18): - case SOCINFO_VERSION(0, 17): - qcom_socinfo->info.oem_variant =3D __le32_to_cpu(info->oem_variant); - debugfs_create_u32("oem_variant", 0444, qcom_socinfo->dbg_root, - &qcom_socinfo->info.oem_variant); - fallthrough; - case SOCINFO_VERSION(0, 16): - qcom_socinfo->info.feature_code =3D __le32_to_cpu(info->feature_code); - qcom_socinfo->info.pcode =3D __le32_to_cpu(info->pcode); - - debugfs_create_u32("feature_code", 0444, qcom_socinfo->dbg_root, - &qcom_socinfo->info.feature_code); - debugfs_create_u32("pcode", 0444, qcom_socinfo->dbg_root, - &qcom_socinfo->info.pcode); - fallthrough; - case SOCINFO_VERSION(0, 15): - qcom_socinfo->info.nmodem_supported =3D __le32_to_cpu(info->nmodem_suppo= rted); - - debugfs_create_u32("nmodem_supported", 0444, qcom_socinfo->dbg_root, - &qcom_socinfo->info.nmodem_supported); - fallthrough; - case SOCINFO_VERSION(0, 14): - qcom_socinfo->info.num_clusters =3D __le32_to_cpu(info->num_clusters); - qcom_socinfo->info.ncluster_array_offset =3D __le32_to_cpu(info->ncluste= r_array_offset); - qcom_socinfo->info.num_subset_parts =3D __le32_to_cpu(info->num_subset_p= arts); - qcom_socinfo->info.nsubset_parts_array_offset =3D - __le32_to_cpu(info->nsubset_parts_array_offset); - - debugfs_create_u32("num_clusters", 0444, qcom_socinfo->dbg_root, - &qcom_socinfo->info.num_clusters); - debugfs_create_u32("ncluster_array_offset", 0444, qcom_socinfo->dbg_root, - &qcom_socinfo->info.ncluster_array_offset); - debugfs_create_u32("num_subset_parts", 0444, qcom_socinfo->dbg_root, - &qcom_socinfo->info.num_subset_parts); - debugfs_create_u32("nsubset_parts_array_offset", 0444, qcom_socinfo->dbg= _root, - &qcom_socinfo->info.nsubset_parts_array_offset); - fallthrough; - case SOCINFO_VERSION(0, 13): - qcom_socinfo->info.nproduct_id =3D __le32_to_cpu(info->nproduct_id); - - debugfs_create_u32("nproduct_id", 0444, qcom_socinfo->dbg_root, - &qcom_socinfo->info.nproduct_id); - DEBUGFS_ADD(info, chip_id); - fallthrough; - case SOCINFO_VERSION(0, 12): - qcom_socinfo->info.chip_family =3D - __le32_to_cpu(info->chip_family); - qcom_socinfo->info.raw_device_family =3D - __le32_to_cpu(info->raw_device_family); - qcom_socinfo->info.raw_device_num =3D - __le32_to_cpu(info->raw_device_num); - - debugfs_create_x32("chip_family", 0444, qcom_socinfo->dbg_root, - &qcom_socinfo->info.chip_family); - debugfs_create_x32("raw_device_family", 0444, - qcom_socinfo->dbg_root, - &qcom_socinfo->info.raw_device_family); - debugfs_create_x32("raw_device_number", 0444, - qcom_socinfo->dbg_root, - &qcom_socinfo->info.raw_device_num); - fallthrough; - case SOCINFO_VERSION(0, 11): - num_pmics =3D le32_to_cpu(info->num_pmics); - pmic_array_offset =3D le32_to_cpu(info->pmic_array_offset); - if (pmic_array_offset + 2 * num_pmics * sizeof(u32) <=3D info_size) - DEBUGFS_ADD(info, pmic_model_array); - fallthrough; - case SOCINFO_VERSION(0, 10): - case SOCINFO_VERSION(0, 9): - qcom_socinfo->info.foundry_id =3D __le32_to_cpu(info->foundry_id); - - debugfs_create_u32("foundry_id", 0444, qcom_socinfo->dbg_root, - &qcom_socinfo->info.foundry_id); - fallthrough; - case SOCINFO_VERSION(0, 8): - case SOCINFO_VERSION(0, 7): - DEBUGFS_ADD(info, pmic_model); - DEBUGFS_ADD(info, pmic_die_rev); - fallthrough; - case SOCINFO_VERSION(0, 6): - qcom_socinfo->info.hw_plat_subtype =3D - __le32_to_cpu(info->hw_plat_subtype); - - debugfs_create_u32("hardware_platform_subtype", 0444, - qcom_socinfo->dbg_root, - &qcom_socinfo->info.hw_plat_subtype); - fallthrough; - case SOCINFO_VERSION(0, 5): - qcom_socinfo->info.accessory_chip =3D - __le32_to_cpu(info->accessory_chip); - - debugfs_create_u32("accessory_chip", 0444, - qcom_socinfo->dbg_root, - &qcom_socinfo->info.accessory_chip); - fallthrough; - case SOCINFO_VERSION(0, 4): - qcom_socinfo->info.plat_ver =3D __le32_to_cpu(info->plat_ver); - - debugfs_create_u32("platform_version", 0444, - qcom_socinfo->dbg_root, - &qcom_socinfo->info.plat_ver); - fallthrough; - case SOCINFO_VERSION(0, 3): - qcom_socinfo->info.hw_plat =3D __le32_to_cpu(info->hw_plat); - - debugfs_create_u32("hardware_platform", 0444, - qcom_socinfo->dbg_root, - &qcom_socinfo->info.hw_plat); - fallthrough; - case SOCINFO_VERSION(0, 2): - qcom_socinfo->info.raw_ver =3D __le32_to_cpu(info->raw_ver); - - debugfs_create_u32("raw_version", 0444, qcom_socinfo->dbg_root, - &qcom_socinfo->info.raw_ver); - fallthrough; - case SOCINFO_VERSION(0, 1): - DEBUGFS_ADD(info, build_id); - break; - } - - for (i =3D 0, j =3D 0; i < ARRAY_SIZE(socinfo_image_names); i++, j++) { - if (!socinfo_image_names[i]) - continue; - - if (i =3D=3D 0) { - versions =3D qcom_smem_get(QCOM_SMEM_HOST_ANY, - SMEM_IMAGE_VERSION_TABLE, - &size); - } else if (i =3D=3D 32) { - versions =3D qcom_smem_get(QCOM_SMEM_HOST_ANY, - SMEM_IMAGE_VERSION_TABLE_2, - &size); - if (IS_ERR(versions)) - break; - - j =3D 0; - } - - dentry =3D debugfs_create_dir(socinfo_image_names[i], - qcom_socinfo->dbg_root); - debugfs_create_file("name", 0444, dentry, &versions[j], - &qcom_image_name_ops); - debugfs_create_file("variant", 0444, dentry, &versions[j], - &qcom_image_variant_ops); - debugfs_create_file("oem", 0444, dentry, &versions[j], - &qcom_image_oem_ops); - } -} - -static void socinfo_debugfs_exit(struct qcom_socinfo *qcom_socinfo) -{ - debugfs_remove_recursive(qcom_socinfo->dbg_root); -} -#else -static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo, - struct socinfo *info, size_t info_size) -{ -} -static void socinfo_debugfs_exit(struct qcom_socinfo *qcom_socinfo) { } -#endif /* CONFIG_DEBUG_FS */ - -static int qcom_socinfo_probe(struct platform_device *pdev) -{ - struct qcom_socinfo *qs; - struct socinfo *info; - size_t item_size; - - info =3D qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_HW_SW_BUILD_ID, - &item_size); - if (IS_ERR(info)) { - dev_err(&pdev->dev, "Couldn't find socinfo\n"); - return PTR_ERR(info); - } - - qs =3D devm_kzalloc(&pdev->dev, sizeof(*qs), GFP_KERNEL); - if (!qs) - return -ENOMEM; - - qs->attr.family =3D "Snapdragon"; - qs->attr.machine =3D socinfo_machine(&pdev->dev, - le32_to_cpu(info->id)); - qs->attr.soc_id =3D devm_kasprintf(&pdev->dev, GFP_KERNEL, "%u", - le32_to_cpu(info->id)); - qs->attr.revision =3D devm_kasprintf(&pdev->dev, GFP_KERNEL, "%u.%u", - SOCINFO_MAJOR(le32_to_cpu(info->ver)), - SOCINFO_MINOR(le32_to_cpu(info->ver))); - if (!qs->attr.soc_id || !qs->attr.revision) - return -ENOMEM; - - if (offsetofend(struct socinfo, serial_num) <=3D item_size) { - qs->attr.serial_number =3D devm_kasprintf(&pdev->dev, GFP_KERNEL, - "%u", - le32_to_cpu(info->serial_num)); - if (!qs->attr.serial_number) - return -ENOMEM; - } - - qs->soc_dev =3D soc_device_register(&qs->attr); - if (IS_ERR(qs->soc_dev)) - return PTR_ERR(qs->soc_dev); - - socinfo_debugfs_init(qs, info, item_size); - - /* Feed the soc specific unique data into entropy pool */ - add_device_randomness(info, item_size); - - platform_set_drvdata(pdev, qs); - - return 0; -} - -static void qcom_socinfo_remove(struct platform_device *pdev) -{ - struct qcom_socinfo *qs =3D platform_get_drvdata(pdev); - - soc_device_unregister(qs->soc_dev); - - socinfo_debugfs_exit(qs); -} - -static struct platform_driver qcom_socinfo_driver =3D { - .probe =3D qcom_socinfo_probe, - .remove =3D qcom_socinfo_remove, - .driver =3D { - .name =3D "qcom-socinfo", - }, -}; - -module_platform_driver(qcom_socinfo_driver); - -MODULE_DESCRIPTION("Qualcomm SoCinfo driver"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:qcom-socinfo"); diff --git a/drivers/soc/qcom/socinfo/Makefile b/drivers/soc/qcom/socinfo/M= akefile new file mode 100644 index 0000000000000000000000000000000000000000..8cdd77f46a22aeb97bcf1eeb904= 18db8f6352d3b --- /dev/null +++ b/drivers/soc/qcom/socinfo/Makefile @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_QCOM_SOCINFO) +=3D socinfo.o diff --git a/drivers/soc/qcom/socinfo/bindings.rs b/drivers/soc/qcom/socinf= o/bindings.rs new file mode 100644 index 0000000000000000000000000000000000000000..243fd2adf26ccf417166a08465b= 2b791030a2364 --- /dev/null +++ b/drivers/soc/qcom/socinfo/bindings.rs @@ -0,0 +1,123 @@ +// SPDX-License-Identifier: GPL-2.0 + +// Copyright (C) 2025 Google LLC. + +use kernel::{ + auxiliary, + bindings, + device::{ + Bound, + Device, // + }, + error::from_err_ptr, + ffi::c_char, + io::{ + Io, + Mmio, + MmioRaw, // + }, + macros::{ + AsBytes, + FromBytes, // + }, + prelude::*, + transmute::AsBytes, + types::ARef, // +}; + +// INVARIANT: raw is a region or subregion returned by get_smem_aux when p= resented with +// the auxdev in dev. +pub(crate) struct Smem { + dev: ARef, + raw: MmioRaw, +} + +impl Smem { + pub(crate) fn access<'a>(&'a self, dev: &'a Device) -> Option<&= 'a Mmio> { + if *dev !=3D *self.dev { + return None; + } + + // SAFETY: By our invariant, this was a subrange of what was retur= ned by smem_aux_get, for + // self.dev, and by our above check, that auxdev is still availabl= e. + Some(unsafe { Mmio::from_raw(&self.raw) }) + } + + pub(crate) fn subrange(&self, offset: usize, len: usize) -> Option { + let remaining_len: usize =3D self.raw.maxsize().checked_sub(offset= )?; + remaining_len.checked_sub(len)?; + // INVARIANT: Maintained because offset is positive, and the lengt= h fits. + Some(Self { + dev: self.dev.clone(), + raw: MmioRaw::new(self.raw.addr() + offset, len).ok()?, + }) + } + + pub(crate) fn maxsize(&self) -> usize { + self.raw.maxsize() + } + + pub(crate) fn get(dev: &auxiliary::Device, host: i32, item: u32= ) -> Result { + let mut size =3D 0; + // SAFETY: qcom_smem_get_aux only requires that the size pointer b= e a writable size_t, + // and that aux be an aux device. + let err_ptr =3D + unsafe { bindings::qcom_smem_get_aux(dev.as_raw(), host as u32= , item, &mut size) }; + let ptr =3D from_err_ptr(err_ptr)?; + let base_dev: &Device =3D dev.as_ref(); + // INVARIANT: If qcom_smem_get_aux does not return an error, the r= eturned pointer points to + // a readable IO region that qcom-smem will keep mapped while our = provided aux device is + // loaded. + Ok(Self { + dev: base_dev.into(), + raw: MmioRaw::new(ptr as usize, size)?, + }) + } +} + +pub(crate) const SMEM_IMAGE_VERSION_TABLE: u32 =3D 469; +pub(crate) const SMEM_IMAGE_VERSION_TABLE_2: u32 =3D 667; + +pub(crate) use bindings::socinfo; + +/// Produce `socinfo` by initializing from a byte buffer that may be too s= mall. +/// Code using the resulting value is expected to use the info_fmt field t= o determine +/// which fields have meaningful values. +pub(crate) fn socinfo_from_partial_bytes(soc_info_mem: &Mmio) -> Result { + let mut soc_info =3D socinfo::default(); + let byte_view: &mut [u8] =3D soc_info.as_bytes_mut(); + let len =3D core::cmp::min(soc_info_mem.maxsize(), byte_view.len()); + soc_info_mem.try_copy_to(&mut byte_view[..len], 0)?; + Ok(soc_info) +} + +#[derive(AsBytes, FromBytes, Default, Copy, Clone)] +#[repr(C)] +pub(crate) struct PmicEntry { + pub(crate) model: u32, + pub(crate) die_rev: u32, +} + +const SMEM_IMAGE_VERSION_NAME_SIZE: usize =3D 75; +const SMEM_IMAGE_VERSION_VARIANT_SIZE: usize =3D 20; +const SMEM_IMAGE_VERSION_OEM_SIZE: usize =3D 32; + +#[derive(AsBytes, FromBytes)] +#[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], +} + +impl Default for ImageVersion { + fn default() -> Self { + ImageVersion { + name: [0; SMEM_IMAGE_VERSION_NAME_SIZE], + variant: [0; SMEM_IMAGE_VERSION_VARIANT_SIZE], + pad: 0, + oem: [0; SMEM_IMAGE_VERSION_OEM_SIZE], + } + } +} diff --git a/drivers/soc/qcom/socinfo/data.rs b/drivers/soc/qcom/socinfo/da= ta.rs new file mode 100644 index 0000000000000000000000000000000000000000..e33e040ae34ddfd2acd1e1e64f5= e35cc78e85483 --- /dev/null +++ b/drivers/soc/qcom/socinfo/data.rs @@ -0,0 +1,438 @@ +// SPDX-License-Identifier: GPL-2.0 + +// Copyright (C) 2025 Google LLC. + +//! Data tables for QCom SocInfo driver +use kernel::{ + c_str, + prelude::*, + sparse_array, // +}; + +macro_rules! soc_ids { + { $( $entry:tt ),* $(,)? } =3D> { + pub(crate) static SOC_IDS: &[SocId] =3D &[ + $( + soc_id_entry!($entry) + ),* + ]; + } +} + +macro_rules! soc_id_entry { + ($id:ident) =3D> { + kernel::macros::paste! { + SocId { + id: kernel::bindings::[], + name: c_str!(stringify!($id)), + } + } + }; + (($id:ident, $name:literal)) =3D> { + kernel::macros::paste! { + SocId { + id: kernel::bindings::[], + name: c_str!($name), + } + } + }; +} + +pub(crate) struct SocId { + pub(crate) id: u32, + pub(crate) name: &'static CStr, +} + +soc_ids! { + MSM8260, + MSM8660, + APQ8060, + MSM8960, + APQ8064, + MSM8930, + MSM8630, + MSM8230, + APQ8030, + MSM8627, + MSM8227, + MSM8660A, + MSM8260A, + APQ8060A, + MSM8974, + MSM8225, + MSM8625, + MPQ8064, + MSM8960AB, + APQ8060AB, + MSM8260AB, + MSM8660AB, + MSM8930AA, + MSM8630AA, + MSM8230AA, + MSM8626, + MSM8610, + APQ8064AB, + MSM8930AB, + MSM8630AB, + MSM8230AB, + APQ8030AB, + MSM8226, + MSM8526, + APQ8030AA, + MSM8110, + MSM8210, + MSM8810, + MSM8212, + MSM8612, + MSM8112, + MSM8125, + MSM8225Q, + MSM8625Q, + MSM8125Q, + APQ8064AA, + APQ8084, + MSM8130, + MSM8130AA, + MSM8130AB, + MSM8627AA, + MSM8227AA, + APQ8074, + MSM8274, + MSM8674, + MDM9635, + (MSM8974PRO_AC, "MSM8974PRO-AC"), + MSM8126, + APQ8026, + MSM8926, + IPQ8062, + IPQ8064, + IPQ8066, + IPQ8068, + MSM8326, + MSM8916, + MSM8994, + (APQ8074PRO_AA, "APQ8074PRO-AA"), + (APQ8074PRO_AB, "APQ8074PRO-AB"), + (APQ8074PRO_AC, "APQ8074PRO-AC"), + (MSM8274PRO_AA, "MSM8274PRO-AA"), + (MSM8274PRO_AB, "MSM8274PRO-AB"), + (MSM8274PRO_AC, "MSM8274PRO-AC"), + (MSM8674PRO_AA, "MSM8674PRO-AA"), + (MSM8674PRO_AB, "MSM8674PRO-AB"), + (MSM8674PRO_AC, "MSM8674PRO-AC"), + (MSM8974PRO_AA, "MSM8974PRO-AA"), + (MSM8974PRO_AB, "MSM8974PRO-AB"), + APQ8028, + MSM8128, + MSM8228, + MSM8528, + MSM8628, + MSM8928, + MSM8510, + MSM8512, + MSM8936, + MDM9640, + MSM8939, + APQ8036, + APQ8039, + MSM8236, + MSM8636, + MSM8909, + MSM8996, + APQ8016, + MSM8216, + MSM8116, + MSM8616, + MSM8992, + APQ8092, + APQ8094, + MSM8209, + MSM8208, + MDM9209, + MDM9309, + MDM9609, + MSM8239, + MSM8952, + APQ8009, + MSM8956, + MSM8929, + MSM8629, + MSM8229, + APQ8029, + APQ8056, + MSM8609, + APQ8076, + MSM8976, + IPQ8065, + IPQ8069, + MDM9650, + MDM9655, + MDM9250, + MDM9255, + MDM9350, + APQ8052, + MDM9607, + APQ8096, + MSM8998, + MSM8953, + MSM8937, + APQ8037, + MDM8207, + MDM9207, + MDM9307, + MDM9628, + MSM8909W, + APQ8009W, + MSM8996L, + MSM8917, + APQ8053, + MSM8996SG, + APQ8017, + MSM8217, + MSM8617, + MSM8996AU, + APQ8096AU, + APQ8096SG, + MSM8940, + SDX201, + SDM660, + SDM630, + APQ8098, + MSM8920, + SDM845, + MDM9206, + IPQ8074, + SDA660, + SDM658, + SDA658, + SDA630, + MSM8905, + SDX202, + SDM670, + SDM450, + SM8150, + SDA845, + IPQ8072, + IPQ8076, + IPQ8078, + SDM636, + SDA636, + SDM632, + SDA632, + SDA450, + SDM439, + SDM429, + SM8250, + SA8155, + SDA439, + SDA429, + SM7150, + SM7150P, + IPQ8070, + IPQ8071, + QM215, + IPQ8072A, + IPQ8074A, + IPQ8076A, + IPQ8078A, + SM6125, + IPQ8070A, + IPQ8071A, + IPQ8172, + IPQ8173, + IPQ8174, + IPQ6018, + IPQ6028, + SDM429W, + SM4250, + IPQ6000, + IPQ6010, + SC7180, + SM6350, + QCM2150, + SDA429W, + SM8350, + QCM2290, + SM7125, + SM6115, + IPQ5010, + IPQ5018, + IPQ5028, + SC8280XP, + IPQ6005, + QRB5165, + SM8450, + SM7225, + SA8295P, + SA8540P, + QCM4290, + QCS4290, + SM7325, + (SM8450_2, "SM8450"), + (SM8450_3, "SM8450"), + SC7280, + SC7180P, + QCM6490, + QCS6490, + SM7325P, + IPQ5000, + IPQ0509, + IPQ0518, + SM6375, + IPQ9514, + IPQ9550, + IPQ9554, + IPQ9570, + IPQ9574, + SM8550, + IPQ5016, + IPQ9510, + QRB4210, + QRB2210, + SAR2130P, + SM8475, + SM8475P, + SA8255P, + SA8775P, + QRU1000, + SM8475_2, + QDU1000, + X1E80100, + SM8650, + SM4450, + SAR1130P, + QDU1010, + QRU1032, + QRU1052, + QRU1062, + IPQ5332, + IPQ5322, + IPQ5312, + IPQ5302, + QCS8550, + QCM8550, + SM8750, + IPQ5300, + SM7635, + SM6650, + SM6650P, + IPQ5321, + IPQ5424, + QCM6690, + QCS6690, + SM8850, + IPQ5404, + QCS9100, + QCS8300, + QCS8275, + QCS9075, + QCS615, +} + +pub(crate) const PMIC_MODELS: &[Option<&str>] =3D &sparse_array! { + 0: "Unknown PMIC model", + 1: "PM8941", + 2: "PM8841", + 3: "PM8019", + 4: "PM8226", + 5: "PM8110", + 6: "PMA8084", + 7: "PMI8962", + 8: "PMD9635", + 9: "PM8994", + 10: "PMI8994", + 11: "PM8916", + 12: "PM8004", + 13: "PM8909/PM8058", + 14: "PM8028", + 15: "PM8901", + 16: "PM8950/PM8027", + 17: "PMI8950/ISL9519", + 18: "PMK8001/PM8921", + 19: "PMI8996/PM8018", + 20: "PM8998/PM8015", + 21: "PMI8998/PM8014", + 22: "PM8821", + 23: "PM8038", + 24: "PM8005/PM8922", + 25: "PM8917/PM8937", + 26: "PM660L", + 27: "PM660", + 30: "PM8150", + 31: "PM8150L", + 32: "PM8150B", + 33: "PMK8002", + 36: "PM8009", + 37: "PMI632", + 38: "PM8150C", + 40: "PM6150", + 41: "SMB2351", + 44: "PM8008", + 45: "PM6125", + 46: "PM7250B", + 47: "PMK8350", + 48: "PM8350", + 49: "PM8350C", + 50: "PM8350B", + 51: "PMR735A", + 52: "PMR735B", + 54: "PM6350", + 55: "PM4125", + 58: "PM8450", + 65: "PM8010", + 69: "PM8550VS", + 70: "PM8550VE", + 71: "PM8550B", + 72: "PMR735D", + 73: "PM8550", + 74: "PMK8550", + 78: "PMM8650AU", + 79: "PMM8650AU_PSAIL", + 80: "PM7550", + 82: "PMC8380", + 83: "SMB2360", + 91: "PMIV0108" +}; + +pub(crate) const IMAGE_NAMES: &[&CStr] =3D &[ + c"boot", + c"tz", + c"tzsecapp", + c"rpm", + c"sdi", + c"hyp", + c"adsp1", + c"adsp2", + c"cdsp2", + c"appsbl", + c"apps", + c"mpss", + c"adsp", + c"cnss", + c"video", + c"dsps", + c"cdsp", + c"npu", + c"wpss", + c"cdsp1", + c"gpdsp", + c"gpdsp1", + c"sensorpd", + c"audiopd", + c"oempd", + c"chargerpd", + c"oispd", + c"soccp", + c"tme", + c"gearvm", + c"uefi", + c"cdsp3", + c"audiopd", + c"audiopd", + c"dcp", + c"oobs", + c"oobns", + c"devcfg", + c"btpd", + c"qecp", +]; diff --git a/drivers/soc/qcom/socinfo/socinfo.rs b/drivers/soc/qcom/socinfo= /socinfo.rs new file mode 100644 index 0000000000000000000000000000000000000000..c0791b33232eed9aef01c4db9e2= 031961fca783f --- /dev/null +++ b/drivers/soc/qcom/socinfo/socinfo.rs @@ -0,0 +1,446 @@ +// SPDX-License-Identifier: GPL-2.0 + +// Copyright (C) 2025 Google LLC. + +//! socinfo driver for Qualcomm SoCs. + +use core::fmt::{ + self, + Formatter, // +}; + +use kernel::{ + auxiliary, + c_str, + debugfs::{ + Scope, + ScopedDir, // + }, + device::{ + Bound, + Core, + Device, // + }, + devres::Devres, + error, + io::{ + Io, + Mmio, // + }, + module_auxiliary_driver, + pr_warn, + prelude::*, + soc, + str::{ + CStr, + CStrExt, + CString, // + }, + transmute::AsBytes, + try_pin_init, // +}; +use pin_init::pin_init_scope; + +mod bindings; +mod data; + +use bindings::*; +use data::{ + IMAGE_NAMES, + PMIC_MODELS, + SOC_IDS, // +}; + +module_auxiliary_driver! { + type: QcomSocInfo, + name: "qcom-socinfo", + authors: ["Matthew Maurer"], + description: "Qualcomm SoCinfo driver", + license: "GPL", + alias: ["platform:qcom-socinfo"], +} + +#[pin_data] +struct QcomSocInfo { + #[pin] + registration: soc::Registration, + #[pin] + params: Devres>, +} + +fn pmic_name(model: u32) -> Option<&'static str> { + let idx =3D SocInfo::version_split(model).1 as usize; + PMIC_MODELS.get(idx).copied().flatten() +} + +fn fmt_pmic_model(model: &u32, f: &mut Formatter<'_>) -> fmt::Result { + if let Some(model) =3D pmic_name(*model) { + writeln!(f, "{model}") + } else { + writeln!(f, "unknown ({})", SocInfo::version_split(*model).1) + } +} + +fn fmt_pmic_die_rev(rev: &u32, f: &mut Formatter<'_>) -> fmt::Result { + let (major, minor) =3D SocInfo::version_split(*rev); + writeln!(f, "{major}.{minor}") +} + +fn fmt_pmic_model_array(array: &KVec, f: &mut Formatter<'_>) ->= fmt::Result { + for pmic_entry in array { + let (die_rev_major, die_rev_minor) =3D + SocInfo::version_split(u32::from_le(pmic_entry.die_rev)); + if let Some(model) =3D pmic_name(pmic_entry.model) { + writeln!(f, "{model} {die_rev_major}.{die_rev_minor}")? + } else { + writeln!(f, "unknown ({})", pmic_entry.model)? + } + } + Ok(()) +} + +#[derive(Default)] +struct Params { + info_fmt: u32, + build_id: [u8; 32], + raw_version: Option, + hardware_platform: Option, + platform_version: Option, + accessory_chip: Option, + hardware_platform_subtype: Option, + pmic_model: Option, + pmic_die_rev: Option, + foundry_id: Option, + pmic_model_array: Option>, + chip_family: Option, + raw_device_family: Option, + raw_device_number: Option, + nproduct_id: Option, + chip_id: Option<[u8; 32]>, + num_clusters: Option, + ncluster_array_offset: Option, + num_subset_parts: Option, + nsubset_parts_array_offset: Option, + nmodem_supported: Option, + feature_code: Option, + pcode: Option, + oem_variant: Option, + boot_core: Option, + boot_cluster: Option, + num_func_clusters: Option, + raw_package_type: Option, + versions: KVec, +} + +struct SocInfo { + soc_info: socinfo, + soc_info_mem: Smem, + version_mem: Smem, + version_mem2: Option, +} + +impl SocInfo { + fn from_mem( + soc_info_mem: Smem, + version_mem: Smem, + version_mem2: Option, + dev: &Device, + ) -> Result { + Ok(Self { + soc_info: socinfo_from_partial_bytes( + soc_info_mem.access(dev).ok_or(error::code::EINVAL)?, + )?, + soc_info_mem, + version_mem, + version_mem2, + }) + } + fn id(&self) -> u32 { + u32::from_le(self.soc_info.id) + } + fn version_split(ver: u32) -> (u16, u16) { + let major =3D (ver >> 16) as u16; + let minor =3D (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.serial_num) + } + fn machine(&self) -> Result> { + for soc in SOC_IDS { + if soc.id =3D=3D self.id() { + return Ok(Some(soc.name.to_cstring()?)); + } + } + Ok(None) + } + fn soc_attributes(&self) -> Result { + Ok(soc::Attributes { + 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.seri= al()))?), + 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 ),* }= } ),* ] } =3D> {$( + if $params.info_fmt >=3D SocInfo::version_fuse($major, $minor) { + $( $params.$dst =3D Some(u32::from_le($self.soc_info.$src).int= o()) );* + } + )*} +} + +impl SocInfo { + fn build_params(self, dev: &Device) -> Result { + let mut params =3D Params { + build_id: self.soc_info.build_id, + info_fmt: u32::from_le(self.soc_info.fmt), + ..Default::default() + }; + 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 + }}, + {0, 20, { raw_package_type: raw_package_type }} + ]}; + if params.info_fmt >=3D SocInfo::version_fuse(0, 11) { + let offset =3D u32::from_le(self.soc_info.pmic_array_offset) a= s usize; + let num_pmics =3D u32::from_le(self.soc_info.num_pmics) as usi= ze; + let mut pmic_model_array =3D + KVec::from_elem(PmicEntry::default(), num_pmics, GFP_KERNE= L)?; + self.soc_info_mem + .access(dev) + .ok_or(error::code::EINVAL)? + .try_copy_to(pmic_model_array.as_bytes_mut(), offset)?; + params.pmic_model_array =3D Some(pmic_model_array); + } + if params.info_fmt >=3D SocInfo::version_fuse(0, 13) { + params.chip_id =3D Some(self.soc_info.chip_id); + } + load_versions(&mut params.versions, &self.version_mem)?; + if let Some(versions) =3D self.version_mem2.as_ref() { + load_versions(&mut params.versions, versions)?; + } + Ok(params) + } +} + +fn load_versions(versions: &mut KVec, mem: &Smem) -> Result<()> { + const IMAGE_SIZE: usize =3D core::mem::size_of::(); + for offset in (0..mem.maxsize()).step_by(IMAGE_SIZE) { + if let Some(subrange) =3D mem.subrange(offset, IMAGE_SIZE) { + versions.push(subrange, GFP_KERNEL)?; + } + } + Ok(()) +} + +macro_rules! value_attrs { + ($builder:ident, $params:ident, @) =3D> {}; + ($builder:ident, $params:ident, @ $s:ident $($rest:tt)*) =3D> { + if let Some(v) =3D $params.$s.as_ref() { + $builder.read_only_file(c_str!(stringify!($s)), v); + } + value_attrs!($builder, $params, @ $($rest)*) + }; + ($builder:ident, $params:ident, @ {$s:ident, $cb:expr} $($rest:tt)*) = =3D> { + if let Some(v) =3D $params.$s.as_ref() { + $builder.read_callback_file(c_str!(stringify!($s)), v, $cb); + } + value_attrs!($builder, $params, @ $($rest)*) + }; + ($builder:ident, $params:ident, {$($items:tt),*}) =3D> { + value_attrs!($builder, $params, @ $($items)*) + }; +} + +fn no_quirk(buf: &[u8; SIZE], f: &mut Formatter<'_>) ->= fmt::Result { + if buf[0] =3D=3D 0 { + writeln!(f) + } else { + nul_array(buf, f) + } +} + +fn nul_array(buf: &[u8; SIZE], f: &mut Formatter<'_>) -= > fmt::Result { + if let Some(end) =3D buf.iter().position(|x| *x =3D=3D 0) { + if end =3D=3D 0 { + // Match original driver quirk - empty strings don't have a tr= ailing newline + return Ok(()); + } + let Ok(c_str) =3D CStr::from_bytes_with_nul(&buf[0..=3Dend]) else { + pr_warn!("Creating CStr from bytes with known first NUL failed= ?"); + return Ok(()); + }; + let Ok(str) =3D c_str.to_str() else { + pr_warn!("Non-unicode-compatible character in string"); + return Ok(()); + }; + writeln!(f, "{str}") + } else { + writeln!(f, "Missing NUL: {buf:?}") + } +} + +fn build_image_debugfs<'a>(dir: &ScopedDir<'a, '_>, image_name: &CStr, mem= : &'a Mmio) { + let subdir =3D dir.dir(image_name); + subdir.read_callback_file(c_str!("name"), mem, &debug_name); + subdir.read_callback_file(c_str!("variant"), mem, &debug_variant); + subdir.read_callback_file(c_str!("oem"), mem, &debug_oem); +} + +fn debug_name(mem: &Mmio, f: &mut Formatter<'_>) -> fmt::Result { + let mut iv =3D ImageVersion::default(); + mem.try_copy_to(iv.as_bytes_mut(), 0) + .map_err(|_| fmt::Error)?; + nul_array(&iv.name, f) +} + +fn debug_variant(mem: &Mmio, f: &mut Formatter<'_>) -> fmt::Result { + let mut iv =3D ImageVersion::default(); + mem.try_copy_to(iv.as_bytes_mut(), 0) + .map_err(|_| fmt::Error)?; + nul_array(&iv.variant, f) +} + +fn debug_oem(mem: &Mmio, f: &mut Formatter<'_>) -> fmt::Result { + let mut iv =3D ImageVersion::default(); + mem.try_copy_to(iv.as_bytes_mut(), 0) + .map_err(|_| fmt::Error)?; + nul_array(&iv.oem, f) +} + +fn hex(x: &u32, f: &mut Formatter<'_>) -> fmt::Result { + writeln!(f, "{x:#010x}") +} + +impl Params { + fn build_debugfs<'data>(&'data self, dev: &'data Device, dir: &= ScopedDir<'data, '_>) { + dir.read_callback_file(c_str!("info_fmt"), &self.info_fmt, &hex); + dir.read_callback_file(c_str!("build_id"), &self.build_id, &no_qui= rk); + value_attrs!(dir, self, { + raw_version, + hardware_platform, + platform_version, + accessory_chip, + hardware_platform_subtype, + {raw_device_number, &hex}, + {raw_device_family, &hex}, + {chip_family, &hex}, + {chip_id, &nul_array}, + nproduct_id, + nsubset_parts_array_offset, + num_subset_parts, + ncluster_array_offset, + num_clusters, + nmodem_supported, + pcode, + feature_code, + oem_variant, + boot_core, + boot_cluster, + num_func_clusters, + foundry_id, + raw_package_type, + {pmic_model, &fmt_pmic_model}, + {pmic_die_rev, &fmt_pmic_die_rev}, + {pmic_model_array, &fmt_pmic_model_array} + }); + for (version, name) in self.versions.iter().zip(IMAGE_NAMES.iter()= ) { + if let Some(version_mem) =3D version.access(dev) { + build_image_debugfs(dir, name, version_mem); + } + } + } +} + +kernel::auxiliary_device_table! { + AUX_TABLE, + MODULE_AUX_TABLE, + ::IdInfo, + [(auxiliary::DeviceId::new(c_str!("smem"), c_str!("qcom-socinfo")), ()= )] +} + +impl auxiliary::Driver for QcomSocInfo { + type IdInfo =3D (); + const ID_TABLE: auxiliary::IdTable =3D &AUX_TABLE; + fn probe(dev: &auxiliary::Device, _id_info: &Self::IdInfo) -> im= pl PinInit { + pin_init_scope(move || { + let soc_info_mem =3D Smem::get( + dev, + kernel::bindings::QCOM_SMEM_HOST_ANY, + kernel::bindings::SMEM_HW_SW_BUILD_ID, + )?; + let version_mem =3D Smem::get( + dev, + kernel::bindings::QCOM_SMEM_HOST_ANY, + bindings::SMEM_IMAGE_VERSION_TABLE, + )?; + let version_mem2 =3D Smem::get( + dev, + kernel::bindings::QCOM_SMEM_HOST_ANY, + bindings::SMEM_IMAGE_VERSION_TABLE_2, + ) + .ok(); + let base_dev =3D dev.as_ref(); + let mem =3D soc_info_mem.access(base_dev).ok_or(error::code::E= INVAL)?; + + rand_from_mmio(mem)?; + + let info =3D SocInfo::from_mem(soc_info_mem, version_mem, vers= ion_mem2, base_dev)?; + let attributes =3D info.soc_attributes()?; + let backing =3D info.build_params(base_dev)?; + + Ok(try_pin_init!(Self { + registration <- soc::Registration::new(attributes), + params <- Devres::dir(base_dev, backing, c_str!("qcom_soci= nfo"), + Params::build_debugfs), + }? Error)) + }) + } +} + +fn rand_from_mmio(mmio: &Mmio) -> Result<()> { + let mut buf: KVec =3D KVec::from_elem(0, mmio.maxsize(), GFP_KERNE= L)?; + mmio.try_copy_to(&mut buf, 0)?; + kernel::random::add_device_randomness(&buf); + Ok(()) +} diff --git a/include/linux/soc/qcom/smem.h b/include/linux/soc/qcom/smem.h index f946e3beca215548ac56dbf779138d05479712f5..1c26f258be1fc1bf34bf3b0112c= 4a8472e676ed8 100644 --- a/include/linux/soc/qcom/smem.h +++ b/include/linux/soc/qcom/smem.h @@ -4,8 +4,12 @@ =20 #define QCOM_SMEM_HOST_ANY -1 =20 +struct auxiliary_device; + bool qcom_smem_is_available(void); int qcom_smem_alloc(unsigned host, unsigned item, size_t size); +void *qcom_smem_get_aux(struct auxiliary_device *aux, unsigned int host, + unsigned int item, size_t *size); void *qcom_smem_get(unsigned host, unsigned item, size_t *size); =20 int qcom_smem_get_free_space(unsigned host); diff --git a/rust/bindgen_parameters b/rust/bindgen_parameters index d56343ca03979e345f8adb7eb8fd7f2b9d4be6ee..3398a8eff517b71c062fd3e52a4= a7895526f64a1 100644 --- a/rust/bindgen_parameters +++ b/rust/bindgen_parameters @@ -72,3 +72,4 @@ # We can't auto-derive AsBytes, as we need a const-time check to see if th= ere # is padding involved. Add it explicitly when you expect no padding. --with-derive-custom-struct cpumask=3DAsBytesFfi +--with-derive-custom-struct socinfo=3DAsBytesFfi diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helpe= r.h index 9fdf76ca630e00715503e2a3a809bedc895697fd..b076b847731d97cf345d8ef80df= 9c315a79c8fab 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -95,6 +95,12 @@ */ #include <../../drivers/base/base.h> =20 +#if IS_ENABLED(CONFIG_QCOM_SOCINFO) +#include +#include +#include +#endif + #if defined(CONFIG_DRM_PANIC_SCREEN_QR_CODE) // Used by `#[export]` in `drivers/gpu/drm/drm_panic_qr.rs`. #include --=20 2.53.0.rc2.204.g2597b5adb4-goog