From nobody Tue Apr 7 09:10:40 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A3ABD3DFC86; Fri, 13 Mar 2026 19:03:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773428608; cv=none; b=SC5urzWvENNY2xFXb9fNGEmmQp0K67zncLUzMgjFPz46dRJQ3z33aPjdmVS6qGO+47VE8BxgW4JtLOhG1mEbz76VBpAR9HlXaSkwrJt1Tn6bShW6Tiu8V/B+wU9oHh3Y3+bQzZF6sxEc52n7FEPElVY2XcxEOYiYkDyWP8N6clE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773428608; c=relaxed/simple; bh=GGL+Ge1RluZCju5B3hATUukSaxdXBcAlUPKwu9Gx+8E=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=PfE6kDMNmIMyzxQWQTTI1LHONpc0QXs59mNpc6s8TeNXbbH3dPn+wsCQrRj/4SnMPQ15LLKLGSQk0Bm3PRCvfHF3bKEiKYzCf/0LEmzp6YyNbKrlbp/k3Fv4uAUNIqb/cRnhmjmCuT2krx0LVhTWcS7UU2mjvQIRVWvEBDgtV3A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ml8zml+G; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ml8zml+G" Received: by smtp.kernel.org (Postfix) with ESMTPS id 2DD38C19425; Fri, 13 Mar 2026 19:03:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773428608; bh=GGL+Ge1RluZCju5B3hATUukSaxdXBcAlUPKwu9Gx+8E=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=ml8zml+G6gjTC5/LKMO27/JNzdpp9GdkHBSxF37vNRhgIdu1nz3QdLC6AQtuT6TIg J/tGcgFpFQiex2DxlpzCv7vVnsgE0EDuVBWqZQ+7C6yUNcBy05rvY6zeqRU0E5m/DV i66cPvncqpicjoKr1ozD+nupq849OrJNKdu7IyZsOztsHuj9xnisc64YdEC9T85nhI 6bWrjdWpKLLbyJOZr+ecx9XmhedOeHDNTP9PzCzvy+7S74HQtldnF9dG6N4IoQa4so u0rpa1u1SuQo4+gKv3YBNUYm8nihr/MKFBBxYy/fmIb/uY53+Lq52+gAJPam/5IdoL lIwk+Raa8GsGA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1B520107BCD0; Fri, 13 Mar 2026 19:03:28 +0000 (UTC) From: Markus Probst via B4 Relay Date: Fri, 13 Mar 2026 20:03:05 +0100 Subject: [PATCH v3 1/7] rust: Add `parent_unchecked` function to `Device` Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260313-synology_microp_initial-v3-1-ad6ac463a201@posteo.de> References: <20260313-synology_microp_initial-v3-0-ad6ac463a201@posteo.de> In-Reply-To: <20260313-synology_microp_initial-v3-0-ad6ac463a201@posteo.de> To: Lee Jones , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Greg Kroah-Hartman , Miguel Ojeda , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , "Rafael J. Wysocki" , Igor Korotin , Daniel Almeida , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= , Pavel Machek , Len Brown , Robert Moore Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, driver-core@lists.linux.dev, linux-pci@vger.kernel.org, linux-leds@vger.kernel.org, linux-acpi@vger.kernel.org, acpica-devel@lists.linux.dev, Markus Probst X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=2195; i=markus.probst@posteo.de; h=from:subject:message-id; bh=HETHM3CRJWMhkQNDAYTp+649XpdPAf3ubTc2qfzj0Cs=; b=owEBiAJ3/ZANAwAIATR2H/jnrUPSAcsmYgBptF9xtg7fm3QCPAN84bfAyXYLoytkYJX0Zk1Hy ocxzpV75O+JAk4EAAEIADkWIQSCdBjE9KxY53IwxHM0dh/4561D0gUCabRfcRsUgAAAAAAEAA5t YW51MiwyLjUrMS4xMSwyLDIACgkQNHYf+OetQ9KYOw/3QgAiL7JIEEzv95AJctnhTBiyqFlBvmt 2rYNF7VZNwNIed5G49vPESuPgVmNr8Z/SKmK0QDdCrgbdBcGQ232hAi3TZA5+z50m5hZF9MzUfX FJsJIqKyynUuiiViozr4rBz1j/OfxU+le1/EvUc3IByZmJyPKfBWlQPBo4UKNZXTVeP7bVP1OQC c7UW5Ws0APSe807FqjLTv2H2KyaKod6o/PwtK8xHp3NpCF/3dLcUlL2GNAvk28tw8Sy5dqOTbay 7OAEZsnYWgVyx9IPv4psnSXNA1naehGefhF/YGSd2eptg9XBYex2+rSPWvkdDy9tn4OM0YDX/3b eQFXWugSsZ7H5D32NOVC3b+S6TVFpfiyozUnPWVT5XGnDiY92+FUn5d8flLyF5OfOqXXtVyi7t2 zhfHnz4w5VUybSv914BmvPsDhGFJgBp9UiZKXQYY+xLPonzOiWNlGq5daufj3u7tvBI5nGUJCLl 2KAAlo59pXQt3yYBomdV0cGNXb9gWP8T8Aeiu1NC/7KsTImCU+1g88pcyEGCRwRDvDQ1CodcFEy xlt0+ejIXt4gMnZVcdRma/+ybL6zuVQZ6NnTm1OpOsswdHLVU7osmsE8C/XgCoGp1lRd61kzgVm BWSIIESxX4PNUz1zTxKUwcSLLBF/tZtanQoc/8+gnPqAzJOcm7A== X-Developer-Key: i=markus.probst@posteo.de; a=openpgp; fpr=827418C4F4AC58E77230C47334761FF8E7AD43D2 X-Endpoint-Received: by B4 Relay for markus.probst@posteo.de/default with auth_id=680 X-Original-From: Markus Probst Reply-To: markus.probst@posteo.de From: Markus Probst This allows mfd sub-devices to access the bus device of their parent. The existing safe `parent` function has been made public for consistency. Signed-off-by: Markus Probst --- rust/kernel/device.rs | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/rust/kernel/device.rs b/rust/kernel/device.rs index 94e0548e7687..a53fb8a388e8 100644 --- a/rust/kernel/device.rs +++ b/rust/kernel/device.rs @@ -340,8 +340,7 @@ pub(crate) fn as_raw(&self) -> *mut bindings::device { } =20 /// Returns a reference to the parent device, if any. - #[cfg_attr(not(CONFIG_AUXILIARY_BUS), expect(dead_code))] - pub(crate) fn parent(&self) -> Option<&Device> { + pub fn parent(&self) -> Option<&Device> { // SAFETY: // - By the type invariant `self.as_raw()` is always valid. // - The parent device is only ever set at device creation. @@ -358,6 +357,28 @@ pub(crate) fn parent(&self) -> Option<&Device> { } } =20 + /// Returns a reference to the parent device as bus device. + /// + /// # Safety + /// + /// Callers must ensure that the device has a parent, that is containe= d in `T`. + pub unsafe fn parent_unchecked>(&self) -> &T { + // SAFETY: + // - By the type invariant `self.as_raw()` is always valid. + // - The parent device is only ever set at device creation. + let parent_raw =3D unsafe { (*self.as_raw()).parent }; + + // SAFETY: + // - The safety requirements guarantee that the device has a paren= t, thus `parent_raw` + // must be a pointer to a valid `struct device`. + // - `parent_raw` is valid for the lifetime of `self`, since a `st= ruct device` holds a + // reference count of its parent. + let parent =3D unsafe { Device::from_raw(parent_raw) }; + + // SAFETY: The safety requirements guarantee that the parent devic= e is contained in `T`. + unsafe { T::from_device(parent) } + } + /// Convert a raw C `struct device` pointer to a `&'a Device`. /// /// # Safety --=20 2.52.0 From nobody Tue Apr 7 09:10:40 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C75773E0228; Fri, 13 Mar 2026 19:03:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773428608; cv=none; b=ZbIwqPyoFQtKzWrLbu8yhl+4zhBk96xJaKcVIWz2gUC/ZOZX+ziNh/ni5sU7YIUaxyJ/D/svhw3nPXoxJ2ionS0oHrDt/E7VLKBZjeq9+aFx71qGN9gRLrUsRKZDaX4hwiZKfzOYq8bmZ1dg4Uep7prO0U3hU9Vn44L7SNj50/s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773428608; c=relaxed/simple; bh=AlpETrqRCdSTlEzY4ZYJxwPGCgmPKV6yiLLLpTONNWc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=pebDcC8kVMcGsK/esAhZhPr9kVeB0FdyJ8K9utzGWaXNF/NFubwFQhw1tghEct5//4yWMESyfqTNpcxokpcDfF59eNSmRPTI2R8uBMxaRXsxodsjw0dI5t1v/z0v/9p3ZvU+iNTX0MEj0xsbaNcix2VtPwmww/JpaVRrre2whf4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=L/pbdra2; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="L/pbdra2" Received: by smtp.kernel.org (Postfix) with ESMTPS id 395BFC2BC86; Fri, 13 Mar 2026 19:03:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773428608; bh=AlpETrqRCdSTlEzY4ZYJxwPGCgmPKV6yiLLLpTONNWc=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=L/pbdra2/SHny3jPvMR5mn62SZYdIHt72QCTSXSEm4XBUubDDF4BN9MPWxFJwp0MU dpAiWYeDx5IH+PRUhZYJSoZJWVR5tBtEqQmo8gELjIld+eQ8PBuMstIWiQCXw9h1QF j/GG/YPNlw7vhmsX3IiPXrqick0oiJqsbAzAVU43mnwvt0U+0/jQ0AHJpjLcKLYzxT NEqVvvkIz8xYWg10EGauZ6ihJsAy4waP+dDbD5k2Az3Lw9tPoHB+AUSuF4DOzgt3g+ eAC/dNUSXrDw7RkB3CCVt3rwEBWHZBlzu5epd6QuGcf2qRGclV9Nr28SiNjN06bAyI kGHlha1LJxHwg== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2AAFE107BCD7; Fri, 13 Mar 2026 19:03:28 +0000 (UTC) From: Markus Probst via B4 Relay Date: Fri, 13 Mar 2026 20:03:06 +0100 Subject: [PATCH v3 2/7] rust: add basic mfd abstractions Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260313-synology_microp_initial-v3-2-ad6ac463a201@posteo.de> References: <20260313-synology_microp_initial-v3-0-ad6ac463a201@posteo.de> In-Reply-To: <20260313-synology_microp_initial-v3-0-ad6ac463a201@posteo.de> To: Lee Jones , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Greg Kroah-Hartman , Miguel Ojeda , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , "Rafael J. Wysocki" , Igor Korotin , Daniel Almeida , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= , Pavel Machek , Len Brown , Robert Moore Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, driver-core@lists.linux.dev, linux-pci@vger.kernel.org, linux-leds@vger.kernel.org, linux-acpi@vger.kernel.org, acpica-devel@lists.linux.dev, Markus Probst X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=11227; i=markus.probst@posteo.de; h=from:subject:message-id; bh=ZJYERfpm0n00oI7yjkATxc2bgro8TlTIhPLy6Dly0cY=; b=owEBiQJ2/ZANAwAIATR2H/jnrUPSAcsmYgBptF9zrNeiJ0tRgQoSJcNbO14e0jlYP/jaFWJju I4P2fGImzCJAk8EAAEIADkWIQSCdBjE9KxY53IwxHM0dh/4561D0gUCabRfcxsUgAAAAAAEAA5t YW51MiwyLjUrMS4xMSwyLDIACgkQNHYf+OetQ9L+JQ//QYfpUWXxcV3wTaX3/5kvn1Eyhkd1hT7 mKG40Y7ioOAYLZ4qgrmScMXXQyMJUVWbuD4XMkfoGGntf6rHQ1QX/cpVMaXcdyYREzp7tt78ybQ uZicXLXmohsMVNRWJDMxmO/63NycSrtfMCMr8gu/5gDIH95KsvXCe7uJrptggQHxo2ZEqPqcEGf PeMOzfT4SSIwP67OikPQS5xJjA+7AmffJmr40JtXWR4gJPOWnalcgrDTMHSS2AZ/ac+u8W52tQN AybHeoUVAW5sKEZ4a7+3VGUSSn5azkmaejdfPYhxWeyCWlDcwYErImDqwajSph64DWOwCHNDCcq 6/2eAV2jKYKcjBlQxNfQDGBo7zrI4UBWsJbv6LP8hQfw9qNi4spR6pOk8R3EU+cGVNwRUUWDCck sEbFxItpjzI1B6oMeBxADL15eDlh3ULVFcQfqWmwUiSjQecodWUf2VHGOMT1UpBdhJmIe1byWaA OK/CSYIhQ9lngfAujisyAhS1auD2cmCzsMXnMq55igM0BxAmEvuH/nCvUgDbo18IoYiNP7diKVS qW2wcp9ELPmTgOPheeoR1lc+Sl31YInzk+z1qeaQMjSNESX8rnqpwr/1sHQqYisXiP39zqiu/6B UmL94ll1jsleQjm2V6QA+rNopg9F6U9/joL1GDIrJyKUtBpYEt0k= X-Developer-Key: i=markus.probst@posteo.de; a=openpgp; fpr=827418C4F4AC58E77230C47334761FF8E7AD43D2 X-Endpoint-Received: by B4 Relay for markus.probst@posteo.de/default with auth_id=680 X-Original-From: Markus Probst Reply-To: markus.probst@posteo.de From: Markus Probst Implement the basic mfd rust abstractions required to register mfd sub-devices, including: - `mfd::Cell` - a safe wrapper for `struct mfd_cell` - `mfd::CellAcpiMatch` - a safe wrapper for `struct mfd_cell_acpi_match` - `const MFD_CELLS: Option<&'static [mfd::Cell]>` in each bus device, except auxiliary The mfd sub-device registration will be done after a successful call to probe in each bus device, except auxiliary. This guarantees that `mfd_add_devices` will only be run at most once per device. It also ensures that the sub-devices will be probed after the drvdata of the device has been set. In order to register mfd sub-devices for a device, the driver needs to set `const MFD_CELLS` in their Driver trait implementation to Some. A build_assert guarantees that this can only be set to Some, if CONFIG_MFD_CORE is enabled. Signed-off-by: Markus Probst --- MAINTAINERS | 6 +++ rust/bindings/bindings_helper.h | 1 + rust/kernel/i2c.rs | 7 +++ rust/kernel/lib.rs | 1 + rust/kernel/mfd.rs | 114 ++++++++++++++++++++++++++++++++++++= ++++ rust/kernel/pci.rs | 7 +++ rust/kernel/platform.rs | 7 +++ rust/kernel/serdev.rs | 6 +++ rust/kernel/usb.rs | 7 +++ 9 files changed, 156 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 749d63ca18fa..fa49e40836ab 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -18082,6 +18082,12 @@ F: drivers/mfd/ F: include/dt-bindings/mfd/ F: include/linux/mfd/ =20 +MULTIFUNCTION DEVICES (MFD) [RUST] +M: Markus Probst +S: Maintained +T: git git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git +F: rust/kernel/mfd.rs + MULTIMEDIA CARD (MMC) ETC. OVER SPI S: Orphan F: drivers/mmc/host/mmc_spi.c diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helpe= r.h index f597fe3352f5..b7c17d1d9ece 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -65,6 +65,7 @@ #include #include #include +#include #include #include #include diff --git a/rust/kernel/i2c.rs b/rust/kernel/i2c.rs index bb5b830f48c3..e733b651d878 100644 --- a/rust/kernel/i2c.rs +++ b/rust/kernel/i2c.rs @@ -14,6 +14,7 @@ devres::Devres, driver, error::*, + mfd, of, prelude::*, types::{ @@ -167,6 +168,9 @@ extern "C" fn probe_callback(idev: *mut bindings::i2c_c= lient) -> kernel::ffi::c_ let data =3D T::probe(idev, info); =20 idev.as_ref().set_drvdata(data)?; + + idev.as_ref().mfd_add_devices(T::MFD_CELLS)?; + Ok(0) }) } @@ -328,6 +332,9 @@ pub trait Driver: Send { /// The table of ACPI device ids supported by the driver. const ACPI_ID_TABLE: Option> =3D None; =20 + /// The mfd cells for mfd devices. + const MFD_CELLS: Option<&'static [mfd::Cell]> =3D None; + /// I2C driver probe. /// /// Called when a new i2c client is added or discovered. diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 311fdf984b87..bacc54ca6aea 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -114,6 +114,7 @@ pub mod led; pub mod list; pub mod maple_tree; +pub mod mfd; pub mod miscdevice; pub mod mm; pub mod module_param; diff --git a/rust/kernel/mfd.rs b/rust/kernel/mfd.rs new file mode 100644 index 000000000000..6c47d9211bf2 --- /dev/null +++ b/rust/kernel/mfd.rs @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Abstractions for the mfd subsystem. +//! +//! C header: [`include/linux/mfd/core.h`](srctree/include/linux/mfd/core.= h) + +use core::{mem::MaybeUninit, ptr}; + +use crate::{ + device::{ + CoreInternal, + Device, // + }, + error::to_result, + prelude::*, // +}; + +/// A mfd cell. +/// +/// # Invariants +/// +/// A [`Cell`] instance represents a valid `struct mfd_cell`. +#[repr(transparent)] +pub struct Cell(bindings::mfd_cell); + +impl Cell { + /// Creates a new mfd cell. + pub const fn new(name: &'static CStr) -> Self { + Self(bindings::mfd_cell { + name: name.as_ptr().cast::(), + + // SAFETY: Always safe to call. + // This is the const equivalent to `bindings::mfd_cell::defaul= t()`. + ..unsafe { MaybeUninit::zeroed().assume_init() } + }) + } + + /// Sets `of_compatible` and optionally `of_reg` and `use_of_reg` on t= he mfd cell. + pub const fn of(self, compatible: &'static CStr, reg: Option) -> = Self { + Self(bindings::mfd_cell { + of_compatible: compatible.as_ptr().cast::(), + // TODO: Use `unwrap_or` once stabilized in const fn. + of_reg: if let Some(reg) =3D reg { reg } else { 0 }, + use_of_reg: reg.is_some(), + + ..self.0 + }) + } + + /// Sets `acpi_match` on the mfd cell. + pub const fn acpi(self, acpi_match: &'static CellAcpiMatch) -> Self { + Self(bindings::mfd_cell { + acpi_match: &raw const acpi_match.0, + + ..self.0 + }) + } +} + +/// A mfd cell acpi match entry. +/// +/// # Invariants +/// +/// A [`CellAcpiMatch`] instance represents a valid `struct mfd_cell_acpi_= match`. +#[repr(transparent)] +pub struct CellAcpiMatch(bindings::mfd_cell_acpi_match); + +impl CellAcpiMatch { + /// Creates a new mfd cell acpi match entry, using a ACPI PNP ID. + pub const fn pnpid(pnpid: &'static CStr) -> Self { + Self(bindings::mfd_cell_acpi_match { + pnpid: pnpid.as_ptr().cast::(), + adr: 0, + }) + } + + /// Creates a new mfd cell acpi match entry, using a ACPI ADR. + pub const fn adr(adr: u64) -> Self { + Self(bindings::mfd_cell_acpi_match { + pnpid: ptr::null(), + adr, + }) + } +} + +impl Device { + /// Registers child mfd devices. + // Always inline to optimize out error path of `build_assert`. + #[inline(always)] + pub(crate) fn mfd_add_devices(&self, cells: Option<&'static [Cell]>) -= > Result { + if let Some(cells) =3D cells { + build_assert!(cfg!(CONFIG_MFD_CORE)); + + // SAFETY: + // - `self.as_raw()` is guaranteed to be a pointer to a valid = `device`. + // - `cells.as_ptr()` is a guaranteed to be a pointer to a val= id `mfd_cell` array + // with the length of `cells.len()`. + to_result(unsafe { + bindings::devm_mfd_add_devices( + self.as_raw(), + bindings::PLATFORM_DEVID_AUTO, + // CAST: `Cell` is a transparent wrapper of `mfd_cell`. + cells.as_ptr().cast::(), + i32::try_from(cells.len())?, + ptr::null_mut(), + 0, + ptr::null_mut(), + ) + })?; + } + + Ok(()) + } +} diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs index af74ddff6114..6c4cf6cf970b 100644 --- a/rust/kernel/pci.rs +++ b/rust/kernel/pci.rs @@ -17,6 +17,7 @@ from_result, to_result, // }, + mfd, prelude::*, str::CStr, types::Opaque, @@ -116,6 +117,9 @@ extern "C" fn probe_callback( let data =3D T::probe(pdev, info); =20 pdev.as_ref().set_drvdata(data)?; + + pdev.as_ref().mfd_add_devices(T::MFD_CELLS)?; + Ok(0) }) } @@ -303,6 +307,9 @@ pub trait Driver: Send { /// The table of device ids supported by the driver. const ID_TABLE: IdTable; =20 + /// The mfd cells for mfd devices. + const MFD_CELLS: Option<&'static [mfd::Cell]> =3D None; + /// PCI driver probe. /// /// Called when a new pci device is added or discovered. Implementers = should diff --git a/rust/kernel/platform.rs b/rust/kernel/platform.rs index 8917d4ee499f..e2bcf8ef093c 100644 --- a/rust/kernel/platform.rs +++ b/rust/kernel/platform.rs @@ -25,6 +25,7 @@ self, IrqRequest, // }, + mfd, of, prelude::*, types::Opaque, @@ -104,6 +105,9 @@ extern "C" fn probe_callback(pdev: *mut bindings::platf= orm_device) -> kernel::ff let data =3D T::probe(pdev, info); =20 pdev.as_ref().set_drvdata(data)?; + + pdev.as_ref().mfd_add_devices(T::MFD_CELLS)?; + Ok(0) }) } @@ -218,6 +222,9 @@ pub trait Driver: Send { /// The table of ACPI device ids supported by the driver. const ACPI_ID_TABLE: Option> =3D None; =20 + /// The mfd cells for mfd devices. + const MFD_CELLS: Option<&'static [mfd::Cell]> =3D None; + /// Platform driver probe. /// /// Called when a new platform device is added or discovered. diff --git a/rust/kernel/serdev.rs b/rust/kernel/serdev.rs index d9fea4bd4439..6e702c734ded 100644 --- a/rust/kernel/serdev.rs +++ b/rust/kernel/serdev.rs @@ -14,6 +14,7 @@ to_result, VTABLE_DEFAULT_ERROR, // }, + mfd, of, prelude::*, sync::Completion, @@ -180,6 +181,8 @@ extern "C" fn probe_callback(sdev: *mut bindings::serde= v_device) -> kernel::ffi: =20 private_data.probe_complete.complete_all(); =20 + sdev.as_ref().mfd_add_devices(T::MFD_CELLS)?; + result.map(|()| 0) }) } @@ -339,6 +342,9 @@ pub trait Driver: Send { /// The table of ACPI device ids supported by the driver. const ACPI_ID_TABLE: Option> =3D None; =20 + /// The mfd cells for mfd devices. + const MFD_CELLS: Option<&'static [mfd::Cell]> =3D None; + /// Serial device bus device driver probe. /// /// Called when a new serial device bus device is added or discovered. diff --git a/rust/kernel/usb.rs b/rust/kernel/usb.rs index 0e1b9a88f4f1..a64ed6a530f1 100644 --- a/rust/kernel/usb.rs +++ b/rust/kernel/usb.rs @@ -17,6 +17,7 @@ from_result, to_result, // }, + mfd, prelude::*, types::{ AlwaysRefCounted, @@ -96,6 +97,9 @@ extern "C" fn probe_callback( =20 let dev: &device::Device =3D intf.as_ref= (); dev.set_drvdata(data)?; + + dev.mfd_add_devices(T::MFD_CELLS)?; + Ok(0) }) } @@ -309,6 +313,9 @@ pub trait Driver { /// The table of device ids supported by the driver. const ID_TABLE: IdTable; =20 + /// The mfd cells for mfd devices. + const MFD_CELLS: Option<&'static [mfd::Cell]> =3D None; + /// USB driver probe. /// /// Called when a new USB interface is bound to this driver. --=20 2.52.0 From nobody Tue Apr 7 09:10:40 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D8D6D3E022C; Fri, 13 Mar 2026 19:03:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773428609; cv=none; b=q6fTF1rBC+mgr2C4C7Ny027B6Cp1UQnej8d6tLVUG0HkbfYc6hzvw0diVBmMAzw5+6uieWGIHWaPHNxZC8xMDAWBRLO2JmlJhzh0I1FEL8XA0nwxN9s9zLQUvqiw73e8xRH6Agdv8KoBlmpqg6E78c6VYpRGp4AAjEezCQa6RKg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773428609; c=relaxed/simple; bh=WNyrV6cUJd1MCtALLHhcaw4UwpQ9xMid5GgH1ipI1uw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=jF5rl/XeHg3ANCzicet7zrfddVmgEOO6EaGubRcjVo5jYcP/HkLTfZi5cvMmRHK0PhyJFo4Hyf9YJTWWeIVReCt2DB4EoNbPKYphAhSYr/hKcXScyuibOGqPCfeAm2blrITU9ZJlMFZRgUTj60494GhiX8Bei9eYlt3H/It1gic= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=c9WEgRCQ; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="c9WEgRCQ" Received: by smtp.kernel.org (Postfix) with ESMTPS id 46122C4AF0C; Fri, 13 Mar 2026 19:03:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773428608; bh=WNyrV6cUJd1MCtALLHhcaw4UwpQ9xMid5GgH1ipI1uw=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=c9WEgRCQSq0ifZQWywjVc93Z4fYUZfib6INXYaPZOf4Pa07RWRBgAQo6rdA69IR3C /e0W74+8qD9M9iFkQf/OHGvTBDalTsAzS9MO1mzEuPQyzkv0lB7DsSukQ40E25mtcs 1vAjkr4SRdqEZRL6gHINzpxeMPyMIp4NbNizKPStf7kIc2DqxJt/TRv0udYzSdbjxR k+pdn0ihLfhq+uDFN0sMJ76X+bKTeuLDmAUECr8BRrbjtZwxNkaiWFVK7iAUGsBOGm iu9gdTHTLqnnTMlqlvShhYuC0rFEHRNDXLuaURofx+R+VN2obdUZ/xZ9YkNTqqBJvv mc5hYKW8XSocQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3B0F7107BCDD; Fri, 13 Mar 2026 19:03:28 +0000 (UTC) From: Markus Probst via B4 Relay Date: Fri, 13 Mar 2026 20:03:07 +0100 Subject: [PATCH v3 3/7] acpi: add acpi_of_match_device_ids Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260313-synology_microp_initial-v3-3-ad6ac463a201@posteo.de> References: <20260313-synology_microp_initial-v3-0-ad6ac463a201@posteo.de> In-Reply-To: <20260313-synology_microp_initial-v3-0-ad6ac463a201@posteo.de> To: Lee Jones , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Greg Kroah-Hartman , Miguel Ojeda , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , "Rafael J. Wysocki" , Igor Korotin , Daniel Almeida , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= , Pavel Machek , Len Brown , Robert Moore Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, driver-core@lists.linux.dev, linux-pci@vger.kernel.org, linux-leds@vger.kernel.org, linux-acpi@vger.kernel.org, acpica-devel@lists.linux.dev, Markus Probst X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=1613; i=markus.probst@posteo.de; h=from:subject:message-id; bh=GJ3md6hqtAxzfdBZYmqM+I2WL+pybDm9TmsuESz9lJ4=; b=owEBiQJ2/ZANAwAIATR2H/jnrUPSAcsmYgBptF913ngpPcMcdUQwBIgHq7F7VzFVgL/AY67jx svY0kKc3OKJAk8EAAEIADkWIQSCdBjE9KxY53IwxHM0dh/4561D0gUCabRfdRsUgAAAAAAEAA5t YW51MiwyLjUrMS4xMSwyLDIACgkQNHYf+OetQ9LkNg//bCn1Kd+N6ljQZDQEebMvChN3dphvi1c JNF9qbgFodbcU4BIFx7T8XQ8KXpBoORI0YxeXgRHUnqGbPpcyeCObRFd7ciSKCMpniWpzDuN1GE 55vld+kUH+kCJCAHxj3uD3aPxn8e7ewuDXqns8NaqWxPsDHE0mjkuKLtUoLdi0m8p0tCV1KNrF3 WWQWPtoa0MpaVlIz68xUxfpKkWcwXSKisntVCuHRB7fUGbkoBG6ewFPxai7OwVz58wYYF8qaMY0 KtM6BU6H2FBNZMZ4BXj/TkKtX9IXz2dhwacbiAXlICtp36ZFtDQDiqQdgKpbKg/U3A1bmDZoJev XWoeg+XwuLcI6BIRCSTnsWShSO8gZtCBSpjR8zIR96fADSNuSvNwze128AS4h2ApAf2a20w00FB JG983Sp8SXAezefYSb54K7tp3WJ7RSl9NXahg69vtzWSoLB9uU0p+0WlwJ9cF7mb3Xnkp34GgxJ fwN9IhRLjSZFFdF+9oXeNNdaob6iHiP4M1qZSFFK1cjV8vQ5t7Wpj/DGU+8EMKkN6/cOKdJZZd4 A5g32ESjeTedyxOxFIOi1oD39zEBZCd7fiIqYj4uxT8tCLsYslNbegGBON1a2xTChUUOxAZ1yG0 gtgcL/kW7JQ3IMZf4yAC3sOtDJwLqZ2CWL1uesYUXGav6f2WlaAI= X-Developer-Key: i=markus.probst@posteo.de; a=openpgp; fpr=827418C4F4AC58E77230C47334761FF8E7AD43D2 X-Endpoint-Received: by B4 Relay for markus.probst@posteo.de/default with auth_id=680 X-Original-From: Markus Probst Reply-To: markus.probst@posteo.de From: Markus Probst Add a function to match acpi devices against of_device_ids. This will be used in the following commit ("mfd: match acpi devices against PRP0001") to match mfd sub-devices against a of compatible string. Signed-off-by: Markus Probst --- drivers/acpi/bus.c | 7 +++++++ include/acpi/acpi_bus.h | 2 ++ 2 files changed, 9 insertions(+) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index f6707325f582..5ddcc56edc87 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -1044,6 +1044,13 @@ int acpi_match_device_ids(struct acpi_device *device, } EXPORT_SYMBOL(acpi_match_device_ids); =20 +int acpi_of_match_device_ids(struct acpi_device *device, + const struct of_device_id *ids) +{ + return __acpi_match_device(device, NULL, ids, NULL, NULL) ? 0 : -ENOENT; +} +EXPORT_SYMBOL(acpi_of_match_device_ids); + bool acpi_driver_match_device(struct device *dev, const struct device_driver *drv) { diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index aad1a95e6863..0081b9e4aaee 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -677,6 +677,8 @@ void acpi_bus_trim(struct acpi_device *start); acpi_status acpi_bus_get_ejd(acpi_handle handle, acpi_handle * ejd); int acpi_match_device_ids(struct acpi_device *device, const struct acpi_device_id *ids); +int acpi_of_match_device_ids(struct acpi_device *device, + const struct of_device_id *ids); void acpi_set_modalias(struct acpi_device *adev, const char *default_id, char *modalias, size_t len); =20 --=20 2.52.0 From nobody Tue Apr 7 09:10:40 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 36050337BA4; Fri, 13 Mar 2026 19:03:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773428609; cv=none; b=rBFiCHTpIgbNUiIxIyXbJiJY+oOCqzWXQHjUYGuu9yOM9979feIxYXIcKWawYmSyR3qG8fezzBHUF+zhALNcDutKywbiV84Qv/ICA4AMYGRLmiey7yC4m6FWYyPhUpRR+uvOmdBTojrGfZ+/Pra7hFgh55MPMSi+Tvc4UqoM10w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773428609; c=relaxed/simple; bh=Bksge0BwZIZRSlux7ElMK3YW88ScPyqClLpzxyD7WoM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=lo2oVGWQy610YMXM6uVZPiw4XkfkfeF4gRk26mgvnTDY5tZFu7x5ndCi4L4FrwzRe6ef6dGiulOmY1bIAkKQwkGrOwJ8uw2BFwm3Uzn+lJmjnXvL3nLP//500m+mt4UTJQlpwfqPs3JyvG8ONziCm7IC0G6KfDVsnSY3EqMihsg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=d3Fds5DX; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="d3Fds5DX" Received: by smtp.kernel.org (Postfix) with ESMTPS id 7A76AC2BCB5; Fri, 13 Mar 2026 19:03:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773428608; bh=Bksge0BwZIZRSlux7ElMK3YW88ScPyqClLpzxyD7WoM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=d3Fds5DXUU0RJrPsweowB8IsWH0+VPxuzLh4NyE/eo6X/HvFZlMvIGszvnbi+PifN ke1u40jr/eKQA5IpHCEZhIRd/x4YFKoZKuB/P2eGul4mTba2OKcp1HVnFQ486HAtBs 89w6UUA7EHKzujRT6gTqnguKhvx7wGoHDs+I5EgAm5Ph+nF7IrJZK0EK6lkYI9u7IS egJdhO/j8J4un38lIxcdSf/2RS/dHczDjf0O+StPsOs0zyeeyNVP/IRIVMZCQ+NWFq xVMJiKMajFyQ9uq4+a3/OBZENulU2vQDnM2Zj+L4BsHcD0Ajxrj3EyXLT3I8ERA8cK sOGHvTB3FbmaA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 71262107BCD0; Fri, 13 Mar 2026 19:03:28 +0000 (UTC) From: Markus Probst via B4 Relay Date: Fri, 13 Mar 2026 20:03:08 +0100 Subject: [PATCH v3 4/7] mfd: match acpi devices against PRP0001 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260313-synology_microp_initial-v3-4-ad6ac463a201@posteo.de> References: <20260313-synology_microp_initial-v3-0-ad6ac463a201@posteo.de> In-Reply-To: <20260313-synology_microp_initial-v3-0-ad6ac463a201@posteo.de> To: Lee Jones , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Greg Kroah-Hartman , Miguel Ojeda , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , "Rafael J. Wysocki" , Igor Korotin , Daniel Almeida , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= , Pavel Machek , Len Brown , Robert Moore Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, driver-core@lists.linux.dev, linux-pci@vger.kernel.org, linux-leds@vger.kernel.org, linux-acpi@vger.kernel.org, acpica-devel@lists.linux.dev, Markus Probst X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=2049; i=markus.probst@posteo.de; h=from:subject:message-id; bh=hBb7npui0bE9foF8ScZ10sjTmUwGIOBRFmkU8LUvBWM=; b=owEBiQJ2/ZANAwAIATR2H/jnrUPSAcsmYgBptF93eoVl4DjsVgQ72oaZooBCN5wvnCfEb4Bga W4Ay9kmUaiJAk8EAAEIADkWIQSCdBjE9KxY53IwxHM0dh/4561D0gUCabRfdxsUgAAAAAAEAA5t YW51MiwyLjUrMS4xMSwyLDIACgkQNHYf+OetQ9L3fhAAhjV2cdrYE2uf7iM0x/J1I4s8JWTDwfI xc+elomemxd+j6pR0OhuKw3DggNCb1dc8H6scm/wv+zqfc0xBKay+QT8Ff3XjZvcfV1U4R3Oyct eyEhtj30Es5qqTjIPLNA1R3NAU3H7lhnUTviHadma7MR00Va9hVUetjEmHx4YDlIepo5n1NNIfU XYlU+dEoRsJ0f74IAhjc0He6zdNLSlLzP7pde5aQLNMq1egTwt42unDrVA6N6Ds++Dzm3ufmCTx fcFTLqoTm9S+A0E+Iie9+3KsPkqsyDY79insqEc8Liv7iqCRtzPrE4GLHh3zYT6pXSMDf/t85Cg IvRUpVxq7plwWrYa7C/s17zVOPhv9NxYSsIldWuUZKqwzJ6Q8xS9HXLA8BCW3XY7OMU6+Qrudjp Qoq/uDrkEHNgAxFHJcxq/L+o89nhnf7dWy0kbljzJaFs4ahpWzmX+BCWp7NtPKfppwnUoTK16va AayxkUxyh1wVVjMwONb4gJImT9Db6YrEzenviJbys/YZpUwQibiBDgRqO0vEuNntLTzChNLekHd bwO+Ca+pBIF05iMu5dk+WfKPtFU8QnXMkSbn7rVm3rkCLGJgYqUz4kTbLWWkCO66okvXGyT20ul nZnHj0MwmDpnd7JKqoESSpaXvpiIAb85zKiiOJMc8kBZFfobEKLQ= X-Developer-Key: i=markus.probst@posteo.de; a=openpgp; fpr=827418C4F4AC58E77230C47334761FF8E7AD43D2 X-Endpoint-Received: by B4 Relay for markus.probst@posteo.de/default with auth_id=680 X-Original-From: Markus Probst Reply-To: markus.probst@posteo.de From: Markus Probst PRP0001 can be used to provide DT-compatible device identification in ACPI. If the mfd device is bound to a acpi fwnode and no acpi_match data is provided by the driver, match against PRP0001 and the provided `of_compatible` string. Signed-off-by: Markus Probst --- drivers/mfd/mfd-core.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index 6be58eb5a746..29bf54664acf 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c @@ -39,6 +39,10 @@ struct match_ids_walk_data { struct acpi_device_id *ids; struct acpi_device *adev; }; +struct match_of_ids_walk_data { + const struct of_device_id *ids; + struct acpi_device *adev; +}; =20 static int match_device_ids(struct acpi_device *adev, void *data) { @@ -52,10 +56,23 @@ static int match_device_ids(struct acpi_device *adev, v= oid *data) return 0; } =20 +static int match_of_device_ids(struct acpi_device *adev, void *data) +{ + struct match_of_ids_walk_data *wd =3D data; + + if (!acpi_of_match_device_ids(adev, wd->ids)) { + wd->adev =3D adev; + return 1; + } + + return 0; +} + static void mfd_acpi_add_device(const struct mfd_cell *cell, struct platform_device *pdev) { const struct mfd_cell_acpi_match *match =3D cell->acpi_match; + const char *of_compatible =3D cell->of_compatible; struct acpi_device *adev =3D NULL; struct acpi_device *parent; =20 @@ -86,6 +103,16 @@ static void mfd_acpi_add_device(const struct mfd_cell *= cell, } else { adev =3D acpi_find_child_device(parent, match->adr, false); } + } else if (of_compatible) { + struct of_device_id ids[2] =3D {}; + struct match_of_ids_walk_data wd =3D { + .adev =3D NULL, + .ids =3D ids, + }; + + strscpy(ids[0].compatible, of_compatible, sizeof(ids[0].compatible)); + acpi_dev_for_each_child(parent, match_of_device_ids, &wd); + adev =3D wd.adev; } =20 device_set_node(&pdev->dev, acpi_fwnode_handle(adev ?: parent)); --=20 2.52.0 From nobody Tue Apr 7 09:10:40 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2FB712DF12F; Fri, 13 Mar 2026 19:03:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773428609; cv=none; b=Eti2YmGyEVFKlhutBwZEmZszlp2I5/IJGEaleCuU99PJmep1ezAT9h+TliUQtjugqG0f/Ych0HuMhCEbp08+gXNnnzW3ZDPWu/Y98/SArBkybo+5mJssy4ME2AbocxcA6D7AA0aXzKPNdx4D5PJGIY7lIO4ccounc/m+1eouBkQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773428609; c=relaxed/simple; bh=Jx7UrUTas1KVn/N4PI1g4X8WSfQKM/+cArejjQk62XM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=URvK54FmBLhY5BlpIqQ6Tw2h9pS7zfOgFvEC/BR/NxGazJsE8POadZQqsck6lW+6iMUKIUi9mEin2YHPH3eCu9KsMdqZMkDN0azl4BIrFL7fqFbloiI5W0DUg1k2w79moVHzmBnOtjhR5ghjlhTLiwGa6Td+8XIml/cf3Ai4s2E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=hGoB1gTC; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="hGoB1gTC" Received: by smtp.kernel.org (Postfix) with ESMTPS id 8BE56C2BCB4; Fri, 13 Mar 2026 19:03:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773428608; bh=Jx7UrUTas1KVn/N4PI1g4X8WSfQKM/+cArejjQk62XM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=hGoB1gTCzNofnwtvKWS4UPRREqrNBAStY344sOOB2vOb0N46Rk5CguD9Iuy8d6X6x GQll9c+1BxFq97mTrp15I2NiSTnFEQ5FtwNqxT+TEnBigxFaCQqXSCJs2xBw6pMz0G ODLtZmU6S47bRHLus0q2VazCDEbPuJyceZWuLlP69e+KYFh0BCqP0PlmK051dHWFRG zdMNHioNSFfWJN9oqHW/DNdIDPkR5A7jBwuK1kqKP8P1zZ6MCS0y05ffhoAZX0Zvj4 7ibcUMDC4ehENvrMwCrTS3WCWxhb0iMn1L6t+SA/0Tn296sRmdsdPvXo41zoBOKT7L jOsYBVFHPfZBQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 824AE107BCDF; Fri, 13 Mar 2026 19:03:28 +0000 (UTC) From: Markus Probst via B4 Relay Date: Fri, 13 Mar 2026 20:03:09 +0100 Subject: [PATCH v3 5/7] dt-bindings: mfd: Add synology,microp device Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260313-synology_microp_initial-v3-5-ad6ac463a201@posteo.de> References: <20260313-synology_microp_initial-v3-0-ad6ac463a201@posteo.de> In-Reply-To: <20260313-synology_microp_initial-v3-0-ad6ac463a201@posteo.de> To: Lee Jones , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Greg Kroah-Hartman , Miguel Ojeda , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , "Rafael J. Wysocki" , Igor Korotin , Daniel Almeida , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= , Pavel Machek , Len Brown , Robert Moore Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, driver-core@lists.linux.dev, linux-pci@vger.kernel.org, linux-leds@vger.kernel.org, linux-acpi@vger.kernel.org, acpica-devel@lists.linux.dev, Markus Probst X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=3421; i=markus.probst@posteo.de; h=from:subject:message-id; bh=BWCjYQBHaSfDWg8Gx+1WSTdoVU+3MjA/rzyHsPChX7o=; b=owEBiQJ2/ZANAwAIATR2H/jnrUPSAcsmYgBptF95QKk57C5wGYpOrgF+665YuLzVFk9/o6152 RHv7L3t4L+JAk8EAAEIADkWIQSCdBjE9KxY53IwxHM0dh/4561D0gUCabRfeRsUgAAAAAAEAA5t YW51MiwyLjUrMS4xMSwyLDIACgkQNHYf+OetQ9LkWQ/+I5FvYw6cc5ThLEBTFpIlGUb3vXxj0s5 CMgyALXltBdsVCG2cfRtMB29vkjz+PvR6DyghJpfPk8T8gO6XZWmqEh4op9aX4e535Hz4UIEITw HMU2whDV/W88fVa9PFICGUOZPSqs44t5Mp3Hwb0OFeOyUdXZine/3B7uPy6X8zCzgj5aGklO8z9 olqCaoOR98NeWTlu+MP1jj6nPeG6scgII52M7pmsb2cSV3AX2sNmJPvq6f4nHE5t1F9ILwNDM70 VLBbMCsZeM75Lbq1bhGiHw78C+zeVv0Qov4JQuajcVwFSVVsa8zi9kEpP4ZhZo905JDuXvokEGI 7Ah3Vcu51/8I9yF0ettPL1L8WuRbuIrwSJoyNleb/lA+8TzdyWFMIxL+fUXfH8llWvnj8/S77CF Y/YmR2IFxAorinV8vwHyIhf4cCXp7KAu+Ia1MdM6ADMDVIvFHzgNQKKjZQ//iEX6B6vuzi0xrVo ad4DSpIcRrN8JlLB3gePGKehcoM5ahQHE4oF18ASh0kq7xsPRGL77wXnHzLAGz+WTUi4I+Q7UnZ Z5N4OKW6s5iKcD+Zyp65fNxkAg4wGHOaabS7sEaTjNxROsBlCWF9llL60oYal2Pqb2nMQWXC2ue LKVuxQ7jsuxM3+O9Oh3SSF7DNcqCzl3xkbEUt6VOe2GgyXZ3FtG4= X-Developer-Key: i=markus.probst@posteo.de; a=openpgp; fpr=827418C4F4AC58E77230C47334761FF8E7AD43D2 X-Endpoint-Received: by B4 Relay for markus.probst@posteo.de/default with auth_id=680 X-Original-From: Markus Probst Reply-To: markus.probst@posteo.de From: Markus Probst Add the Synology Microp devicetree bindings. Those devices are microcontrollers found on Synology NAS devices. They are connected to a serial port on the host device. Those devices are used to control certain LEDs, fan speeds, a beeper, to handle buttons, fan failures and to properly shutdown and reboot the device. Signed-off-by: Markus Probst --- .../devicetree/bindings/leds/synology,microp.yaml | 40 +++++++++++++++++ .../devicetree/bindings/mfd/synology,microp.yaml | 51 ++++++++++++++++++= ++++ 2 files changed, 91 insertions(+) diff --git a/Documentation/devicetree/bindings/leds/synology,microp.yaml b/= Documentation/devicetree/bindings/leds/synology,microp.yaml new file mode 100644 index 000000000000..f7bf32c240f7 --- /dev/null +++ b/Documentation/devicetree/bindings/leds/synology,microp.yaml @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/leds/synology,microp.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Synology NAS on-board Microcontroller LEDs + +maintainers: + - Markus Probst + +description: | + This is part of device tree bindings for Synology NAS on-board + Microcontroller. + + This device can manage up to 4 leds in Synology NAS devices: + - Power + - Status + - Alert + - USB + + The Power and Status LEDs are available on every Synology NAS model, + therefore the associated child nodes are mandatory. If the NAS also has + a alert or usb led, the associated child nodes need to be added. + +properties: + compatible: + const: synology,microp-leds + +patternProperties: + "^(power|status|alert|usb)-led$": + $ref: /schemas/leds/common.yaml + unevaluatedProperties: false + +required: + - compatible + - power-led + - status-led + +additionalProperties: false diff --git a/Documentation/devicetree/bindings/mfd/synology,microp.yaml b/D= ocumentation/devicetree/bindings/mfd/synology,microp.yaml new file mode 100644 index 000000000000..57bb986d24f7 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/synology,microp.yaml @@ -0,0 +1,51 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mfd/synology,microp.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Synology NAS on-board Microcontroller + +maintainers: + - Markus Probst + +description: | + Synology Microp is a microcontroller found in Synology NAS devices. + It is connected to a serial port on the host device. + + It is a multifunction device with the following sub modules: + - LEDs + +properties: + compatible: + const: synology,microp + + leds: + $ref: /schemas/leds/synology,microp.yaml + +required: + - compatible + +additionalProperties: false + +examples: + - | + #include + + mcu { + compatible =3D "synology,microp"; + + leds { + compatible =3D "synology,microp-leds"; + + power-led { + color =3D ; + function =3D LED_FUNCTION_POWER; + }; + + status-led { + color =3D ; + function =3D LED_FUNCTION_STATUS; + }; + }; + }; --=20 2.52.0 From nobody Tue Apr 7 09:10:40 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2FD4733509B; Fri, 13 Mar 2026 19:03:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773428609; cv=none; b=HVm4xo3JgfbnZmQbjJZ5uGOGs6fXVteu/O4DWRjCksF9fSIUOW6hPyHBENxzToRGu2Yv6ZzGlMGX5Ch9AgfbmcmJnKgGXL9pmIJntbiQ3XLEh4GdIpRP6+cP7YzayAnlrGWX5ub7uRkApGc8VjQuWfGDHMnVzFgiydDMp0ZUgPs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773428609; c=relaxed/simple; bh=e599/+9riorUGtuRfkF9HzcpRuZoJHcKGAJ9QlZI5I8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=nXpmJuekQZ/Y23pJdseybLApJWE0YGRFkV8ddQJ0jySXw0g1ic3CzesK9Gx1W5mdLxF+9s6vIzPVrXH7jLsn6NFReOjACAhbsGZsKjt+pqP2jjLvxiQySUHgLX+r0/7xa37KjWmYBZRW53lxvtqw27wAfXhM8NZrfgQ1dmuyzvY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=pvJLiRlV; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="pvJLiRlV" Received: by smtp.kernel.org (Postfix) with ESMTPS id 9D21AC2BCB6; Fri, 13 Mar 2026 19:03:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773428608; bh=e599/+9riorUGtuRfkF9HzcpRuZoJHcKGAJ9QlZI5I8=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=pvJLiRlVTW9gj4yNp19D00dm8OTYy0w6khpjKe122WpTkf8RqPCoBowhTmwWCdTOv sv4PKFUP3zo0RueVJcPzy3YeqvYpURal4NjR6Sny/XdWyxnk2qJuc09lpFVHbKD/dK 8kaVi276zEQIYnqSGmHcBVKEa161uWrEaCo8ObN/ACXevVXGzchAuPXZEKR5vEag0x IjqOVbGRGjIldUBxNKGFAbngT6tbwnBGPRpRVTU0LkAone7APgmxdlwU+pjh/UKd6n X2o+OI3tEmrHGJs40VECpZByH+5FYB0NytevZ66bnKcxY0pjZRoljm4a6ZM61r+v62 RFrgUNSqQVuFw== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 91AAA107BCD7; Fri, 13 Mar 2026 19:03:28 +0000 (UTC) From: Markus Probst via B4 Relay Date: Fri, 13 Mar 2026 20:03:10 +0100 Subject: [PATCH v3 6/7] mfd: Add synology microp core driver Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260313-synology_microp_initial-v3-6-ad6ac463a201@posteo.de> References: <20260313-synology_microp_initial-v3-0-ad6ac463a201@posteo.de> In-Reply-To: <20260313-synology_microp_initial-v3-0-ad6ac463a201@posteo.de> To: Lee Jones , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Greg Kroah-Hartman , Miguel Ojeda , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , "Rafael J. Wysocki" , Igor Korotin , Daniel Almeida , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= , Pavel Machek , Len Brown , Robert Moore Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, driver-core@lists.linux.dev, linux-pci@vger.kernel.org, linux-leds@vger.kernel.org, linux-acpi@vger.kernel.org, acpica-devel@lists.linux.dev, Markus Probst X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=3772; i=markus.probst@posteo.de; h=from:subject:message-id; bh=n1TKkDCU7sA420yu0PCrb8RGAbqzgpwd288LpkGJk1c=; b=owEBiQJ2/ZANAwAIATR2H/jnrUPSAcsmYgBptF97W5uQx7vZUUUd4QTbEpR69O3l4q/MbVaPB MN4wBOFIiyJAk8EAAEIADkWIQSCdBjE9KxY53IwxHM0dh/4561D0gUCabRfexsUgAAAAAAEAA5t YW51MiwyLjUrMS4xMSwyLDIACgkQNHYf+OetQ9IsyhAAhBUVFnog6ffMupKTG44AV8/+txW6AW1 EvUWNHUFE8jVpTzG30B+pT3z9Ay1Wm6uXoBrrg9hRXLYdZczOyEPw5SHpbBQ02+xqwRi732nBd0 NE+9GUMnsEI2Z64+5sNuqjEJCQRQT4shpdDV8fJ4QGegPLRoTcl/ns/JG7Uxik+98RCzJFKuEoH qPiaqjizLGlQSjWRxmToWO8wcORGh27vMzKUR1xRqWWHEBQKN6FbgK3+C+CO8sOSoamqMnhkTq9 z4rxYOrOtA1J/ZiHlNLd55BEQhTXDyKTriwjm8POPEKXAeahPGy4nCXLK9RTKDrGIGERH7DEZCN IhdOEF8AYgjZG4A3F5xy5RxRRAZB2zeEYD8UqGhGthVmmPlD8eo2oBUgox3iNh7BkxER5SqYa6P EKkEKwJZkzbeXT2JmQ3uCNTuGiiA0sLzO0JYPeYNvnwgVtswPVgMZv4zeokBKJe+6tNFBUFcwvn nbQsJYfMsuR6Z/vbZXek0ofgoaTKNDfjbBNyojNybEwKLF35it2wvyfwiwfgRVDpRYcZhswpP22 3+DBMH2MreBmpoTD6ut+vAqGJmAwhRoEPu1P9B4sgWnWkBn6BAq7nTNm3d8nD6OGaw/CbnVpR7x W3cW1RzC4tFC/zCLdW9w6BMAaK9wt8vl1wEqBVbCxRHWXTqCAl7Y= X-Developer-Key: i=markus.probst@posteo.de; a=openpgp; fpr=827418C4F4AC58E77230C47334761FF8E7AD43D2 X-Endpoint-Received: by B4 Relay for markus.probst@posteo.de/default with auth_id=680 X-Original-From: Markus Probst Reply-To: markus.probst@posteo.de From: Markus Probst Add a synology microp core driver, written in Rust. The driver targets a microcontroller found in Synology NAS devices. It only provides the base for sub-devices, like LEDs. Tested successfully on a Synology DS923+. Signed-off-by: Markus Probst --- MAINTAINERS | 7 +++++++ drivers/mfd/Kconfig | 11 ++++++++++ drivers/mfd/Makefile | 2 ++ drivers/mfd/synology_microp.rs | 46 ++++++++++++++++++++++++++++++++++++++= ++++ 4 files changed, 66 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index fa49e40836ab..32932ecab9cf 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -25539,6 +25539,13 @@ F: drivers/dma-buf/sync_* F: include/linux/sync_file.h F: include/uapi/linux/sync_file.h =20 +SYNOLOGY MICROP DRIVER +M: Markus Probst +S: Maintained +F: Documentation/devicetree/bindings/leds/synology,microp.yaml +F: Documentation/devicetree/bindings/mfd/synology,microp.yaml +F: drivers/mfd/synology_microp.rs + SYNOPSYS ARC ARCHITECTURE M: Vineet Gupta L: linux-snps-arc@lists.infradead.org diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 7192c9d1d268..8b8b391d1b47 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -1320,6 +1320,17 @@ config MFD_SY7636A To enable support for building sub-devices as modules, choose M here. =20 +config MFD_SYNOLOGY_MICROP + tristate "Synology Microp core driver" + depends on RUST + select RUST_SERIAL_DEV_BUS_ABSTRACTIONS + select MFD_CORE + help + Enable support for the MCU found in Synology NAS devices. + + This driver only provides the base for sub-devices. For additional + functionality, you have to enable support for the sub-devices as well. + config MFD_RDC321X tristate "RDC R-321x southbridge" select MFD_CORE diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index e75e8045c28a..f754be7163cd 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -304,3 +304,5 @@ obj-$(CONFIG_MFD_RSMU_SPI) +=3D rsmu_spi.o rsmu_core.o obj-$(CONFIG_MFD_UPBOARD_FPGA) +=3D upboard-fpga.o =20 obj-$(CONFIG_MFD_LOONGSON_SE) +=3D loongson-se.o + +obj-$(CONFIG_MFD_SYNOLOGY_MICROP) +=3D synology_microp.o diff --git a/drivers/mfd/synology_microp.rs b/drivers/mfd/synology_microp.rs new file mode 100644 index 000000000000..b9b5fff5c18d --- /dev/null +++ b/drivers/mfd/synology_microp.rs @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Synology Microp core driver + +use kernel::{ + device, + mfd, + of, + prelude::*, + serdev, // +}; + +kernel::module_serdev_device_driver! { + type: SynologyMicropCoreDriver, + name: "synology_microp", + authors: ["Markus Probst "], + description: "Synology Microp core driver", + license: "GPL v2", +} + +struct SynologyMicropCoreDriver; + +kernel::of_device_table!( + OF_TABLE, + MODULE_OF_TABLE, + ::IdInfo, + [(of::DeviceId::new(c"synology,microp"), ()),] +); + +#[vtable] +impl serdev::Driver for SynologyMicropCoreDriver { + type IdInfo =3D (); + const OF_ID_TABLE: Option> =3D Some(&OF_TABL= E); + const MFD_CELLS: Option<&'static [mfd::Cell]> =3D + Some(&[mfd::Cell::new(c"synology_microp_leds").of(c"synology,micro= p-leds", None)]); + + fn probe( + dev: &serdev::Device, + _id_info: Option<&Self::IdInfo>, + ) -> impl PinInit { + let _ =3D dev.set_baudrate(9600); + dev.set_flow_control(false); + dev.set_parity(serdev::Parity::None)?; + Ok(Self) + } +} --=20 2.52.0 From nobody Tue Apr 7 09:10:40 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2FBFA332EA0; Fri, 13 Mar 2026 19:03:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773428609; cv=none; b=V1P3QOVC2oV2O5RBaGQHuWyRdUdvZFpcmbiKGLPTmmue+QvNnWz4JccGVY1iuf9yxollcetNPIJwQf2tAfqGCyB286jj8UaOmIe30rT+cGmkkYLquZCUkEc7Mfaa/e7D/J+L1TGET0GVBqK4/DfI7pDLij2yhLIR5o3X2i5d8mY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773428609; c=relaxed/simple; bh=6nwsa038/+UqK8i/OW5KkRLqAoVjm2Rwe3YclvOqsjY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=FQvhR+yU5tiXa3dzWVJPhV3VvZdpEd1qeYLc/iroWrSHqEINm69k01oTGZ8MNmT5+WdcYAzWcMUTRTuT3ENqERy+1bOncVe4WEDs5uQo+0rySeMM8oqdLuDQVdbmMV+QMczzoEeyzGdKUTNYYAP6BHCBCJMEgDXt+BjK/zNZgjo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=hvdpqjHc; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="hvdpqjHc" Received: by smtp.kernel.org (Postfix) with ESMTPS id AB49AC2BCFD; Fri, 13 Mar 2026 19:03:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773428608; bh=6nwsa038/+UqK8i/OW5KkRLqAoVjm2Rwe3YclvOqsjY=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=hvdpqjHcYxBYXYH0kewivVC8QNPu+Qd72QfakWURdTXFjByt72UC0w9CCa4rVFH3U t5bE+gdr7DgtELPVh7do7EGGVoBh3tMhorBGjbfHHTK1uIdONba8dykDG/X2bgrJ4D 8yivb7IHwa4ZII0OsRQaHJDGW6V7tS+G6LyWKcmRxTJj1SP5Gtg1RAfpC0x64JqMIz TzBBJfDdd3ShoVJB+OvwMeEUYvWbv6LWrR933xXesBUaGbWcwjpDwQOKpYd9Or+/KF m8HfOkxFooEgOIu/UseRTV2YUF70yhAso8n2PoCaroWm3dOgduIsPTW3ieSvx5Tg54 xmINpWHVuMT1A== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id A4DB9107BCE1; Fri, 13 Mar 2026 19:03:28 +0000 (UTC) From: Markus Probst via B4 Relay Date: Fri, 13 Mar 2026 20:03:11 +0100 Subject: [PATCH v3 7/7] leds: add synology microp led driver Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260313-synology_microp_initial-v3-7-ad6ac463a201@posteo.de> References: <20260313-synology_microp_initial-v3-0-ad6ac463a201@posteo.de> In-Reply-To: <20260313-synology_microp_initial-v3-0-ad6ac463a201@posteo.de> To: Lee Jones , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Greg Kroah-Hartman , Miguel Ojeda , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , "Rafael J. Wysocki" , Igor Korotin , Daniel Almeida , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= , Pavel Machek , Len Brown , Robert Moore Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, driver-core@lists.linux.dev, linux-pci@vger.kernel.org, linux-leds@vger.kernel.org, linux-acpi@vger.kernel.org, acpica-devel@lists.linux.dev, Markus Probst X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=11929; i=markus.probst@posteo.de; h=from:subject:message-id; bh=T1SW+a7NjbONWvSTUMQ0xLoz4Oyv2hqygRcc9ZCC+ZU=; b=owEBiQJ2/ZANAwAIATR2H/jnrUPSAcsmYgBptF98zekI0a25/58vV5A6eVvauiqKTck4qWoj8 EOrIJXbs9iJAk8EAAEIADkWIQSCdBjE9KxY53IwxHM0dh/4561D0gUCabRffBsUgAAAAAAEAA5t YW51MiwyLjUrMS4xMSwyLDIACgkQNHYf+OetQ9JWpQ/+MMLFUuexZCRkzzNVhWFcWjJFmlbHYtz evXkZs3grpliS1P2jSxdk21crtz39Kw2DmCGFvLJkiiDKi53Z0HnMklLRj2vbZ6wf8zHNAgOK1s zUWlotwm0XjA77baY/WSoH9Kwdx8Dhoa+Wyo8qxVGCGdQQduHuuIdCNlRrD/VplHp7o20QV9/u/ Fe+wjZX6PYAlT/RhZ8DrZPN1iYev0rEP5w4ajZXU7m66qOrdKz6YjPuLflgaX/CSn0WpPfyuhxV XN1E2Y2YQruRjEhLtqifYnuDOrAim/rfZlch/EvFpQ0MLSqY/B2Sv+D3RAa6zr5V/Bcfi+mc67e pjDexD2ifn+Lz3m8VLuGg2Pvtln+BiNQ03DXp/PQxu5VX53LeMkBZtpVf7Vc4lrimfznhTf6iaj 3Zlq7c6pa5ajkPXh84CdKvSzuxywVx3d8ZaN3rTEMmlyZtuocuBZKHAWIeuFcZ2fAmT3RyHs1kt rRdOEICPlryhhn9o4IpfGbQGExqAivOyDECgUzkwaByMrDENolvglxW0E7rsl56RqfeMNdkMlK8 QBSxbqTdHyHo91OrHPyi2XptfDIV4N0BmlPHAWYb9lPuiGtIc9WCnKC7BI/EJucrOHlxtpDrG2o GpjiGlaB4QDHFrNqy/Ye/Q9HfgUcYjh6OHrG1IPkqG+qyTKVHKRE= X-Developer-Key: i=markus.probst@posteo.de; a=openpgp; fpr=827418C4F4AC58E77230C47334761FF8E7AD43D2 X-Endpoint-Received: by B4 Relay for markus.probst@posteo.de/default with auth_id=680 X-Original-From: Markus Probst Reply-To: markus.probst@posteo.de From: Markus Probst Add a driver to control the power, status, alert and usb LEDs on Synology NAS devices. This will be bound to a mfd sub-device, registered by the synology microp core driver. Tested successfully on a Synology DS923+. Signed-off-by: Markus Probst --- MAINTAINERS | 1 + drivers/leds/Kconfig | 11 ++ drivers/leds/Makefile | 1 + drivers/leds/leds_synology_microp.rs | 303 +++++++++++++++++++++++++++++++= ++++ 4 files changed, 316 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 32932ecab9cf..1d9240055d29 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -25544,6 +25544,7 @@ M: Markus Probst S: Maintained F: Documentation/devicetree/bindings/leds/synology,microp.yaml F: Documentation/devicetree/bindings/mfd/synology,microp.yaml +F: drivers/leds/leds_synology_microp.rs F: drivers/mfd/synology_microp.rs =20 SYNOPSYS ARC ARCHITECTURE diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 597d7a79c988..9a9609b924fe 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -1029,6 +1029,17 @@ config LEDS_ACER_A500 This option enables support for the Power Button LED of Acer Iconia Tab A500. =20 +config LEDS_SYNOLOGY_MICROP + tristate "Synology Microp led driver" + depends on MFD_SYNOLOGY_MICROP + depends on RUST + depends on LEDS_CLASS && LEDS_CLASS_MULTICOLOR + help + Enable support for the MCU found in Synology NAS devices. + + This is needed to control the power, status, alert and usb leds on the + NAS device. + source "drivers/leds/blink/Kconfig" =20 comment "Flash and Torch LED drivers" diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index 8fdb45d5b439..200101eb26d5 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -89,6 +89,7 @@ obj-$(CONFIG_LEDS_SC27XX_BLTC) +=3D leds-sc27xx-bltc.o obj-$(CONFIG_LEDS_ST1202) +=3D leds-st1202.o obj-$(CONFIG_LEDS_SUN50I_A100) +=3D leds-sun50i-a100.o obj-$(CONFIG_LEDS_SUNFIRE) +=3D leds-sunfire.o +obj-$(CONFIG_LEDS_SYNOLOGY_MICROP) +=3D leds_synology_microp.o obj-$(CONFIG_LEDS_SYSCON) +=3D leds-syscon.o obj-$(CONFIG_LEDS_TCA6507) +=3D leds-tca6507.o obj-$(CONFIG_LEDS_TI_LMU_COMMON) +=3D leds-ti-lmu-common.o diff --git a/drivers/leds/leds_synology_microp.rs b/drivers/leds/leds_synol= ogy_microp.rs new file mode 100644 index 000000000000..d2e94e992981 --- /dev/null +++ b/drivers/leds/leds_synology_microp.rs @@ -0,0 +1,303 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Synology Microp led driver + +use kernel::{ + device::Bound, + devres::{self, Devres}, + led::{ + self, + LedOps, + MultiColorSubLed, // + }, + new_mutex, + platform, + prelude::*, + serdev, + sync::Mutex, // +}; +use pin_init::pin_init_scope; + +kernel::module_platform_driver! { + type: SynologyMicropLedDriver, + name: "synology_microp_leds", + authors: ["Markus Probst "], + description: "Synology Microp led driver", + license: "GPL v2", +} + +#[pin_data] +struct SynologyMicropLedDriver { + #[pin] + status: Devres>, + #[pin] + power: Devres>, +} + +impl platform::Driver for SynologyMicropLedDriver { + type IdInfo =3D (); + + fn probe( + dev: &platform::Device, + _id_info: Option<&Self::IdInfo>, + ) -> impl PinInit { + pin_init_scope(move || { + let fwnode =3D dev.as_ref().fwnode().ok_or(EINVAL)?; + + if let Some(alert_fwnode) =3D fwnode.get_child_by_name(c"alert= -led") { + devres::register( + dev.as_ref(), + led::DeviceBuilder::new() + .fwnode(Some(alert_fwnode)) + .devicename(c"synology-microp/alert-led") + .color(led::Color::Orange) + .build( + &**dev, + try_pin_init!(LedHandler { + blink <- new_mutex!(false), + command: Command::Alert, + }), + ), + GFP_KERNEL, + )?; + } + + if let Some(alert_fwnode) =3D fwnode.get_child_by_name(c"usb-l= ed") { + devres::register( + dev.as_ref(), + led::DeviceBuilder::new() + .fwnode(Some(alert_fwnode)) + .devicename(c"synology-microp/usb-led") + .color(led::Color::Green) + .build( + &**dev, + try_pin_init!(LedHandler { + blink <- new_mutex!(false), + command: Command::Usb, + }), + ), + GFP_KERNEL, + )?; + } + + Ok(try_pin_init!(Self { + status <- led::DeviceBuilder::new() + .fwnode(Some(fwnode.get_child_by_name(c"status-led").o= k_or(EINVAL)?)) + .devicename(c"synology-microp/status-led") + .color(led::Color::Multi) + .build_multicolor( + &**dev, + try_pin_init!(StatusLedHandler { + blink <- new_mutex!(false), + }), + StatusLedHandler::SUBLEDS, + ), + power <- led::DeviceBuilder::new() + .fwnode(Some(fwnode.get_child_by_name(c"power-led").ok= _or(EINVAL)?)) + .devicename(c"synology-microp/power-led") + .color(led::Color::Blue) + .default_trigger(c"timer") + .build( + &**dev, + try_pin_init!(LedHandler { + blink <- new_mutex!(true), + command: Command::Power, + }), + ), + })) + }) + } +} + +enum StatusLedColor { + Green, + Orange, +} + +enum State { + On, + Blink, + Off, +} + +enum Command { + Power(State), + Status(StatusLedColor, State), + Alert(State), + Usb(State), +} + +impl Command { + fn write(self, dev: &platform::Device) -> Result { + // SAFETY: Since we have no of and no acpi match table, we assume = this is a mfd sub-device + // and our parent is a serial device bus device, bound to the syno= logy microp core driver. + let parent =3D unsafe { dev.as_ref().parent_unchecked::>() }; + parent.write_all( + match self { + Self::Power(State::On) =3D> &[0x34], + Self::Power(State::Blink) =3D> &[0x35], + Self::Power(State::Off) =3D> &[0x36], + + Self::Status(_, State::Off) =3D> &[0x37], + Self::Status(StatusLedColor::Green, State::On) =3D> &[0x38= ], + Self::Status(StatusLedColor::Green, State::Blink) =3D> &[0= x39], + Self::Status(StatusLedColor::Orange, State::On) =3D> &[0x3= A], + Self::Status(StatusLedColor::Orange, State::Blink) =3D> &[= 0x3B], + + Self::Alert(State::On) =3D> &[0x4C, 0x41, 0x31], + Self::Alert(State::Blink) =3D> &[0x4C, 0x41, 0x32], + Self::Alert(State::Off) =3D> &[0x4C, 0x41, 0x33], + + Self::Usb(State::On) =3D> &[0x40], + Self::Usb(State::Blink) =3D> &[0x41], + Self::Usb(State::Off) =3D> &[0x42], + }, + serdev::Timeout::Max, + )?; + Ok(()) + } +} + +#[pin_data] +struct LedHandler { + #[pin] + blink: Mutex, + command: fn(State) -> Command, +} + +#[vtable] +impl LedOps for LedHandler { + type Bus =3D platform::Device; + type Mode =3D led::Normal; + const BLOCKING: bool =3D true; + const MAX_BRIGHTNESS: u32 =3D 1; + + fn brightness_set( + &self, + dev: &Self::Bus, + _classdev: &led::Device, + brightness: u32, + ) -> Result<()> { + let mut blink =3D self.blink.lock(); + (self.command)(if brightness =3D=3D 0 { + *blink =3D false; + State::Off + } else if *blink { + State::Blink + } else { + State::On + }) + .write(dev)?; + + Ok(()) + } + + fn blink_set( + &self, + dev: &Self::Bus, + _classdev: &led::Device, + delay_on: &mut usize, + delay_off: &mut usize, + ) -> Result<()> { + let mut blink =3D self.blink.lock(); + + (self.command)(if *delay_on =3D=3D 0 && *delay_off !=3D 0 { + State::Off + } else if *delay_on !=3D 0 && *delay_off =3D=3D 0 { + State::On + } else { + *blink =3D true; + *delay_on =3D 167; + *delay_off =3D 167; + + State::Blink + }) + .write(dev) + } +} + +#[pin_data] +struct StatusLedHandler { + #[pin] + blink: Mutex, +} + +impl StatusLedHandler { + const SUBLEDS: &[MultiColorSubLed] =3D &[ + MultiColorSubLed::new(led::Color::Green).initial_intensity(1), + MultiColorSubLed::new(led::Color::Orange), + ]; +} + +#[vtable] +impl LedOps for StatusLedHandler { + type Bus =3D platform::Device; + type Mode =3D led::MultiColor; + const BLOCKING: bool =3D true; + const MAX_BRIGHTNESS: u32 =3D 1; + + fn brightness_set( + &self, + dev: &Self::Bus, + classdev: &led::MultiColorDevice, + brightness: u32, + ) -> Result<()> { + let mut blink =3D self.blink.lock(); + if brightness =3D=3D 0 { + *blink =3D false; + } + + let (color, subled_brightness) =3D if classdev.subleds()[1].intens= ity =3D=3D 0 { + (StatusLedColor::Green, classdev.subleds()[0].brightness) + } else { + (StatusLedColor::Orange, classdev.subleds()[1].brightness) + }; + + Command::Status( + color, + if subled_brightness =3D=3D 0 { + State::Off + } else if *blink { + State::Blink + } else { + State::On + }, + ) + .write(dev) + } + + fn blink_set( + &self, + dev: &Self::Bus, + classdev: &led::MultiColorDevice, + delay_on: &mut usize, + delay_off: &mut usize, + ) -> Result<()> { + let mut blink =3D self.blink.lock(); + *blink =3D true; + + let (color, subled_intensity) =3D if classdev.subleds()[1].intensi= ty =3D=3D 0 { + (StatusLedColor::Green, classdev.subleds()[0].intensity) + } else { + (StatusLedColor::Orange, classdev.subleds()[1].intensity) + }; + Command::Status( + color, + if *delay_on =3D=3D 0 && *delay_off !=3D 0 { + *blink =3D false; + State::Off + } else if subled_intensity =3D=3D 0 { + State::Off + } else if *delay_on !=3D 0 && *delay_off =3D=3D 0 { + *blink =3D false; + State::On + } else { + *delay_on =3D 167; + *delay_off =3D 167; + + State::Blink + }, + ) + .write(dev) + } +} --=20 2.52.0