Devicetree
 help / color / mirror / Atom feed
* Re: [PATCH v6 5/6] clk: fsl-sai: Extract clock setup into fsl_sai_clk_register()
From: Stephen Boyd @ 2026-04-12  0:37 UTC (permalink / raw)
  To: Marek Vasut, linux-clk
  Cc: Marek Vasut, Brian Masney, Conor Dooley, Krzysztof Kozlowski,
	Michael Turquette, Michael Walle, Rob Herring, devicetree,
	linux-kernel
In-Reply-To: <20260409002952.319668-5-marex@nabladev.com>

Quoting Marek Vasut (2026-04-08 17:29:05)
> Create helper function fsl_sai_clk_register() to set up and register
> SAI clock. Rename BCLK specific struct fsl_sai_clk members with bclk_
> prefix. Use of_node_full_name(dev->of_node) and clock name to register
> uniquely named clock. This is done in preparation for the follow up
> patch, which adds MCLK support.
> 
> Signed-off-by: Marek Vasut <marex@nabladev.com>
> ---

Applied to clk-next

^ permalink raw reply

* Re: [PATCH v6 3/6] clk: fsl-sai: Add i.MX8M support with 8 byte register offset
From: Stephen Boyd @ 2026-04-12  0:37 UTC (permalink / raw)
  To: Marek Vasut, linux-clk
  Cc: Marek Vasut, Brian Masney, Peng Fan, Conor Dooley,
	Krzysztof Kozlowski, Michael Turquette, Michael Walle,
	Rob Herring, devicetree, linux-kernel
In-Reply-To: <20260409002952.319668-3-marex@nabladev.com>

Quoting Marek Vasut (2026-04-08 17:29:03)
> The i.MX8M/Mini/Nano/Plus variant of the SAI IP has control registers
> shifted by +8 bytes and requires additional bus clock. Add support for
> the i.MX8M variant of the IP with this register shift and additional
> clock.
> 
> Reviewed-by: Brian Masney <bmasney@redhat.com>
> Reviewed-by: Peng Fan <peng.fan@nxp.com>
> Signed-off-by: Marek Vasut <marex@nabladev.com>
> ---

Applied to clk-next

^ permalink raw reply

* Re: [PATCH v6 4/6] dt-bindings: clock: fsl-sai: Document clock-cells = <1> support
From: Stephen Boyd @ 2026-04-12  0:37 UTC (permalink / raw)
  To: Marek Vasut, linux-clk
  Cc: Marek Vasut, Conor Dooley, Brian Masney, Conor Dooley,
	Krzysztof Kozlowski, Michael Turquette, Michael Walle,
	Rob Herring, devicetree, linux-kernel
In-Reply-To: <20260409002952.319668-4-marex@nabladev.com>

Quoting Marek Vasut (2026-04-08 17:29:04)
> The driver now supports generation of both BCLK and MCLK, document
> support for #clock-cells = <0> for legacy case and #clock-cells = <1>
> for the new case which can differentiate between BCLK and MCLK.
> 
> Acked-by: Conor Dooley <conor.dooley@microchip.com>
> Signed-off-by: Marek Vasut <marex@nabladev.com>
> ---

Applied to clk-next

^ permalink raw reply

* Re: [PATCH v6 2/6] clk: fsl-sai: Sort the headers
From: Stephen Boyd @ 2026-04-12  0:37 UTC (permalink / raw)
  To: Marek Vasut, linux-clk
  Cc: Marek Vasut, Brian Masney, Conor Dooley, Krzysztof Kozlowski,
	Michael Turquette, Michael Walle, Rob Herring, devicetree,
	linux-kernel
In-Reply-To: <20260409002952.319668-2-marex@nabladev.com>

Quoting Marek Vasut (2026-04-08 17:29:02)
> Sort the headers. No functional change.
> 
> Reviewed-by: Brian Masney <bmasney@redhat.com>
> Signed-off-by: Marek Vasut <marex@nabladev.com>
> ---

Applied to clk-next

^ permalink raw reply

* Re: [PATCH v2 5/5] arm64: dts: qcom: sdm845-xiaomi-beryllium-tianma: Disable MDSS
From: Dmitry Baryshkov @ 2026-04-12  0:36 UTC (permalink / raw)
  To: David Heidelberg
  Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sam Day, linux-arm-msm, devicetree, linux-kernel,
	phone-devel, Petr Hodina
In-Reply-To: <c746d310-5925-4656-9487-3521cb87793a@ixit.cz>

On Fri, Apr 10, 2026 at 03:51:12PM +0200, David Heidelberg wrote:
> On 18/03/2026 15:47, Dmitry Baryshkov wrote:
> > On Tue, Mar 17, 2026 at 11:12:35PM +0100, David Heidelberg via B4 Relay wrote:
> > > From: Petr Hodina <petr.hodina@protonmail.com>
> > > 
> > > Currently the panel driver for tianma is broken.
> > > Disable MDSS to prevent DRM taking over the framebuffer.
> > 
> > I'd still hope that somebody can get it to work. I'd start by using
> > prepare_prev_first. Sumit reported the panel as working in 2020 and I
> > have no doubts that it was the case. Another option migt be something
> > related to the dispcc (see my [1]).
> 
> Sadly, the prepare_prev_first didn't solve the issue. The framebuffer ->
> MDSS takover happens, but at greetd (login) loading screen goes black and
> never restores.
> 
> Will need more work.

Do you see a console _while_ it boots, after the handover? I'd check the
mode programming. Maybe, disabling panel reset would also (temporarily)
help.

> 
> David>
> > [1] https://lore.kernel.org/linux-arm-msm/20260217-sdm845-hdk-v1-1-866f1965fef7@oss.qualcomm.com/

-- 
With best wishes
Dmitry

^ permalink raw reply

* Re: [PATCH v6 1/6] dt-bindings: clock: fsl-sai: Document i.MX8M support
From: Stephen Boyd @ 2026-04-12  0:36 UTC (permalink / raw)
  To: Marek Vasut, linux-clk
  Cc: Marek Vasut, Conor Dooley, Brian Masney, Conor Dooley,
	Krzysztof Kozlowski, Michael Turquette, Michael Walle,
	Rob Herring, devicetree, linux-kernel
In-Reply-To: <20260409002952.319668-1-marex@nabladev.com>

Quoting Marek Vasut (2026-04-08 17:29:01)
> The i.MX8M/Mini/Nano/Plus variant of the SAI IP has control registers
> shifted by +8 bytes and requires additional bus clock. Document support
> for the i.MX8M variant of the IP with this register shift and additional
> clock. Update the description slightly.
> 
> Acked-by: Conor Dooley <conor.dooley@microchip.com>
> Signed-off-by: Marek Vasut <marex@nabladev.com>
> ---

Applied to clk-next

^ permalink raw reply

* Re: [PATCH v5 0/5] Add support for AAEON SRG-IMX8P MCU
From: Guenter Roeck @ 2026-04-12  0:12 UTC (permalink / raw)
  To: Thomas Perrot (Schneider Electric), Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Linus Walleij,
	Bartosz Golaszewski, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam,
	Jérémie Dautheribes, Wim Van Sebroeck, Lee Jones
  Cc: devicetree, linux-kernel, linux-gpio, imx, linux-arm-kernel,
	linux-watchdog, Thomas Petazzoni, Miquel Raynal,
	Krzysztof Kozlowski, Conor Dooley, Bartosz Golaszewski
In-Reply-To: <20260408-dev-b4-aaeon-mcu-driver-v5-0-ad98bd481668@bootlin.com>

On 4/8/26 10:21, Thomas Perrot (Schneider Electric) wrote:
> This patch series introduces support for the AAEON SRG-IMX8P embedded
> controller (MCU). The MCU is connected via I2C and provides GPIO and
> watchdog functionality for the SRG-IMX8P board.
> 
> The series includes:
> - Device tree binding for the MFD driver
> - MFD driver that serves as the core driver for the MCU
> - GPIO driver implementing the GPIO functionality
> - Watchdog driver for system monitoring
> - MAINTAINERS entry for the new drivers
> 
> The drivers follow the standard Linux kernel subsystem patterns, with
> the MFD driver registering the sub-devices (GPIO and watchdog) which
> are then handled by their respective subsystem drivers.
> 
> Signed-off-by: Thomas Perrot (Schneider Electric) <thomas.perrot@bootlin.com>

Sashiko has some interesting feedback that might be worth looking into.

https://sashiko.dev/#/patchset/20260408-dev-b4-aaeon-mcu-driver-v5-0-ad98bd481668%40bootlin.com

Guenter


^ permalink raw reply

* Re: [GIT PULL] clk: tenstorrent: Add Atlantis PRCM for v7.1
From: Stephen Boyd @ 2026-04-11 23:00 UTC (permalink / raw)
  To: Drew Fustini
  Cc: Brian Masney, Philipp Zabel, Anirudh Srinivasan, Drew Fustini,
	linux-riscv, devicetree, linux-kernel, linux-clk
In-Reply-To: <abghFg5INVslFFcc@x1>

Quoting Drew Fustini (2026-03-16 08:26:14)
> Hi Stephen,
> 
> This pull request introduces support for the Tenstorrent Atlantis RISC-V
> SoC in the form of a clk driver, reset driver and the associated DT
> binding. The reset driver was reviewed by Philipp, who agreed that it
> could go via the clk tree. Brian reviewed the clk driver but there is no
> review/ack from you. Please let me know if you'd like to see any changes
> and we will post a new revision.
> 
> The following changes since commit 6de23f81a5e08be8fbf5e8d7e9febc72a5b5f27f:
> 
>   Linux 7.0-rc1 (2026-02-22 13:18:59 -0800)
> 
> are available in the Git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/tenstorrent/linux.git tags/tenstorrent-clk-for-v7.1
> 
> for you to fetch changes up to 23c8ebc952849b3ba47d04d0ec95daf5cc136061:
> 
>   clk: tenstorrent: Add Atlantis clock controller driver (2026-03-09 20:10:26 -0700)
> 
> ----------------------------------------------------------------

Thanks. Pulled into clk-next

^ permalink raw reply

* Re: [PATCH 1/2] dt-bindings: mmc: dw-mshc-common: add option for configuring DMA threshold
From: Krzysztof Kozlowski @ 2026-04-11 20:27 UTC (permalink / raw)
  To: Kaustabh Chakraborty, Ulf Hansson, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Jaehoon Chung, Shawn Lin
  Cc: linux-mmc, devicetree, linux-kernel
In-Reply-To: <20260412-dwmmc-dma-thr-v1-1-75a2f658eee3@disroot.org>

On 11/04/2026 21:43, Kaustabh Chakraborty wrote:
> Some controllers, such as certain Exynos SDIO ones, are unable to
> perform DMA transfers of small amount of bytes properly. Add a property
> to configure the DMA transfer threshold.
> 
> Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org>
> ---
>  .../devicetree/bindings/mmc/synopsys-dw-mshc-common.yaml          | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc-common.yaml b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc-common.yaml
> index 6f11b2adf1036..1693277957a91 100644
> --- a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc-common.yaml
> +++ b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc-common.yaml
> @@ -57,6 +57,14 @@ properties:
>        force fifo watermark setting accordingly.
>      $ref: /schemas/types.yaml#/definitions/flag
>  
> +  dma-threshold-bytes:
> +    description:
> +      DMA transfer takes place only if the transfer size is equal to or greater
> +      than the number of bytes defined by the threshold value. Some controllers are
> +      unable to perform the DMA transfer properly with small amounts of data.

Looks like controller specific, thus should be deducible from the
compatible.

Best regards,
Krzysztof

^ permalink raw reply

* [PATCH 2/2] mmc: dw_mmc: implement option for configuring DMA threshold
From: Kaustabh Chakraborty @ 2026-04-11 19:43 UTC (permalink / raw)
  To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Jaehoon Chung, Shawn Lin
  Cc: linux-mmc, devicetree, linux-kernel, Kaustabh Chakraborty
In-Reply-To: <20260412-dwmmc-dma-thr-v1-0-75a2f658eee3@disroot.org>

Some controllers, such as certain Exynos SDIO ones, are unable to
perform DMA transfers of small amount of bytes properly. Following the
device tree schema, implement the property to define the DMA transfer
threshold (from a hard coded value of 16 bytes) so that lesser number of
bytes can be transferred safely skipping DMA in such controllers. The
value of 16 bytes stays as the default for controllers which do not
define it.

Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org>
---
 drivers/mmc/host/dw_mmc.c | 6 ++++--
 drivers/mmc/host/dw_mmc.h | 1 +
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 20193ee7b73eb..0c0d269b5e033 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -40,7 +40,6 @@
 				 SDMMC_INT_RESP_ERR | SDMMC_INT_HLE)
 #define DW_MCI_ERROR_FLAGS	(DW_MCI_DATA_ERROR_FLAGS | \
 				 DW_MCI_CMD_ERROR_FLAGS)
-#define DW_MCI_DMA_THRESHOLD	16
 
 #define DW_MCI_FREQ_MAX	200000000	/* unit: HZ */
 #define DW_MCI_FREQ_MIN	100000		/* unit: HZ */
@@ -821,7 +820,7 @@ static int dw_mci_pre_dma_transfer(struct dw_mci *host,
 	 * non-word-aligned buffers or lengths. Also, we don't bother
 	 * with all the DMA setup overhead for short transfers.
 	 */
-	if (data->blocks * data->blksz < DW_MCI_DMA_THRESHOLD)
+	if (data->blocks * data->blksz < host->dma_threshold)
 		return -EINVAL;
 
 	if (data->blksz & 3)
@@ -3137,6 +3136,9 @@ static int dw_mci_parse_dt(struct dw_mci *host)
 	if (!host->data_addr_override)
 		device_property_read_u32(dev, "data-addr", &host->data_addr_override);
 
+	if (device_property_read_u32(dev, "dma-threshold-bytes", &host->dma_threshold) < 0)
+		host->dma_threshold = 16;
+
 	if (device_property_present(dev, "fifo-watermark-aligned"))
 		host->wm_aligned = true;
 
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
index 42e58be74ce09..5cdd342d01b68 100644
--- a/drivers/mmc/host/dw_mmc.h
+++ b/drivers/mmc/host/dw_mmc.h
@@ -163,6 +163,7 @@ struct dw_mci {
 	void __iomem		*regs;
 	void __iomem		*fifo_reg;
 	u32			data_addr_override;
+	u32			dma_threshold;
 	bool			wm_aligned;
 
 	struct scatterlist	*sg;

-- 
2.53.0


^ permalink raw reply related

* [PATCH 1/2] dt-bindings: mmc: dw-mshc-common: add option for configuring DMA threshold
From: Kaustabh Chakraborty @ 2026-04-11 19:43 UTC (permalink / raw)
  To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Jaehoon Chung, Shawn Lin
  Cc: linux-mmc, devicetree, linux-kernel, Kaustabh Chakraborty
In-Reply-To: <20260412-dwmmc-dma-thr-v1-0-75a2f658eee3@disroot.org>

Some controllers, such as certain Exynos SDIO ones, are unable to
perform DMA transfers of small amount of bytes properly. Add a property
to configure the DMA transfer threshold.

Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org>
---
 .../devicetree/bindings/mmc/synopsys-dw-mshc-common.yaml          | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc-common.yaml b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc-common.yaml
index 6f11b2adf1036..1693277957a91 100644
--- a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc-common.yaml
+++ b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc-common.yaml
@@ -57,6 +57,14 @@ properties:
       force fifo watermark setting accordingly.
     $ref: /schemas/types.yaml#/definitions/flag
 
+  dma-threshold-bytes:
+    description:
+      DMA transfer takes place only if the transfer size is equal to or greater
+      than the number of bytes defined by the threshold value. Some controllers are
+      unable to perform the DMA transfer properly with small amounts of data.
+      This option allows to configure the threshold up to a comfortable value.
+    $ref: /schemas/types.yaml#/definitions/uint32
+
   dmas:
     maxItems: 1
 

-- 
2.53.0


^ permalink raw reply related

* [PATCH 0/2] Configuring DMA threshold value for DW-MMC controllers
From: Kaustabh Chakraborty @ 2026-04-11 19:43 UTC (permalink / raw)
  To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Jaehoon Chung, Shawn Lin
  Cc: linux-mmc, devicetree, linux-kernel, Kaustabh Chakraborty

In Samsung Exynos 7870 devices with Broadcom Wi-Fi, it has been observed
that small sized DMA transfers are unreliable and are not written
properly, which renders the cache incoherent.

Experimental observations say that DMA transfer sizes of somewhere
around 64 to 512 are intolerable. We must thus implement a mechanism to
fall back to PIO transfer in this case. One such approach, which this
series implements is allowing the DMA transfer threshold, which is
already defined in the driver, to be configurable.

Note that this patch is likely to be labelled as a workaround. These
smaller transfers seem to be successful from downstream kernels,
however efforts to figure out how so went in vain. It is also very
possible that the downstream Broadcom Wi-Fi SDIO driver uses PIO
transfers as well.

Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org>
---
Kaustabh Chakraborty (2):
      dt-bindings: mmc: dw-mshc-common: add option for configuring DMA threshold
      mmc: dw_mmc: implement option for configuring DMA threshold

 .../devicetree/bindings/mmc/synopsys-dw-mshc-common.yaml          | 8 ++++++++
 drivers/mmc/host/dw_mmc.c                                         | 6 ++++--
 drivers/mmc/host/dw_mmc.h                                         | 1 +
 3 files changed, 13 insertions(+), 2 deletions(-)
---
base-commit: 66672af7a095d89f082c5327f3b15bc2f93d558e
change-id: 20260412-dwmmc-dma-thr-1090d8285ea7

Best regards,
-- 
Kaustabh Chakraborty <kauschluss@disroot.org>


^ permalink raw reply

* Re: [PATCH v3 2/5] dt-bindings: iio: adc: ad4130: Add new supported parts
From: David Lechner @ 2026-04-11 19:08 UTC (permalink / raw)
  To: Jonathan Santos, linux-iio, linux-kernel, devicetree
  Cc: lars, Michael.Hennerich, jic23, nuno.sa, andy, robh, krzk+dt,
	conor+dt, Krzysztof Kozlowski
In-Reply-To: <7bf387e8ad20e2f2bb14534fb03608bbadfa47d2.1774996100.git.Jonathan.Santos@analog.com>

On 4/1/26 6:58 AM, Jonathan Santos wrote:
> Extend driver support for AD4129-4/8, AD4130-4, and AD4131-4/8 ADC
> variants.
> 
> Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
> Signed-off-by: Jonathan Santos <Jonathan.Santos@analog.com>
> ---
> Changes in v3:
> * None.
> 
> Changes in v2:
> * None.
> ---
>  .../devicetree/bindings/iio/adc/adi,ad4130.yaml   | 15 +++++++++++++--
>  1 file changed, 13 insertions(+), 2 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad4130.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad4130.yaml
> index fcc00e5cfd54..f4cad68fa04d 100644
> --- a/Documentation/devicetree/bindings/iio/adc/adi,ad4130.yaml
> +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad4130.yaml
> @@ -5,19 +5,30 @@
>  $id: http://devicetree.org/schemas/iio/adc/adi,ad4130.yaml#
>  $schema: http://devicetree.org/meta-schemas/core.yaml#
>  
> -title: Analog Devices AD4130 ADC device driver
> +title: Analog Devices AD4130 family ADC device driver

I'm surprised that on one said anything about the word "driver"
in a devicetree binding. :-)


^ permalink raw reply

* [PATCH v2] dt-bindings: ARM: arm,vexpress-scc: convert to DT schema
From: Khushal Chitturi @ 2026-04-11 18:33 UTC (permalink / raw)
  To: robh, krzk+dt, conor+dt, liviu.dudau, sudeep.holla, lpieralisi
  Cc: pawel.moll, devicetree, linux-arm-kernel, linux-kernel,
	Khushal Chitturi

Convert the ARM Versatile Express Serial Configuration Controller
bindings to DT schema.

Signed-off-by: Khushal Chitturi <khushalchitturi@gmail.com>
---
Changelog:
v1 -> v2:
- Modified compatible string to use an enum instead of a generic pattern.
- Updated maintainers list.

 .../bindings/arm/arm,vexpress-scc.yaml        | 53 +++++++++++++++++++
 .../devicetree/bindings/arm/vexpress-scc.txt  | 33 ------------
 2 files changed, 53 insertions(+), 33 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/arm,vexpress-scc.yaml
 delete mode 100644 Documentation/devicetree/bindings/arm/vexpress-scc.txt

diff --git a/Documentation/devicetree/bindings/arm/arm,vexpress-scc.yaml b/Documentation/devicetree/bindings/arm/arm,vexpress-scc.yaml
new file mode 100644
index 000000000000..9b8f7e0c4ea0
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/arm,vexpress-scc.yaml
@@ -0,0 +1,53 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/arm/arm,vexpress-scc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: ARM Versatile Express Serial Configuration Controller
+
+maintainers:
+  - Liviu Dudau <liviu.dudau@arm.com>
+  - Sudeep Holla <sudeep.holla@arm.com>
+
+description: |
+  Test chips for ARM Versatile Express platform implement SCC (Serial
+  Configuration Controller) interface, used to set initial conditions
+  for the test chip.
+
+  In some cases its registers are also mapped in normal address space
+  and can be used to obtain runtime information about the chip internals
+  (like silicon temperature sensors) and as interface to other subsystems
+  like platform configuration control and power management.
+
+properties:
+  compatible:
+    items:
+      - enum:
+          - arm,vexpress-scc,v2p-ca15_a7
+      - const: arm,vexpress-scc
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+required:
+  - compatible
+
+additionalProperties: false
+
+examples:
+  - |
+    bus {
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        scc@7fff0000 {
+            compatible = "arm,vexpress-scc,v2p-ca15_a7", "arm,vexpress-scc";
+            reg = <0 0x7fff0000 0 0x1000>;
+            interrupts = <0 95 4>;
+        };
+    };
+...
diff --git a/Documentation/devicetree/bindings/arm/vexpress-scc.txt b/Documentation/devicetree/bindings/arm/vexpress-scc.txt
deleted file mode 100644
index ae5043e42e5d..000000000000
--- a/Documentation/devicetree/bindings/arm/vexpress-scc.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-ARM Versatile Express Serial Configuration Controller
------------------------------------------------------
-
-Test chips for ARM Versatile Express platform implement SCC (Serial
-Configuration Controller) interface, used to set initial conditions
-for the test chip.
-
-In some cases its registers are also mapped in normal address space
-and can be used to obtain runtime information about the chip internals
-(like silicon temperature sensors) and as interface to other subsystems
-like platform configuration control and power management.
-
-Required properties:
-
-- compatible value: "arm,vexpress-scc,<model>", "arm,vexpress-scc";
-		    where <model> is the full tile model name (as used
-		    in the tile's Technical Reference Manual),
-		    eg. for Coretile Express A15x2 A7x3 (V2P-CA15_A7):
-	compatible = "arm,vexpress-scc,v2p-ca15_a7", "arm,vexpress-scc";
-
-Optional properties:
-
-- reg: when the SCC is memory mapped, physical address and size of the
-       registers window
-- interrupts: when the SCC can generate a system-level interrupt
-
-Example:
-
-	scc@7fff0000 {
-		compatible = "arm,vexpress-scc,v2p-ca15_a7", "arm,vexpress-scc";
-		reg = <0 0x7fff0000 0 0x1000>;
-		interrupts = <0 95 4>;
-	};
-- 
2.53.0


^ permalink raw reply related

* Re: [PATCH v6 3/3] arm64: dts: rockchip: Add Orange Pi 5 Pro board support
From: Alexey Charkov @ 2026-04-11 18:00 UTC (permalink / raw)
  To: dennis
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner,
	FUKAUMI Naoki, Hsun Lai, Jonas Karlman, Chaoyi Chen, John Clark,
	Michael Opdenacker, Quentin Schulz, Andrew Lunn, Chukun Pan,
	Peter Robinson, Michael Riesch, Mykola Kvach, Jimmy Hon,
	devicetree, linux-arm-kernel, linux-rockchip, linux-kernel
In-Reply-To: <20260411024743.195385-4-dennis@ausil.us>

On Sat, Apr 11, 2026 at 6:47 AM <dennis@ausil.us> wrote:
>
> From: Dennis Gilmore <dennis@ausil.us>
>
> Add device tree for the Xunlong Orange Pi 5 Pro (RK3588S).
>
> - eMMC module, you can optionally solder a SPI NOR in place and turn
>  off the eMMC
> - PCIe-attached NIC (pcie2x1l1)
> - PCIe NVMe slot (pcie2x1l2)
> - AP6256 WiFi (BCM43456) via SDIO with mmc-pwrseq
> - BCM4345C5 Bluetooth
> - es8388 audio
> - USB 2.0 and USB 3.0
> - Two HDMI ports, the second is connected to the SoC's DP controller
>   driven by a transparent LT8711UXD bridge that has firmware onboard and
>   needs no node defined.
>
> Vendors description and links to schematics available:
> http://www.orangepi.org/html/hardWare/computerAndMicrocontrollers/details/Orange-Pi-5-Pro.html

Hi Dennis,

The most useful of these is the schematic, so it's best to include a
direct link to that in a dedicated Link: tag

Link: https://drive.google.com/file/d/1qs1DratHuh7C6J6MEtQIwUsiSrg8qgTi/view
[schematic]

> Signed-off-by: Dennis Gilmore <dennis@ausil.us>
> ---
>  .../display/rockchip/rockchip,dw-dp.yaml      |   7 +
>  arch/arm64/boot/dts/rockchip/Makefile         |   1 +
>  .../dts/rockchip/rk3588s-orangepi-5-pro.dts   | 352 ++++++++++++++++++
>  drivers/gpu/drm/bridge/synopsys/dw-dp.c       |  12 +

These should be three separate patches, never lumped together. First
the binding change, next the driver change. They go together via the
subsystem tree (likely DRM in this case). Then the DTS addition (or
change) separately (it goes via the SoC tree).

>  4 files changed, 372 insertions(+)
>  create mode 100644 arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5-pro.dts
>
> diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-dp.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-dp.yaml
> index 6345f0132d43..079a912d97f1 100644
> --- a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-dp.yaml
> +++ b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-dp.yaml
> @@ -57,6 +57,13 @@ properties:
>        - const: i2s
>        - const: spdif
>
> +  hpd-gpios:
> +    maxItems: 1
> +    description:
> +      GPIO used for hot plug detection when the controller's native HPD
> +      input is not connected. If not specified, the controller uses its
> +      internal HPD detection mechanism.

Do you actually need this change? According to the schematic, the
DP_HPDIN line from the DP-HDMI bridge is routed to the native
DP0_HPDIN_M0 pin of the DP controller, so it shouldn't require this
GPIO trick if the pinctrl is configured properly.

>    phys:
>      maxItems: 1
>
> diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile
> index 4d384f153c13..c99dca2ae9e7 100644
> --- a/arch/arm64/boot/dts/rockchip/Makefile
> +++ b/arch/arm64/boot/dts/rockchip/Makefile
> @@ -214,6 +214,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-nanopi-r6c.dtb
>  dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-odroid-m2.dtb
>  dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-orangepi-5.dtb
>  dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-orangepi-5b.dtb
> +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-orangepi-5-pro.dtb
>  dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-orangepi-cm5-base.dtb
>  dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-radxa-cm5-io.dtb
>  dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-roc-pc.dtb
> diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5-pro.dts b/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5-pro.dts
> new file mode 100644
> index 000000000000..84c83aa69f63
> --- /dev/null
> +++ b/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5-pro.dts
> @@ -0,0 +1,352 @@
> +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
> +
> +/dts-v1/;
> +
> +#include "rk3588s-orangepi-5.dtsi"
> +
> +/ {
> +       model = "Xunlong Orange Pi 5 Pro";
> +       compatible = "xunlong,orangepi-5-pro", "rockchip,rk3588s";
> +
> +       aliases {
> +               mmc0 = &sdhci;
> +               mmc1 = &sdmmc;
> +               mmc2 = &sdio;
> +       };
> +
> +       dp-con {
> +               compatible = "dp-connector";

You don't have a physical DP connector on the board, so this node
doesn't describe actual hardware, and is thus a no-go. What you have
instead is an HDMI type A connector routed via an onboard DP to HDMI
bridge, so you should describe exactly that in the device tree (a node
for the HDMI connector, a node for the bridge, a node for the DP
controller, and endpoints connected from the controller to the bridge,
from the bridge to the connector). Please refer to the device tree for
Radxa Rock 5 ITX, which has a similar setup (but a different bridge
IC).

I don't think your LT8711UXD has existing binding or driver entry, so
a one-line patch will likely be needed to
Documentation/devicetree/bindings/display/bridge/simple-bridge.yaml,
and a separate one to drivers/gpu/drm/bridge/simple-bridge.c. Separate
ones :)

> +               port {
> +                       dp_con_in: endpoint {
> +                               remote-endpoint = <&dp0_out_con>;
> +                       };
> +               };
> +       };
> +
> +       analog-sound {
> +               compatible = "simple-audio-card";
> +               pinctrl-names = "default";
> +               pinctrl-0 = <&hp_detect>;
> +               simple-audio-card,bitclock-master = <&masterdai>;
> +               simple-audio-card,format = "i2s";
> +               simple-audio-card,frame-master = <&masterdai>;
> +               simple-audio-card,hp-det-gpios = <&gpio1 RK_PD5 GPIO_ACTIVE_HIGH>;
> +               simple-audio-card,mclk-fs = <256>;
> +               simple-audio-card,name = "rockchip,es8388";
> +               simple-audio-card,routing =
> +                       "Headphones", "LOUT1",
> +                       "Headphones", "ROUT1",
> +                       "LINPUT1", "Microphone Jack",
> +                       "RINPUT1", "Microphone Jack",
> +                       "LINPUT2", "Onboard Microphone",
> +                       "RINPUT2", "Onboard Microphone";
> +               simple-audio-card,widgets =
> +                       "Microphone", "Microphone Jack",
> +                       "Microphone", "Onboard Microphone",
> +                       "Headphone", "Headphones";
> +
> +               simple-audio-card,cpu {
> +                       sound-dai = <&i2s2_2ch>;
> +               };
> +
> +               masterdai: simple-audio-card,codec {
> +                       sound-dai = <&es8388>;
> +                       system-clock-frequency = <12288000>;
> +               };
> +       };
> +
> +       pwm-leds {
> +               compatible = "pwm-leds";
> +
> +               led-0 {
> +                       color = <LED_COLOR_ID_BLUE>;
> +                       function = LED_FUNCTION_STATUS;
> +                       linux,default-trigger = "heartbeat";
> +                       max-brightness = <255>;
> +                       pwms = <&pwm15 0 1000000 0>;
> +               };
> +
> +               led-1 {
> +                       color = <LED_COLOR_ID_GREEN>;
> +                       function = LED_FUNCTION_ACTIVITY;
> +                       linux,default-trigger = "heartbeat";
> +                       max-brightness = <255>;
> +                       pwms = <&pwm3 0 1000000 0>;
> +               };
> +       };
> +
> +       fan: pwm-fan {
> +               compatible = "pwm-fan";
> +               #cooling-cells = <2>;
> +               cooling-levels = <0 50 100 150 200 255>;
> +               fan-supply = <&vcc5v0_sys>;
> +               pwms = <&pwm2 0 20000000 0>;
> +       };
> +
> +       vcc3v3_dp: regulator-vcc3v3-dp {
> +               compatible = "regulator-fixed";
> +               enable-active-high;
> +               gpios = <&gpio3 RK_PC2 GPIO_ACTIVE_HIGH>;

Please don't forget to add explicit pinctrl nodes for each GPIO pin
you use (here and in other places like this). These GPIOs happen to
work on Linux without configuring their pin control first, but that is
pure luck and coincidence due to how the respective Linux subsystems
are wired together, and if you ever need to use this device tree in
e.g. U-boot (which also derives its DTS from the Linux kernel tree) it
will break there.

> +               regulator-always-on;
> +               regulator-boot-on;

Does it have to be always-on, boot-on? This looks like a hack to work
around the fact that you didn't define the bridge node, which uses
this as its supply. Please model the dependencies explicitly - most
likely that will let you drop these attributes.

> +               regulator-max-microvolt = <3300000>;
> +               regulator-min-microvolt = <3300000>;

It's two separate regulators on your schematic, one DCDC at 1.25V and
the other a load switch at 3.3V, driving six separate voltage inputs
of the DP bridge. They are both controlled by the same GPIO pin
though, so _maybe_ it's okay to have just one "virtual" node like this
to model them together. Would be great for the DT maintainers to weigh
in on this.

> +               regulator-name = "vcc3v3_dp";
> +               vin-supply = <&vcc_3v3_s3>;
> +       };
> +
> +       vcc3v3_phy1: regulator-vcc3v3-phy1 {
> +               compatible = "regulator-fixed";
> +               enable-active-high;
> +               gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_HIGH>;
> +               regulator-boot-on;

See above

> +               regulator-max-microvolt = <3300000>;
> +               regulator-min-microvolt = <3300000>;
> +               regulator-name = "vcc3v3_phy1";
> +               startup-delay-us = <50000>;
> +               vin-supply = <&vcc_3v3_s3>;
> +       };
> +
> +       vcc5v0_otg: regulator-vcc5v0-otg {
> +               compatible = "regulator-fixed";
> +               enable-active-high;
> +               gpios = <&gpio0 RK_PC4 GPIO_ACTIVE_HIGH>;
> +               pinctrl-names = "default";
> +               pinctrl-0 = <&vcc5v0_otg_en>;
> +               regulator-max-microvolt = <5000000>;
> +               regulator-min-microvolt = <5000000>;
> +               regulator-name = "vcc5v0_otg";
> +               vin-supply = <&vcc5v0_sys>;
> +       };
> +
> +       sdio_pwrseq: sdio-pwrseq {
> +               compatible = "mmc-pwrseq-simple";
> +               clocks = <&hym8563>;
> +               clock-names = "ext_clock";
> +               post-power-on-delay-ms = <200>;
> +               reset-gpios = <&gpio0 RK_PD0 GPIO_ACTIVE_LOW>;

This GPIO also needs a pinctrl

> +       };
> +
> +       typea_con: usb-a-connector {
> +               compatible = "usb-a-connector";
> +               data-role = "host";
> +               label = "USB3 Type-A";
> +               power-role = "source";
> +               vbus-supply = <&vcc5v0_otg>;
> +       };
> +};
> +
> +&dp0 {
> +       pinctrl-names = "default";
> +       pinctrl-0 = <&dp0m0_pins>;

This switches your HPD pin to the native DP controller handling
(DP0_HPDIN_M0), so the GPIO bits you've patched into the controller
driver aren't even used, and it doesn't look like you tested that code
path.

> +       status = "okay";
> +};
> +
> +&dp0_in {
> +       dp0_in_vp1: endpoint {
> +               remote-endpoint = <&vp1_out_dp0>;
> +       };
> +};
> +
> +&dp0_out {
> +       dp0_out_con: endpoint {
> +               remote-endpoint = <&dp_con_in>;

This will need to be rewritten once you add the proper bridge chain
leading up to the HDMI type A connector.

> +       };
> +};
> +
> +&i2c1 {
> +       pinctrl-names = "default";
> +       pinctrl-0 = <&i2c1m4_xfer>;
> +       status = "okay";
> +};
> +
> +&i2c3 {
> +       pinctrl-names = "default";
> +       pinctrl-0 = <&i2c3m0_xfer>;
> +       status = "okay";
> +
> +       es8388: audio-codec@11 {
> +               compatible = "everest,es8388", "everest,es8328";
> +               reg = <0x11>;
> +               #sound-dai-cells = <0>;
> +               AVDD-supply = <&vcc_3v3_s0>;

Are you sure? Schematic says VCCA_3V3_S0, which is a different
regulator (PLDO4 output of the PMIC)

> +               DVDD-supply = <&vcc_1v8_s0>;

Schematic says VCCA_1V8_S0, which is a different regulator (PLDO1
output of the PMIC)

> +               HPVDD-supply = <&vcc_3v3_s0>;

Schematic says VCCA_3V3_S0

> +               PVDD-supply = <&vcc_3v3_s0>;

Schematic says VCCA_1V8_S0

> +               assigned-clock-rates = <12288000>;
> +               assigned-clocks = <&cru I2S2_2CH_MCLKOUT>;
> +               clocks = <&cru I2S2_2CH_MCLKOUT>;
> +               pinctrl-names = "default";
> +               pinctrl-0 = <&i2s2m1_mclk>;
> +       };
> +};
> +
> +&i2c4 {
> +       pinctrl-names = "default";
> +       pinctrl-0 = <&i2c4m3_xfer>;
> +       status = "okay";
> +};
> +
> +&i2s2_2ch {
> +       pinctrl-0 = <&i2s2m1_lrck &i2s2m1_sclk
> +                    &i2s2m1_sdi &i2s2m1_sdo>;
> +       status = "okay";
> +};
> +
> +&package_thermal {
> +       polling-delay = <1000>;
> +
> +       cooling-maps {
> +               map0 {
> +                       trip = <&package_fan0>;
> +                       cooling-device = <&fan THERMAL_NO_LIMIT 1>;
> +               };
> +
> +               map1 {
> +                       trip = <&package_fan1>;
> +                       cooling-device = <&fan 2 THERMAL_NO_LIMIT>;
> +               };
> +       };
> +
> +       trips {
> +               package_fan0: package-fan0 {
> +                       hysteresis = <2000>;
> +                       temperature = <55000>;
> +                       type = "active";
> +               };
> +
> +               package_fan1: package-fan1 {
> +                       hysteresis = <2000>;
> +                       temperature = <65000>;
> +                       type = "active";
> +               };
> +       };
> +};
> +
> +/* NVMe */
> +&pcie2x1l1 {
> +       pinctrl-names = "default";
> +       pinctrl-0 = <&pcie30x1m1_1_clkreqn &pcie30x1m1_1_waken>;
> +       reset-gpios = <&gpio4 RK_PA2 GPIO_ACTIVE_HIGH>;

The GPIO also needs a pinctrl

> +       supports-clkreq;
> +       vpcie3v3-supply = <&vcc_3v3_s3>;
> +       status = "okay";
> +};
> +
> +/* NIC */
> +&pcie2x1l2 {
> +       reset-gpios = <&gpio3 RK_PD1 GPIO_ACTIVE_HIGH>;

The GPIO also needs a pinctrl

> +       vpcie3v3-supply = <&vcc3v3_phy1>;
> +       status = "okay";
> +};
> +
> +&pinctrl {
> +       bluetooth {
> +               bt_wake_gpio: bt-wake-pin {
> +                       rockchip,pins = <0 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>;
> +               };
> +
> +               bt_wake_host_irq: bt-wake-host-irq {
> +                       rockchip,pins = <0 RK_PC5 RK_FUNC_GPIO &pcfg_pull_down>;
> +               };
> +       };
> +
> +       usb {
> +               vcc5v0_otg_en: vcc5v0-otg-en {
> +                       rockchip,pins = <0 RK_PC4 RK_FUNC_GPIO &pcfg_pull_none>;
> +               };
> +       };
> +
> +       wlan {
> +               wifi_host_wake_irq: wifi-host-wake-irq {
> +                       rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_down>;
> +               };
> +       };
> +};
> +
> +&pwm15 {
> +       pinctrl-names = "default";
> +       pinctrl-0 = <&pwm15m2_pins>;
> +       status = "okay";
> +};
> +
> +&pwm2 {
> +       pinctrl-names = "default";
> +       pinctrl-0 = <&pwm2m1_pins>;
> +       status = "okay";
> +};
> +
> +&pwm3 {
> +       pinctrl-names = "default";
> +       pinctrl-0 = <&pwm3m2_pins>;
> +       status = "okay";
> +};
> +
> +&sdhci {
> +       status = "okay";
> +};
> +
> +&sdio {
> +       #address-cells = <1>;
> +       #size-cells = <0>;
> +       bus-width = <4>;
> +       cap-sd-highspeed;
> +       cap-sdio-irq;
> +       keep-power-in-suspend;
> +       max-frequency = <150000000>;
> +       mmc-pwrseq = <&sdio_pwrseq>;
> +       no-mmc;
> +       no-sd;
> +       non-removable;
> +       sd-uhs-sdr104;
> +       status = "okay";
> +
> +       ap6256: wifi@1 {
> +               compatible = "brcm,bcm43456-fmac", "brcm,bcm4329-fmac";
> +               reg = <1>;
> +               interrupt-names = "host-wake";
> +               interrupt-parent = <&gpio0>;
> +               interrupts = <RK_PA0 IRQ_TYPE_LEVEL_HIGH>;
> +               pinctrl-names = "default";
> +               pinctrl-0 = <&wifi_host_wake_irq>;
> +       };
> +};
> +
> +&uart9 {
> +       pinctrl-names = "default";
> +       pinctrl-0 = <&uart9m2_xfer &uart9m2_ctsn &uart9m2_rtsn>;
> +       uart-has-rtscts;
> +       status = "okay";
> +
> +       bluetooth {
> +               compatible = "brcm,bcm4345c5";
> +               clocks = <&hym8563>;
> +               clock-names = "lpo";
> +               device-wakeup-gpios = <&gpio0 RK_PC6 GPIO_ACTIVE_HIGH>;
> +               interrupt-names = "host-wakeup";
> +               interrupt-parent = <&gpio0>;
> +               interrupts = <RK_PC5 IRQ_TYPE_LEVEL_HIGH>;
> +               max-speed = <1500000>;
> +               pinctrl-names = "default";
> +               pinctrl-0 = <&bt_wake_host_irq &bt_wake_gpio>;
> +               shutdown-gpios = <&gpio0 RK_PD5 GPIO_ACTIVE_HIGH>;
> +               vbat-supply = <&vcc_3v3_s3>;
> +               vddio-supply = <&vcc_1v8_s3>;
> +       };
> +};
> +
> +&usb_host0_xhci {
> +       dr_mode = "host";
> +};
> +
> +&usbdp_phy0 {
> +       rockchip,dp-lane-mux = <0 1>;

I'm wondering if the DP controller's "out" endpoint should go to the
PHY instead of directly to the connector/bridge. That would describe
the hardware better.

> +};
> +
> +&vp1 {
> +       vp1_out_dp0: endpoint@a {
> +               reg = <ROCKCHIP_VOP2_EP_DP0>;
> +               remote-endpoint = <&dp0_in_vp1>;
> +       };
> +};
> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-dp.c b/drivers/gpu/drm/bridge/synopsys/dw-dp.c
> index fd23ca2834b0..b58f57b69b22 100644
> --- a/drivers/gpu/drm/bridge/synopsys/dw-dp.c
> +++ b/drivers/gpu/drm/bridge/synopsys/dw-dp.c
> @@ -8,6 +8,7 @@
>   */
>  #include <linux/bitfield.h>
>  #include <linux/clk.h>
> +#include <linux/gpio/consumer.h>
>  #include <linux/iopoll.h>
>  #include <linux/irq.h>
>  #include <linux/media-bus-format.h>
> @@ -330,6 +331,8 @@ struct dw_dp {
>         u8 pixel_mode;
>
>         DECLARE_BITMAP(sdp_reg_bank, SDP_REG_BANK_SIZE);
> +
> +       struct gpio_desc *hpd_gpiod;
>  };
>
>  enum {
> @@ -481,6 +484,9 @@ static bool dw_dp_hpd_detect(struct dw_dp *dp)
>  {
>         u32 value;
>
> +       if (dp->hpd_gpiod)
> +               return gpiod_get_value_cansleep(dp->hpd_gpiod);
> +
>         regmap_read(dp->regmap, DW_DP_HPD_STATUS, &value);
>
>         return FIELD_GET(HPD_STATE, value) == DW_DP_HPD_STATE_PLUG;
> @@ -2002,6 +2008,12 @@ struct dw_dp *dw_dp_bind(struct device *dev, struct drm_encoder *encoder,
>                 return ERR_CAST(dp->regmap);
>         }
>
> +       dp->hpd_gpiod = devm_gpiod_get_optional(dev, "hpd", GPIOD_IN);

Not tested, not needed, why bother?..

Best regards,
Alexey

^ permalink raw reply

* Re: [PATCH v7 1/2] platform: Add initial synology microp driver
From: Onur Özkan @ 2026-04-11 16:55 UTC (permalink / raw)
  To: Markus Probst via B4 Relay
  Cc: Hans de Goede, Ilpo Järvinen, Bryan O'Donoghue,
	Lee Jones, Pavel Machek, Miguel Ojeda, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
	Trevor Gross, Danilo Krummrich, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Greg Kroah-Hartman, platform-driver-x86, linux-leds,
	devicetree, linux-kernel, rust-for-linux, Markus Probst
In-Reply-To: <20260411-synology_microp_initial-v7-1-9a3a094e763a@posteo.de>

On Sat, 11 Apr 2026 17:27:34 +0200
Markus Probst via B4 Relay <devnull+markus.probst.posteo.de@kernel.org> wrote:

> From: Markus Probst <markus.probst@posteo.de>
> 
> Add a initial synology microp driver, written in Rust.
> The driver targets a microcontroller found in Synology NAS devices. It
> currently only supports controlling of the power led, status led, alert
> led and usb led. Other components such as fan control or handling
> on-device buttons will be added once the required rust abstractions are
> there.
> 
> This driver can be used both on arm and x86, thus it goes into the root
> directory of drivers/platform.
> 
> Tested successfully on a Synology DS923+.
> 
> Signed-off-by: Markus Probst <markus.probst@posteo.de>
> ---
>  MAINTAINERS                                        |   5 +
>  drivers/platform/Kconfig                           |   2 +
>  drivers/platform/Makefile                          |   1 +
>  drivers/platform/synology_microp/Kconfig           |  13 +
>  drivers/platform/synology_microp/Makefile          |   3 +
>  drivers/platform/synology_microp/TODO              |   7 +
>  drivers/platform/synology_microp/command.rs        |  55 ++++
>  drivers/platform/synology_microp/led.rs            | 276 +++++++++++++++++++++
>  drivers/platform/synology_microp/model.rs          |  49 ++++
>  .../platform/synology_microp/synology_microp.rs    | 109 ++++++++
>  10 files changed, 520 insertions(+)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index a667f4efb66e..78c99d831431 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -25554,6 +25554,11 @@ F:	drivers/dma-buf/sync_*
>  F:	include/linux/sync_file.h
>  F:	include/uapi/linux/sync_file.h
>  
> +SYNOLOGY MICROP DRIVER
> +M:	Markus Probst <markus.probst@posteo.de>
> +S:	Maintained
> +F:	drivers/platform/synology_microp/
> +
>  SYNOPSYS ARC ARCHITECTURE
>  M:	Vineet Gupta <vgupta@kernel.org>
>  L:	linux-snps-arc@lists.infradead.org
> diff --git a/drivers/platform/Kconfig b/drivers/platform/Kconfig
> index 312788f249c9..996050566a4a 100644
> --- a/drivers/platform/Kconfig
> +++ b/drivers/platform/Kconfig
> @@ -22,3 +22,5 @@ source "drivers/platform/arm64/Kconfig"
>  source "drivers/platform/raspberrypi/Kconfig"
>  
>  source "drivers/platform/wmi/Kconfig"
> +
> +source "drivers/platform/synology_microp/Kconfig"
> diff --git a/drivers/platform/Makefile b/drivers/platform/Makefile
> index fa322e7f8716..2381872e9133 100644
> --- a/drivers/platform/Makefile
> +++ b/drivers/platform/Makefile
> @@ -15,3 +15,4 @@ obj-$(CONFIG_SURFACE_PLATFORMS)	+= surface/
>  obj-$(CONFIG_ARM64_PLATFORM_DEVICES)	+= arm64/
>  obj-$(CONFIG_BCM2835_VCHIQ)	+= raspberrypi/
>  obj-$(CONFIG_ACPI_WMI)		+= wmi/
> +obj-$(CONFIG_SYNOLOGY_MICROP)	+= synology_microp/
> diff --git a/drivers/platform/synology_microp/Kconfig b/drivers/platform/synology_microp/Kconfig
> new file mode 100644
> index 000000000000..7c4d8f2808f0
> --- /dev/null
> +++ b/drivers/platform/synology_microp/Kconfig
> @@ -0,0 +1,13 @@
> +# SPDX-License-Identifier: GPL-2.0
> +
> +config SYNOLOGY_MICROP
> +	tristate "Synology Microp driver"
> +	depends on LEDS_CLASS && LEDS_CLASS_MULTICOLOR
> +	depends on RUST_SERIAL_DEV_BUS_ABSTRACTIONS
> +	help
> +	  Enable support for the MCU found in Synology NAS devices.
> +
> +	  This is needed to properly shutdown and reboot the device, as well as
> +	  additional functionality like fan and LED control.
> +
> +	  This driver is work in progress and may not be fully functional.
> diff --git a/drivers/platform/synology_microp/Makefile b/drivers/platform/synology_microp/Makefile
> new file mode 100644
> index 000000000000..63585ccf76e4
> --- /dev/null
> +++ b/drivers/platform/synology_microp/Makefile
> @@ -0,0 +1,3 @@
> +# SPDX-License-Identifier: GPL-2.0
> +
> +obj-y += synology_microp.o
> diff --git a/drivers/platform/synology_microp/TODO b/drivers/platform/synology_microp/TODO
> new file mode 100644
> index 000000000000..1961a33115db
> --- /dev/null
> +++ b/drivers/platform/synology_microp/TODO
> @@ -0,0 +1,7 @@
> +TODO:
> +- add missing components:
> +  - handle on-device buttons (Power, Factory reset, "USB Copy")
> +  - handle fan failure
> +  - beeper
> +  - fan speed control
> +  - correctly perform device power-off and restart on Synology devices
> diff --git a/drivers/platform/synology_microp/command.rs b/drivers/platform/synology_microp/command.rs
> new file mode 100644
> index 000000000000..5b3dd715afac
> --- /dev/null
> +++ b/drivers/platform/synology_microp/command.rs
> @@ -0,0 +1,55 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +use kernel::{
> +    device::Bound,
> +    error::Result,
> +    serdev, //
> +};
> +
> +use crate::led;
> +
> +#[derive(Copy, Clone)]

Copy and Clone seem never used, please drop them (also see [1]).

[1]: https://rust-for-linux.zulipchat.com/#narrow/channel/509436-Nova/topic/clone.2Fcopy.20additions

> +#[expect(
> +    clippy::enum_variant_names,
> +    reason = "future variants will not end with Led"
> +)]
> +pub(crate) enum Command {
> +    PowerLed(led::State),
> +    StatusLed(led::StatusLedColor, led::State),
> +    AlertLed(led::State),
> +    UsbLed(led::State),
> +    EsataLed(led::State),
> +}
> +
> +impl Command {
> +    pub(crate) fn write(self, dev: &serdev::Device<Bound>) -> Result {
> +        dev.write_all(
> +            match self {
> +                Self::PowerLed(led::State::On) => &[0x34],
> +                Self::PowerLed(led::State::Blink) => &[0x35],
> +                Self::PowerLed(led::State::Off) => &[0x36],
> +
> +                Self::StatusLed(_, led::State::Off) => &[0x37],
> +                Self::StatusLed(led::StatusLedColor::Green, led::State::On) => &[0x38],
> +                Self::StatusLed(led::StatusLedColor::Green, led::State::Blink) => &[0x39],
> +                Self::StatusLed(led::StatusLedColor::Orange, led::State::On) => &[0x3A],
> +                Self::StatusLed(led::StatusLedColor::Orange, led::State::Blink) => &[0x3B],
> +
> +                Self::AlertLed(led::State::On) => &[0x4C, 0x41, 0x31],
> +                Self::AlertLed(led::State::Blink) => &[0x4C, 0x41, 0x32],
> +                Self::AlertLed(led::State::Off) => &[0x4C, 0x41, 0x33],
> +
> +                Self::UsbLed(led::State::On) => &[0x40],
> +                Self::UsbLed(led::State::Blink) => &[0x41],
> +                Self::UsbLed(led::State::Off) => &[0x42],
> +
> +                Self::EsataLed(led::State::On) => &[0x4C, 0x45, 0x31],
> +                Self::EsataLed(led::State::Blink) => &[0x4C, 0x45, 0x32],
> +                Self::EsataLed(led::State::Off) => &[0x4C, 0x45, 0x33],
> +            },
> +            serdev::Timeout::Max,
> +        )?;
> +        dev.wait_until_sent(serdev::Timeout::Max);
> +        Ok(())
> +    }
> +}
> diff --git a/drivers/platform/synology_microp/led.rs b/drivers/platform/synology_microp/led.rs
> new file mode 100644
> index 000000000000..a78a95588456
> --- /dev/null
> +++ b/drivers/platform/synology_microp/led.rs
> @@ -0,0 +1,276 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +use kernel::{
> +    device::Bound,
> +    devres::{
> +        self,
> +        Devres, //
> +    },
> +    led::{
> +        self,
> +        LedOps,
> +        MultiColorSubLed, //
> +    },
> +    new_mutex,
> +    prelude::*,
> +    serdev,
> +    str::CString,
> +    sync::Mutex, //
> +};
> +use pin_init::pin_init_scope;
> +
> +use crate::{
> +    command::Command,
> +    model::Model, //
> +};
> +
> +#[pin_data]
> +pub(crate) struct Data {
> +    #[pin]
> +    status: Devres<led::MultiColorDevice<StatusLedHandler>>,
> +    power_name: CString,
> +    #[pin]
> +    power: Devres<led::Device<LedHandler>>,
> +}
> +
> +impl Data {
> +    pub(super) fn register<'a>(
> +        dev: &'a serdev::Device<Bound>,
> +        model: &'a Model,
> +    ) -> impl PinInit<Self, Error> + 'a {
> +        pin_init_scope(move || {
> +            if let Some(color) = model.led_alert {
> +                let name = CString::try_from_fmt(fmt!("{}:alarm", color.as_c_str().to_str()?))?;
> +                devres::register(
> +                    dev.as_ref(),
> +                    led::DeviceBuilder::new().color(color).name(&name).build(
> +                        dev,
> +                        try_pin_init!(LedHandler {
> +                            blink <- new_mutex!(false),
> +                            command: Command::AlertLed,
> +                        }),
> +                    ),
> +                    GFP_KERNEL,
> +                )?;
> +            }
> +
> +            if model.led_usb_copy {
> +                devres::register(
> +                    dev.as_ref(),
> +                    led::DeviceBuilder::new()
> +                        .color(led::Color::Green)
> +                        .name(c"green:usb")
> +                        .build(
> +                            dev,
> +                            try_pin_init!(LedHandler {
> +                                blink <- new_mutex!(false),
> +                                command: Command::UsbLed,
> +                            }),
> +                        ),
> +                    GFP_KERNEL,
> +                )?;
> +            }
> +
> +            if model.led_esata {
> +                devres::register(
> +                    dev.as_ref(),
> +                    led::DeviceBuilder::new()
> +                        .color(led::Color::Green)
> +                        .name(c"green:esata")
> +                        .build(
> +                            dev,
> +                            try_pin_init!(LedHandler {
> +                                blink <- new_mutex!(false),
> +                                command: Command::EsataLed,
> +                            }),
> +                        ),
> +                    GFP_KERNEL,
> +                )?;
> +            }
> +
> +            Ok(try_pin_init!(Self {
> +                status <- led::DeviceBuilder::new()
> +                    .color(led::Color::Multi)
> +                    .name(c"multicolor:status")
> +                    .build_multicolor(
> +                        dev,
> +                        try_pin_init!(StatusLedHandler {
> +                            blink <- new_mutex!(false),
> +                        }),
> +                        StatusLedHandler::SUBLEDS,
> +                    ),
> +                power_name: CString::try_from_fmt(fmt!(
> +                    "{}:power",
> +                    model.led_power.as_c_str().to_str()?
> +                ))?,
> +                power <- led::DeviceBuilder::new()
> +                    .color(model.led_power)
> +                    .name(power_name)
> +                    .build(
> +                        dev,
> +                        try_pin_init!(LedHandler {
> +                            blink <- new_mutex!(true),
> +                            command: Command::PowerLed,
> +                        }),
> +                    ),
> +            }))
> +        })
> +    }
> +}
> +
> +#[derive(Copy, Clone)]
> +pub(crate) enum StatusLedColor {
> +    Green,
> +    Orange,
> +}
> +
> +#[derive(Copy, Clone)]
> +pub(crate) enum State {
> +    On,
> +    Blink,
> +    Off,
> +}
> +
> +#[pin_data]
> +struct LedHandler {
> +    #[pin]
> +    blink: Mutex<bool>,
> +    command: fn(State) -> Command,
> +}
> +
> +#[vtable]
> +impl LedOps for LedHandler {
> +    type Bus = serdev::Device<Bound>;
> +    type Mode = led::Normal;
> +    const BLOCKING: bool = true;
> +    const MAX_BRIGHTNESS: u32 = 1;
> +
> +    fn brightness_set(
> +        &self,
> +        dev: &Self::Bus,
> +        _classdev: &led::Device<Self>,
> +        brightness: u32,
> +    ) -> Result<()> {
> +        let mut blink = self.blink.lock();
> +        (self.command)(if brightness == 0 {
> +            *blink = false;
> +            State::Off
> +        } else if *blink {
> +            State::Blink
> +        } else {
> +            State::On
> +        })
> +        .write(dev)?;
> +
> +        Ok(())
> +    }
> +
> +    fn blink_set(
> +        &self,
> +        dev: &Self::Bus,
> +        _classdev: &led::Device<Self>,
> +        delay_on: &mut usize,
> +        delay_off: &mut usize,
> +    ) -> Result<()> {
> +        let mut blink = self.blink.lock();
> +
> +        (self.command)(if *delay_on == 0 && *delay_off != 0 {
> +            State::Off
> +        } else if *delay_on != 0 && *delay_off == 0 {
> +            State::On
> +        } else {
> +            *blink = true;
> +            *delay_on = 167;
> +            *delay_off = 167;

Perhaps using a named constant with a simple comment instead of a hard-coded
integer would help to clarify what 167 is.

- Onur

> +
> +            State::Blink
> +        })
> +        .write(dev)
> +    }
> +}
> +
> +#[pin_data]
> +struct StatusLedHandler {
> +    #[pin]
> +    blink: Mutex<bool>,
> +}
> +
> +impl StatusLedHandler {
> +    const SUBLEDS: &[MultiColorSubLed] = &[
> +        MultiColorSubLed::new(led::Color::Green).initial_intensity(1),
> +        MultiColorSubLed::new(led::Color::Orange),
> +    ];
> +}
> +
> +#[vtable]
> +impl LedOps for StatusLedHandler {
> +    type Bus = serdev::Device<Bound>;
> +    type Mode = led::MultiColor;
> +    const BLOCKING: bool = true;
> +    const MAX_BRIGHTNESS: u32 = 1;
> +
> +    fn brightness_set(
> +        &self,
> +        dev: &Self::Bus,
> +        classdev: &led::MultiColorDevice<Self>,
> +        brightness: u32,
> +    ) -> Result<()> {
> +        let mut blink = self.blink.lock();
> +        if brightness == 0 {
> +            *blink = false;
> +        }
> +
> +        let (color, subled_brightness) = if classdev.subleds()[1].intensity == 0 {
> +            (StatusLedColor::Green, classdev.subleds()[0].brightness)
> +        } else {
> +            (StatusLedColor::Orange, classdev.subleds()[1].brightness)
> +        };
> +
> +        Command::StatusLed(
> +            color,
> +            if subled_brightness == 0 {
> +                State::Off
> +            } else if *blink {
> +                State::Blink
> +            } else {
> +                State::On
> +            },
> +        )
> +        .write(dev)
> +    }
> +
> +    fn blink_set(
> +        &self,
> +        dev: &Self::Bus,
> +        classdev: &led::MultiColorDevice<Self>,
> +        delay_on: &mut usize,
> +        delay_off: &mut usize,
> +    ) -> Result<()> {
> +        let mut blink = self.blink.lock();
> +        *blink = true;
> +
> +        let (color, subled_intensity) = if classdev.subleds()[1].intensity == 0 {
> +            (StatusLedColor::Green, classdev.subleds()[0].intensity)
> +        } else {
> +            (StatusLedColor::Orange, classdev.subleds()[1].intensity)
> +        };
> +        Command::StatusLed(
> +            color,
> +            if *delay_on == 0 && *delay_off != 0 {
> +                *blink = false;
> +                State::Off
> +            } else if subled_intensity == 0 {
> +                State::Off
> +            } else if *delay_on != 0 && *delay_off == 0 {
> +                *blink = false;
> +                State::On
> +            } else {
> +                *delay_on = 167;
> +                *delay_off = 167;
> +
> +                State::Blink
> +            },
> +        )
> +        .write(dev)
> +    }
> +}
> diff --git a/drivers/platform/synology_microp/model.rs b/drivers/platform/synology_microp/model.rs
> new file mode 100644
> index 000000000000..715d8840f56b
> --- /dev/null
> +++ b/drivers/platform/synology_microp/model.rs
> @@ -0,0 +1,49 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +use kernel::led::Color;
> +
> +pub(crate) struct Model {
> +    pub(crate) led_power: Color,
> +    pub(crate) led_alert: Option<Color>,
> +    pub(crate) led_usb_copy: bool,
> +    pub(crate) led_esata: bool,
> +}
> +
> +impl Model {
> +    pub(super) const fn new() -> Self {
> +        Self {
> +            led_power: Color::Blue,
> +            led_alert: None,
> +            led_usb_copy: false,
> +            led_esata: false,
> +        }
> +    }
> +
> +    pub(super) const fn led_power(self, color: Color) -> Self {
> +        Self {
> +            led_power: color,
> +            ..self
> +        }
> +    }
> +
> +    pub(super) const fn led_alert(self, color: Color) -> Self {
> +        Self {
> +            led_alert: Some(color),
> +            ..self
> +        }
> +    }
> +
> +    pub(super) const fn led_esata(self) -> Self {
> +        Self {
> +            led_esata: true,
> +            ..self
> +        }
> +    }
> +
> +    pub(super) const fn led_usb_copy(self) -> Self {
> +        Self {
> +            led_usb_copy: true,
> +            ..self
> +        }
> +    }
> +}
> diff --git a/drivers/platform/synology_microp/synology_microp.rs b/drivers/platform/synology_microp/synology_microp.rs
> new file mode 100644
> index 000000000000..f02c4dade76c
> --- /dev/null
> +++ b/drivers/platform/synology_microp/synology_microp.rs
> @@ -0,0 +1,109 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +//! Synology Microp driver
> +
> +use kernel::{
> +    device,
> +    led::Color,
> +    of::{
> +        DeviceId,
> +        IdTable, //
> +    },
> +    of_device_table,
> +    prelude::*,
> +    serdev, //
> +};
> +use pin_init::pin_init_scope;
> +
> +use crate::model::Model;
> +
> +pub(crate) mod command;
> +mod led;
> +mod model;
> +
> +kernel::module_serdev_device_driver! {
> +    type: SynologyMicropDriver,
> +    name: "synology_microp",
> +    authors: ["Markus Probst <markus.probst@posteo.de>"],
> +    description: "Synology Microp driver",
> +    license: "GPL v2",
> +}
> +
> +#[rustfmt::skip]
> +of_device_table!(
> +    OF_TABLE,
> +    MODULE_OF_TABLE,
> +    Model,
> +    [
> +        // apollolake
> +        (DeviceId::new(c"synology,ds918p-microp"), Model::new()),
> +
> +        // evansport
> +        (DeviceId::new(c"synology,ds214play-microp"), Model::new()),
> +
> +        // geminilakenk
> +        (DeviceId::new(c"synology,ds225p-microp"), Model::new().led_usb_copy()),
> +        (DeviceId::new(c"synology,ds425p-microp"), Model::new()),
> +
> +        // pineview
> +        (DeviceId::new(c"synology,ds710p-microp"), Model::new().led_esata()),
> +        (DeviceId::new(c"synology,ds1010p-microp"), Model::new().led_alert(Color::Orange)),
> +
> +        // r1000
> +        (DeviceId::new(c"synology,ds923p-microp"), Model::new()),
> +        (DeviceId::new(c"synology,ds723p-microp"), Model::new()),
> +        (DeviceId::new(c"synology,ds1522p-microp"), Model::new()),
> +        (DeviceId::new(c"synology,rs422p-microp"), Model::new().led_power(Color::Green)),
> +
> +        // r1000nk
> +        (DeviceId::new(c"synology,ds725p-microp"), Model::new()),
> +
> +        // rtd1296
> +        (DeviceId::new(c"synology,ds118-microp"), Model::new()),
> +
> +        // rtd1619b
> +        (DeviceId::new(c"synology,ds124-microp"), Model::new()),
> +        (DeviceId::new(c"synolody,ds223-microp"), Model::new().led_usb_copy()),
> +        (DeviceId::new(c"synology,ds223j-microp"), Model::new()),
> +
> +        // v1000
> +        (DeviceId::new(c"synology,ds1823xsp-microp"), Model::new()),
> +        (DeviceId::new(c"synology,rs822p-microp"), Model::new().led_power(Color::Green)),
> +        (DeviceId::new(c"synology,rs1221p-microp"), Model::new().led_power(Color::Green)),
> +        (DeviceId::new(c"synology,rs1221rpp-microp"), Model::new().led_power(Color::Green)),
> +
> +        // v1000nk
> +        (DeviceId::new(c"synology,ds925p-microp"), Model::new()),
> +        (DeviceId::new(c"synology,ds1525p-microp"), Model::new()),
> +        (DeviceId::new(c"synology,ds1825p-microp"), Model::new()),
> +    ]
> +);
> +
> +#[pin_data]
> +struct SynologyMicropDriver {
> +    #[pin]
> +    led: led::Data,
> +}
> +
> +#[vtable]
> +impl serdev::Driver for SynologyMicropDriver {
> +    type IdInfo = Model;
> +    const OF_ID_TABLE: Option<IdTable<Self::IdInfo>> = Some(&OF_TABLE);
> +
> +    fn probe(
> +        dev: &serdev::Device<device::Core>,
> +        model: Option<&Model>,
> +    ) -> impl PinInit<Self, kernel::error::Error> {
> +        pin_init_scope(move || {
> +            let model = model.ok_or(EINVAL)?;
> +
> +            dev.set_baudrate(9600).map_err(|_| EINVAL)?;
> +            dev.set_flow_control(false);
> +            dev.set_parity(serdev::Parity::None)?;
> +
> +            Ok(try_pin_init!(Self {
> +                led <- led::Data::register(dev, model),
> +            }))
> +        })
> +    }
> +}
> 
> -- 
> 2.52.0
> 
> 

^ permalink raw reply

* Re: [PATCH v9 2/3] hwmon: ltc4283: Add support for the LTC4283 Swap Controller
From: Guenter Roeck @ 2026-04-11 15:54 UTC (permalink / raw)
  To: Nuno Sá, nuno.sa, linux-gpio, linux-hwmon, devicetree,
	linux-doc
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Jonathan Corbet,
	Linus Walleij, Bartosz Golaszewski
In-Reply-To: <2653dc70f42fd015b88e2744da257f6200603b50.camel@gmail.com>

On 4/11/26 05:38, Nuno Sá wrote:
> On Fri, 2026-04-10 at 16:27 -0700, Guenter Roeck wrote:
>> On 4/6/26 07:31, Nuno Sá via B4 Relay wrote:
>>> From: Nuno Sá <nuno.sa@analog.com>
>>>
>>> Support the LTC4283 Hot Swap Controller. The device features programmable
>>> current limit with foldback and independently adjustable inrush current to
>>> optimize the MOSFET safe operating area (SOA). The SOA timer limits MOSFET
>>> temperature rise for reliable protection against overstresses.
>>>
>>> An I2C interface and onboard ADC allow monitoring of board current,
>>> voltage, power, energy, and fault status.
>>>
>>> Signed-off-by: Nuno Sá <nuno.sa@analog.com>
>>
>> The patch still has some issues. Please see
>>
>> https://sashiko.dev/#/patchset/20260406-ltc4283-support-v9-0-b66cfc749261%40analog.com
>>
>> Specifically:
>>
>> - regmap_clear_bits() may not cause problems, but it is not the best
>>     choice either because the register was already read.
>>     It might be better to just write the value to be masked since
>>     both the register value and the mask are known.
> 
> Fair enough.
> 
>>
>> - I can't comment on the energy accuracy lost. That is your call.
>>
> 
> The AI might have a point. Maybe you know better but if I understood correctly,
> mul_u64_u64_div_u64() will handle the multiplication by using 128bits (when
> available) or if not, using clever tricks. And it should also handle overflows.
> 
> So my feeling is that we can simplify all of those check_overflow paths with the
> suggested API.
> 
>> - Clamping before multiplying is indeed wrong.
>>     You'll need to clamp before multiplying (and then possibly
>>     clamp again).
> 
> Yeah, the clamp change was just nonsense from me. What about about
> 
> val = clamp_val((u64)val * MILLI, ...)
> 
> ?
> 

I don't think that will work on systems where sizeof(long) == 64.
I'd suggest to just bite the bullet and clamp against LONG_MAX/MILLI
first.

> 
>> -  %*ph: The AI seems to have a point.
> 
> Indeed!
> 
> FWIW, I was already aware of the AI feedback but I'll just setup things locally and
> run the review before submitting again.
> 

The AI now copies you on new revisions. Please feel free to rely on that
(unless you have tokens to burn, of course ;-). Those AI reviews are cheap
for what they do, but they are expensive in absolute terms.

Thanks,
Guenter


^ permalink raw reply

* [PATCH v7 1/2] platform: Add initial synology microp driver
From: Markus Probst via B4 Relay @ 2026-04-11 15:27 UTC (permalink / raw)
  To: Hans de Goede, Ilpo Järvinen, Bryan O'Donoghue,
	Lee Jones, Pavel Machek, Miguel Ojeda, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
	Trevor Gross, Danilo Krummrich, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Greg Kroah-Hartman
  Cc: platform-driver-x86, linux-leds, devicetree, linux-kernel,
	rust-for-linux, Markus Probst
In-Reply-To: <20260411-synology_microp_initial-v7-0-9a3a094e763a@posteo.de>

From: Markus Probst <markus.probst@posteo.de>

Add a initial synology microp driver, written in Rust.
The driver targets a microcontroller found in Synology NAS devices. It
currently only supports controlling of the power led, status led, alert
led and usb led. Other components such as fan control or handling
on-device buttons will be added once the required rust abstractions are
there.

This driver can be used both on arm and x86, thus it goes into the root
directory of drivers/platform.

Tested successfully on a Synology DS923+.

Signed-off-by: Markus Probst <markus.probst@posteo.de>
---
 MAINTAINERS                                        |   5 +
 drivers/platform/Kconfig                           |   2 +
 drivers/platform/Makefile                          |   1 +
 drivers/platform/synology_microp/Kconfig           |  13 +
 drivers/platform/synology_microp/Makefile          |   3 +
 drivers/platform/synology_microp/TODO              |   7 +
 drivers/platform/synology_microp/command.rs        |  55 ++++
 drivers/platform/synology_microp/led.rs            | 276 +++++++++++++++++++++
 drivers/platform/synology_microp/model.rs          |  49 ++++
 .../platform/synology_microp/synology_microp.rs    | 109 ++++++++
 10 files changed, 520 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index a667f4efb66e..78c99d831431 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -25554,6 +25554,11 @@ F:	drivers/dma-buf/sync_*
 F:	include/linux/sync_file.h
 F:	include/uapi/linux/sync_file.h
 
+SYNOLOGY MICROP DRIVER
+M:	Markus Probst <markus.probst@posteo.de>
+S:	Maintained
+F:	drivers/platform/synology_microp/
+
 SYNOPSYS ARC ARCHITECTURE
 M:	Vineet Gupta <vgupta@kernel.org>
 L:	linux-snps-arc@lists.infradead.org
diff --git a/drivers/platform/Kconfig b/drivers/platform/Kconfig
index 312788f249c9..996050566a4a 100644
--- a/drivers/platform/Kconfig
+++ b/drivers/platform/Kconfig
@@ -22,3 +22,5 @@ source "drivers/platform/arm64/Kconfig"
 source "drivers/platform/raspberrypi/Kconfig"
 
 source "drivers/platform/wmi/Kconfig"
+
+source "drivers/platform/synology_microp/Kconfig"
diff --git a/drivers/platform/Makefile b/drivers/platform/Makefile
index fa322e7f8716..2381872e9133 100644
--- a/drivers/platform/Makefile
+++ b/drivers/platform/Makefile
@@ -15,3 +15,4 @@ obj-$(CONFIG_SURFACE_PLATFORMS)	+= surface/
 obj-$(CONFIG_ARM64_PLATFORM_DEVICES)	+= arm64/
 obj-$(CONFIG_BCM2835_VCHIQ)	+= raspberrypi/
 obj-$(CONFIG_ACPI_WMI)		+= wmi/
+obj-$(CONFIG_SYNOLOGY_MICROP)	+= synology_microp/
diff --git a/drivers/platform/synology_microp/Kconfig b/drivers/platform/synology_microp/Kconfig
new file mode 100644
index 000000000000..7c4d8f2808f0
--- /dev/null
+++ b/drivers/platform/synology_microp/Kconfig
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config SYNOLOGY_MICROP
+	tristate "Synology Microp driver"
+	depends on LEDS_CLASS && LEDS_CLASS_MULTICOLOR
+	depends on RUST_SERIAL_DEV_BUS_ABSTRACTIONS
+	help
+	  Enable support for the MCU found in Synology NAS devices.
+
+	  This is needed to properly shutdown and reboot the device, as well as
+	  additional functionality like fan and LED control.
+
+	  This driver is work in progress and may not be fully functional.
diff --git a/drivers/platform/synology_microp/Makefile b/drivers/platform/synology_microp/Makefile
new file mode 100644
index 000000000000..63585ccf76e4
--- /dev/null
+++ b/drivers/platform/synology_microp/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-y += synology_microp.o
diff --git a/drivers/platform/synology_microp/TODO b/drivers/platform/synology_microp/TODO
new file mode 100644
index 000000000000..1961a33115db
--- /dev/null
+++ b/drivers/platform/synology_microp/TODO
@@ -0,0 +1,7 @@
+TODO:
+- add missing components:
+  - handle on-device buttons (Power, Factory reset, "USB Copy")
+  - handle fan failure
+  - beeper
+  - fan speed control
+  - correctly perform device power-off and restart on Synology devices
diff --git a/drivers/platform/synology_microp/command.rs b/drivers/platform/synology_microp/command.rs
new file mode 100644
index 000000000000..5b3dd715afac
--- /dev/null
+++ b/drivers/platform/synology_microp/command.rs
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0
+
+use kernel::{
+    device::Bound,
+    error::Result,
+    serdev, //
+};
+
+use crate::led;
+
+#[derive(Copy, Clone)]
+#[expect(
+    clippy::enum_variant_names,
+    reason = "future variants will not end with Led"
+)]
+pub(crate) enum Command {
+    PowerLed(led::State),
+    StatusLed(led::StatusLedColor, led::State),
+    AlertLed(led::State),
+    UsbLed(led::State),
+    EsataLed(led::State),
+}
+
+impl Command {
+    pub(crate) fn write(self, dev: &serdev::Device<Bound>) -> Result {
+        dev.write_all(
+            match self {
+                Self::PowerLed(led::State::On) => &[0x34],
+                Self::PowerLed(led::State::Blink) => &[0x35],
+                Self::PowerLed(led::State::Off) => &[0x36],
+
+                Self::StatusLed(_, led::State::Off) => &[0x37],
+                Self::StatusLed(led::StatusLedColor::Green, led::State::On) => &[0x38],
+                Self::StatusLed(led::StatusLedColor::Green, led::State::Blink) => &[0x39],
+                Self::StatusLed(led::StatusLedColor::Orange, led::State::On) => &[0x3A],
+                Self::StatusLed(led::StatusLedColor::Orange, led::State::Blink) => &[0x3B],
+
+                Self::AlertLed(led::State::On) => &[0x4C, 0x41, 0x31],
+                Self::AlertLed(led::State::Blink) => &[0x4C, 0x41, 0x32],
+                Self::AlertLed(led::State::Off) => &[0x4C, 0x41, 0x33],
+
+                Self::UsbLed(led::State::On) => &[0x40],
+                Self::UsbLed(led::State::Blink) => &[0x41],
+                Self::UsbLed(led::State::Off) => &[0x42],
+
+                Self::EsataLed(led::State::On) => &[0x4C, 0x45, 0x31],
+                Self::EsataLed(led::State::Blink) => &[0x4C, 0x45, 0x32],
+                Self::EsataLed(led::State::Off) => &[0x4C, 0x45, 0x33],
+            },
+            serdev::Timeout::Max,
+        )?;
+        dev.wait_until_sent(serdev::Timeout::Max);
+        Ok(())
+    }
+}
diff --git a/drivers/platform/synology_microp/led.rs b/drivers/platform/synology_microp/led.rs
new file mode 100644
index 000000000000..a78a95588456
--- /dev/null
+++ b/drivers/platform/synology_microp/led.rs
@@ -0,0 +1,276 @@
+// SPDX-License-Identifier: GPL-2.0
+
+use kernel::{
+    device::Bound,
+    devres::{
+        self,
+        Devres, //
+    },
+    led::{
+        self,
+        LedOps,
+        MultiColorSubLed, //
+    },
+    new_mutex,
+    prelude::*,
+    serdev,
+    str::CString,
+    sync::Mutex, //
+};
+use pin_init::pin_init_scope;
+
+use crate::{
+    command::Command,
+    model::Model, //
+};
+
+#[pin_data]
+pub(crate) struct Data {
+    #[pin]
+    status: Devres<led::MultiColorDevice<StatusLedHandler>>,
+    power_name: CString,
+    #[pin]
+    power: Devres<led::Device<LedHandler>>,
+}
+
+impl Data {
+    pub(super) fn register<'a>(
+        dev: &'a serdev::Device<Bound>,
+        model: &'a Model,
+    ) -> impl PinInit<Self, Error> + 'a {
+        pin_init_scope(move || {
+            if let Some(color) = model.led_alert {
+                let name = CString::try_from_fmt(fmt!("{}:alarm", color.as_c_str().to_str()?))?;
+                devres::register(
+                    dev.as_ref(),
+                    led::DeviceBuilder::new().color(color).name(&name).build(
+                        dev,
+                        try_pin_init!(LedHandler {
+                            blink <- new_mutex!(false),
+                            command: Command::AlertLed,
+                        }),
+                    ),
+                    GFP_KERNEL,
+                )?;
+            }
+
+            if model.led_usb_copy {
+                devres::register(
+                    dev.as_ref(),
+                    led::DeviceBuilder::new()
+                        .color(led::Color::Green)
+                        .name(c"green:usb")
+                        .build(
+                            dev,
+                            try_pin_init!(LedHandler {
+                                blink <- new_mutex!(false),
+                                command: Command::UsbLed,
+                            }),
+                        ),
+                    GFP_KERNEL,
+                )?;
+            }
+
+            if model.led_esata {
+                devres::register(
+                    dev.as_ref(),
+                    led::DeviceBuilder::new()
+                        .color(led::Color::Green)
+                        .name(c"green:esata")
+                        .build(
+                            dev,
+                            try_pin_init!(LedHandler {
+                                blink <- new_mutex!(false),
+                                command: Command::EsataLed,
+                            }),
+                        ),
+                    GFP_KERNEL,
+                )?;
+            }
+
+            Ok(try_pin_init!(Self {
+                status <- led::DeviceBuilder::new()
+                    .color(led::Color::Multi)
+                    .name(c"multicolor:status")
+                    .build_multicolor(
+                        dev,
+                        try_pin_init!(StatusLedHandler {
+                            blink <- new_mutex!(false),
+                        }),
+                        StatusLedHandler::SUBLEDS,
+                    ),
+                power_name: CString::try_from_fmt(fmt!(
+                    "{}:power",
+                    model.led_power.as_c_str().to_str()?
+                ))?,
+                power <- led::DeviceBuilder::new()
+                    .color(model.led_power)
+                    .name(power_name)
+                    .build(
+                        dev,
+                        try_pin_init!(LedHandler {
+                            blink <- new_mutex!(true),
+                            command: Command::PowerLed,
+                        }),
+                    ),
+            }))
+        })
+    }
+}
+
+#[derive(Copy, Clone)]
+pub(crate) enum StatusLedColor {
+    Green,
+    Orange,
+}
+
+#[derive(Copy, Clone)]
+pub(crate) enum State {
+    On,
+    Blink,
+    Off,
+}
+
+#[pin_data]
+struct LedHandler {
+    #[pin]
+    blink: Mutex<bool>,
+    command: fn(State) -> Command,
+}
+
+#[vtable]
+impl LedOps for LedHandler {
+    type Bus = serdev::Device<Bound>;
+    type Mode = led::Normal;
+    const BLOCKING: bool = true;
+    const MAX_BRIGHTNESS: u32 = 1;
+
+    fn brightness_set(
+        &self,
+        dev: &Self::Bus,
+        _classdev: &led::Device<Self>,
+        brightness: u32,
+    ) -> Result<()> {
+        let mut blink = self.blink.lock();
+        (self.command)(if brightness == 0 {
+            *blink = false;
+            State::Off
+        } else if *blink {
+            State::Blink
+        } else {
+            State::On
+        })
+        .write(dev)?;
+
+        Ok(())
+    }
+
+    fn blink_set(
+        &self,
+        dev: &Self::Bus,
+        _classdev: &led::Device<Self>,
+        delay_on: &mut usize,
+        delay_off: &mut usize,
+    ) -> Result<()> {
+        let mut blink = self.blink.lock();
+
+        (self.command)(if *delay_on == 0 && *delay_off != 0 {
+            State::Off
+        } else if *delay_on != 0 && *delay_off == 0 {
+            State::On
+        } else {
+            *blink = true;
+            *delay_on = 167;
+            *delay_off = 167;
+
+            State::Blink
+        })
+        .write(dev)
+    }
+}
+
+#[pin_data]
+struct StatusLedHandler {
+    #[pin]
+    blink: Mutex<bool>,
+}
+
+impl StatusLedHandler {
+    const SUBLEDS: &[MultiColorSubLed] = &[
+        MultiColorSubLed::new(led::Color::Green).initial_intensity(1),
+        MultiColorSubLed::new(led::Color::Orange),
+    ];
+}
+
+#[vtable]
+impl LedOps for StatusLedHandler {
+    type Bus = serdev::Device<Bound>;
+    type Mode = led::MultiColor;
+    const BLOCKING: bool = true;
+    const MAX_BRIGHTNESS: u32 = 1;
+
+    fn brightness_set(
+        &self,
+        dev: &Self::Bus,
+        classdev: &led::MultiColorDevice<Self>,
+        brightness: u32,
+    ) -> Result<()> {
+        let mut blink = self.blink.lock();
+        if brightness == 0 {
+            *blink = false;
+        }
+
+        let (color, subled_brightness) = if classdev.subleds()[1].intensity == 0 {
+            (StatusLedColor::Green, classdev.subleds()[0].brightness)
+        } else {
+            (StatusLedColor::Orange, classdev.subleds()[1].brightness)
+        };
+
+        Command::StatusLed(
+            color,
+            if subled_brightness == 0 {
+                State::Off
+            } else if *blink {
+                State::Blink
+            } else {
+                State::On
+            },
+        )
+        .write(dev)
+    }
+
+    fn blink_set(
+        &self,
+        dev: &Self::Bus,
+        classdev: &led::MultiColorDevice<Self>,
+        delay_on: &mut usize,
+        delay_off: &mut usize,
+    ) -> Result<()> {
+        let mut blink = self.blink.lock();
+        *blink = true;
+
+        let (color, subled_intensity) = if classdev.subleds()[1].intensity == 0 {
+            (StatusLedColor::Green, classdev.subleds()[0].intensity)
+        } else {
+            (StatusLedColor::Orange, classdev.subleds()[1].intensity)
+        };
+        Command::StatusLed(
+            color,
+            if *delay_on == 0 && *delay_off != 0 {
+                *blink = false;
+                State::Off
+            } else if subled_intensity == 0 {
+                State::Off
+            } else if *delay_on != 0 && *delay_off == 0 {
+                *blink = false;
+                State::On
+            } else {
+                *delay_on = 167;
+                *delay_off = 167;
+
+                State::Blink
+            },
+        )
+        .write(dev)
+    }
+}
diff --git a/drivers/platform/synology_microp/model.rs b/drivers/platform/synology_microp/model.rs
new file mode 100644
index 000000000000..715d8840f56b
--- /dev/null
+++ b/drivers/platform/synology_microp/model.rs
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: GPL-2.0
+
+use kernel::led::Color;
+
+pub(crate) struct Model {
+    pub(crate) led_power: Color,
+    pub(crate) led_alert: Option<Color>,
+    pub(crate) led_usb_copy: bool,
+    pub(crate) led_esata: bool,
+}
+
+impl Model {
+    pub(super) const fn new() -> Self {
+        Self {
+            led_power: Color::Blue,
+            led_alert: None,
+            led_usb_copy: false,
+            led_esata: false,
+        }
+    }
+
+    pub(super) const fn led_power(self, color: Color) -> Self {
+        Self {
+            led_power: color,
+            ..self
+        }
+    }
+
+    pub(super) const fn led_alert(self, color: Color) -> Self {
+        Self {
+            led_alert: Some(color),
+            ..self
+        }
+    }
+
+    pub(super) const fn led_esata(self) -> Self {
+        Self {
+            led_esata: true,
+            ..self
+        }
+    }
+
+    pub(super) const fn led_usb_copy(self) -> Self {
+        Self {
+            led_usb_copy: true,
+            ..self
+        }
+    }
+}
diff --git a/drivers/platform/synology_microp/synology_microp.rs b/drivers/platform/synology_microp/synology_microp.rs
new file mode 100644
index 000000000000..f02c4dade76c
--- /dev/null
+++ b/drivers/platform/synology_microp/synology_microp.rs
@@ -0,0 +1,109 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Synology Microp driver
+
+use kernel::{
+    device,
+    led::Color,
+    of::{
+        DeviceId,
+        IdTable, //
+    },
+    of_device_table,
+    prelude::*,
+    serdev, //
+};
+use pin_init::pin_init_scope;
+
+use crate::model::Model;
+
+pub(crate) mod command;
+mod led;
+mod model;
+
+kernel::module_serdev_device_driver! {
+    type: SynologyMicropDriver,
+    name: "synology_microp",
+    authors: ["Markus Probst <markus.probst@posteo.de>"],
+    description: "Synology Microp driver",
+    license: "GPL v2",
+}
+
+#[rustfmt::skip]
+of_device_table!(
+    OF_TABLE,
+    MODULE_OF_TABLE,
+    Model,
+    [
+        // apollolake
+        (DeviceId::new(c"synology,ds918p-microp"), Model::new()),
+
+        // evansport
+        (DeviceId::new(c"synology,ds214play-microp"), Model::new()),
+
+        // geminilakenk
+        (DeviceId::new(c"synology,ds225p-microp"), Model::new().led_usb_copy()),
+        (DeviceId::new(c"synology,ds425p-microp"), Model::new()),
+
+        // pineview
+        (DeviceId::new(c"synology,ds710p-microp"), Model::new().led_esata()),
+        (DeviceId::new(c"synology,ds1010p-microp"), Model::new().led_alert(Color::Orange)),
+
+        // r1000
+        (DeviceId::new(c"synology,ds923p-microp"), Model::new()),
+        (DeviceId::new(c"synology,ds723p-microp"), Model::new()),
+        (DeviceId::new(c"synology,ds1522p-microp"), Model::new()),
+        (DeviceId::new(c"synology,rs422p-microp"), Model::new().led_power(Color::Green)),
+
+        // r1000nk
+        (DeviceId::new(c"synology,ds725p-microp"), Model::new()),
+
+        // rtd1296
+        (DeviceId::new(c"synology,ds118-microp"), Model::new()),
+
+        // rtd1619b
+        (DeviceId::new(c"synology,ds124-microp"), Model::new()),
+        (DeviceId::new(c"synolody,ds223-microp"), Model::new().led_usb_copy()),
+        (DeviceId::new(c"synology,ds223j-microp"), Model::new()),
+
+        // v1000
+        (DeviceId::new(c"synology,ds1823xsp-microp"), Model::new()),
+        (DeviceId::new(c"synology,rs822p-microp"), Model::new().led_power(Color::Green)),
+        (DeviceId::new(c"synology,rs1221p-microp"), Model::new().led_power(Color::Green)),
+        (DeviceId::new(c"synology,rs1221rpp-microp"), Model::new().led_power(Color::Green)),
+
+        // v1000nk
+        (DeviceId::new(c"synology,ds925p-microp"), Model::new()),
+        (DeviceId::new(c"synology,ds1525p-microp"), Model::new()),
+        (DeviceId::new(c"synology,ds1825p-microp"), Model::new()),
+    ]
+);
+
+#[pin_data]
+struct SynologyMicropDriver {
+    #[pin]
+    led: led::Data,
+}
+
+#[vtable]
+impl serdev::Driver for SynologyMicropDriver {
+    type IdInfo = Model;
+    const OF_ID_TABLE: Option<IdTable<Self::IdInfo>> = Some(&OF_TABLE);
+
+    fn probe(
+        dev: &serdev::Device<device::Core>,
+        model: Option<&Model>,
+    ) -> impl PinInit<Self, kernel::error::Error> {
+        pin_init_scope(move || {
+            let model = model.ok_or(EINVAL)?;
+
+            dev.set_baudrate(9600).map_err(|_| EINVAL)?;
+            dev.set_flow_control(false);
+            dev.set_parity(serdev::Parity::None)?;
+
+            Ok(try_pin_init!(Self {
+                led <- led::Data::register(dev, model),
+            }))
+        })
+    }
+}

-- 
2.52.0



^ permalink raw reply related

* [PATCH v7 2/2] dt-bindings: embedded-controller: Add synology microp devices
From: Markus Probst via B4 Relay @ 2026-04-11 15:27 UTC (permalink / raw)
  To: Hans de Goede, Ilpo Järvinen, Bryan O'Donoghue,
	Lee Jones, Pavel Machek, Miguel Ojeda, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
	Trevor Gross, Danilo Krummrich, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Greg Kroah-Hartman
  Cc: platform-driver-x86, linux-leds, devicetree, linux-kernel,
	rust-for-linux, Markus Probst
In-Reply-To: <20260411-synology_microp_initial-v7-0-9a3a094e763a@posteo.de>

From: Markus Probst <markus.probst@posteo.de>

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.

The device has a different feature set depending on the Synology NAS
model, like having different number of fans, buttons and leds. Depending
on the architecture of the model, they also need a different system
shutdown behaviour.

Signed-off-by: Markus Probst <markus.probst@posteo.de>
---
 .../synology,ds923p-microp.yaml                    | 92 ++++++++++++++++++++++
 MAINTAINERS                                        |  1 +
 2 files changed, 93 insertions(+)

diff --git a/Documentation/devicetree/bindings/embedded-controller/synology,ds923p-microp.yaml b/Documentation/devicetree/bindings/embedded-controller/synology,ds923p-microp.yaml
new file mode 100644
index 000000000000..0a8fb1d8f314
--- /dev/null
+++ b/Documentation/devicetree/bindings/embedded-controller/synology,ds923p-microp.yaml
@@ -0,0 +1,92 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/embedded-controller/synology,ds923p-microp.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Synology NAS on-board Microcontroller
+
+maintainers:
+  - Markus Probst <markus.probst@posteo.de>
+
+description: |
+  Synology Microp is a microcontroller found in Synology NAS devices.
+  It is connected to a serial port on the host device.
+
+  It is necessary to properly shutdown and reboot the NAS device and
+  provides additional functionality such as led control, fan speed control,
+  a beeper and buttons on the NAS device.
+
+properties:
+  compatible:
+    enum:
+      - synology,ds923p-microp
+      - synology,ds918p-microp
+      - synology,ds214play-microp
+      - synology,ds225p-microp
+      - synology,ds425p-microp
+      - synology,ds710p-microp
+      - synology,ds1010p-microp
+      - synology,ds723p-microp
+      - synology,ds1522p-microp
+      - synology,rs422p-microp
+      - synology,ds725p-microp
+      - synology,ds118-microp
+      - synology,ds124-microp
+      - synology,ds223-microp
+      - synology,ds223j-microp
+      - synology,ds1823xsp-microp
+      - synology,rs822p-microp
+      - synology,rs1221p-microp
+      - synology,rs1221rpp-microp
+      - synology,ds925p-microp
+      - synology,ds1525p-microp
+      - synology,ds1825p-microp
+
+  fan-failure-gpios:
+    description: GPIOs needed to determine which fans stopped working on a fan failure event.
+    minItems: 2
+    maxItems: 3
+
+required:
+  - compatible
+
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - synology,ds214play-microp
+              - synology,ds225p-microp
+              - synology,ds710p-microp
+              - synology,ds723p-microp
+              - synology,ds725p-microp
+              - synology,ds118-microp
+              - synology,ds124-microp
+              - synology,ds223-microp
+              - synology,ds223j-microp
+              - synology,ds1823xsp-microp
+              - synology,rs822p-microp
+              - synology,rs1221p-microp
+              - synology,rs1221rpp-microp
+              - synology,ds1825p-microp
+    then:
+      properties:
+        fan-failure-gpios: false
+    else:
+      required:
+        - fan-failure-gpios
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/leds/common.h>
+    #include <dt-bindings/gpio/gpio.h>
+
+    embedded-controller {
+      compatible = "synology,ds923p-microp";
+
+      fan-failure-gpios = <&gpio 68 GPIO_ACTIVE_HIGH>, <&gpio 69 GPIO_ACTIVE_HIGH>;
+    };
diff --git a/MAINTAINERS b/MAINTAINERS
index 78c99d831431..72075c9a2016 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -25557,6 +25557,7 @@ F:	include/uapi/linux/sync_file.h
 SYNOLOGY MICROP DRIVER
 M:	Markus Probst <markus.probst@posteo.de>
 S:	Maintained
+F:	Documentation/devicetree/bindings/embedded-controller/synology,ds923p-microp.yaml
 F:	drivers/platform/synology_microp/
 
 SYNOPSYS ARC ARCHITECTURE

-- 
2.52.0



^ permalink raw reply related

* [PATCH v7 0/2] Introduce Synology Microp driver
From: Markus Probst via B4 Relay @ 2026-04-11 15:27 UTC (permalink / raw)
  To: Hans de Goede, Ilpo Järvinen, Bryan O'Donoghue,
	Lee Jones, Pavel Machek, Miguel Ojeda, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
	Trevor Gross, Danilo Krummrich, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Greg Kroah-Hartman
  Cc: platform-driver-x86, linux-leds, devicetree, linux-kernel,
	rust-for-linux, Markus Probst

Synology uses a microcontroller in their NAS devices connected to a
serial port to control certain LEDs, fan speeds, a beeper, to handle
proper shutdown and restart, buttons and fan failures.

This patch series depends on the rust led abstraction [1] and the rust
serdev abstraction [2].

This is only a initial version of the driver able to control LEDs.
The following rust abstractions would be required, to implement the
remaining features:
- hwmon (include/linux/hwmon.h)
- input (include/linux/input.h)
- sysoff handler + hardware protection shutdown (include/linux/reboot.h)

[1] https://lore.kernel.org/rust-for-linux/20260329-rust_leds-v13-0-21a599c5b2d1@posteo.de/
[2] https://lore.kernel.org/rust-for-linux/20260411-rust_serdev-v4-0-845e960c6627@posteo.de/

Signed-off-by: Markus Probst <markus.probst@posteo.de>
---
Changes in v7:
- remove list of compatible ids from commit msg
- explain what makes the different models not compatible in the commit msg
- remove unnecessary examples
- Link to v6: https://lore.kernel.org/r/20260405-synology_microp_initial-v6-0-08fde474b6c9@posteo.de

Changes in v6:
- moved devicetree bindings patch at the end of the set
- remove several patches
- move of id table from model.rs to synology_microp.rs
- remove the model! macro
- use if blocks in devicetree schema to narrow down the
  fan-failure-gpios property
- add multiple devicetree examples to test if blocks
- Link to v5: https://lore.kernel.org/r/20260329-synology_microp_initial-v5-0-27cb80bdf591@posteo.de

Changes in v5:
- add esata led support
- use different compatible for each model
- add visibility modifier to of_device_table macro
- fix match data missing when using PRP0001
- Link to v4: https://lore.kernel.org/r/20260320-synology_microp_initial-v4-0-0423ddb83ca4@posteo.de

Changes in v4:
- convert to monolithic driver and moved it into drivers/platform
- removed mfd rust abstraction
- moved dt-bindings to embedded-controller
- Link to v3: https://lore.kernel.org/r/20260313-synology_microp_initial-v3-0-ad6ac463a201@posteo.de

Changes in v3:
- remove `default n` from Kconfig entry, as n is the default already.
- select RUST_SERIAL_DEV_BUS_ABSTRACTIONS in Kconfig
- add mfd rust abstraction
- split core and led parts into their own driver. It should now be considered a
  MFD device.
- split led part of dt binding into its own file
- Link to v2: https://lore.kernel.org/r/20260308-synology_microp_initial-v2-0-9389963f31c5@posteo.de

Changes in v2:
- fix missing tabs in MAINTAINERS file
- remove word binding from patch subject
- add missing signed-off-by
- add missing help entry in Kconfig
- add missing spdx license headers
- remove no-check{,-cpu}-fan properties from the dt-bindings and replace
  them with the check_fan module parameter
- use patternProperties for leds in dt-bindings
- license dt-binding as GPL-2.0-only OR BSD-2-Clause
- move driver from staging tree into mfd tree and mark it as work in
  progress inside Kconfig
- only register alert and usb led if fwnode is present
- Link to v1: https://lore.kernel.org/r/20260306-synology_microp_initial-v1-0-fcffede6448c@posteo.de

---
Markus Probst (2):
      platform: Add initial synology microp driver
      dt-bindings: embedded-controller: Add synology microp devices

 .../synology,ds923p-microp.yaml                    |  92 +++++++
 MAINTAINERS                                        |   6 +
 drivers/platform/Kconfig                           |   2 +
 drivers/platform/Makefile                          |   1 +
 drivers/platform/synology_microp/Kconfig           |  13 +
 drivers/platform/synology_microp/Makefile          |   3 +
 drivers/platform/synology_microp/TODO              |   7 +
 drivers/platform/synology_microp/command.rs        |  55 ++++
 drivers/platform/synology_microp/led.rs            | 276 +++++++++++++++++++++
 drivers/platform/synology_microp/model.rs          |  49 ++++
 .../platform/synology_microp/synology_microp.rs    | 109 ++++++++
 11 files changed, 613 insertions(+)
---
base-commit: 0e5d0a0b5ca6ea4e391d6786266405c5871e0151
change-id: 20260306-synology_microp_initial-0f7dac7b7496
prerequisite-change-id: 20251217-rust_serdev-ee5481e9085c:v4
prerequisite-patch-id: 52b17274481cc770c257d8f95335293eca32a2c5
prerequisite-patch-id: eec47e5051640d08bcd34a9670b98804449cad52
prerequisite-patch-id: f24b68c71c3f69371e8ac0251efca0a023b31cc4
prerequisite-patch-id: d0686cf451ef899a06d468adfba51ccd84e6ff98
prerequisite-change-id: 20251114-rust_leds-a959f7c2f7f9:v13
prerequisite-patch-id: 818700f22dcb9676157c985f82762d7c607b861e
prerequisite-patch-id: b15ffa7d95d9260151bfb116b259c4473f721c82
prerequisite-patch-id: 8c47e0d107530f577a1be0b79f8ee791f95d3cbe



^ permalink raw reply

* Re: [PATCH v3 3/4] ARM: dts: qcom: msm8960: Add GSBI5 I2C controller
From: Dmitry Baryshkov @ 2026-04-11 15:20 UTC (permalink / raw)
  To: guptarud
  Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, linux-arm-msm, devicetree, linux-kernel,
	Konrad Dybcio
In-Reply-To: <20260401-expressatt_fuel_guage-v3-3-9674cfc0b5a2@gmail.com>

On Wed, Apr 01, 2026 at 01:32:15PM -0700, Rudraksha Gupta via B4 Relay wrote:
> From: Rudraksha Gupta <guptarud@gmail.com>
> 
> Add the I2C controller node for GSBI5 (gpio24/gpio25) alongside
> its pinctrl default and sleep states.
> 
> Assisted-by: Claude:claude-opus-4.6
> Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
> Signed-off-by: Rudraksha Gupta <guptarud@gmail.com>
> ---
>  arch/arm/boot/dts/qcom/qcom-msm8960.dtsi | 31 +++++++++++++++++++++++++++++++
>  1 file changed, 31 insertions(+)
> 

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>


-- 
With best wishes
Dmitry

^ permalink raw reply

* [PATCH RFC v2 11/11] arm64: dts: amlogic: odroid-c2: add support for I2S audio input
From: Valerio Setti @ 2026-04-11 14:57 UTC (permalink / raw)
  To: Jerome Brunet, Liam Girdwood, Mark Brown, Jaroslav Kysela,
	Takashi Iwai, Neil Armstrong, Kevin Hilman, Martin Blumenstingl,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Valerio Setti
  Cc: linux-kernel, linux-sound, linux-arm-kernel, linux-amlogic,
	devicetree
In-Reply-To: <20260411-audin-rfc-v2-0-4c8a6ec5fcab@baylibre.com>

- Enable AUDIN I2S decoder and all FIFO components;
- Add AUDIN I2S Decoder as AUX device to the GX sound card;
- Add AUDIN Capture frontend DAIs in the GX sound card;
- Add I2S input data routing to the GX sound card.

Note: in the routing part, usage of "AIU I2S Encoder Capture" as source
for "AUDIN I2S Decoder IN" is fine (despite the Encoder/Decoder mismatch).
This belong to the fact that the interface is implemented by "AIU I2S
Encoder", which was already existing (and named) before the AUDIN addition.

Signed-off-by: Valerio Setti <vsetti@baylibre.com>
---
 .../arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts | 34 ++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
index 5943bc810678edc81fe1a8e3eeae69786e27010c..54798e5b631fdc594cabc5876ab73a3a85944ab0 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
@@ -188,6 +188,12 @@ sound {
 				       <270950400>,
 				       <393216000>;
 
+		audio-aux-devs = <&audin_decoder_i2s>;
+		audio-routing = "AUDIN I2S Decoder IN", "AIU I2S Encoder Capture",
+				"AUDIN FIFO0 I2S IN", "AUDIN I2S Decoder OUT",
+				"AUDIN FIFO1 I2S IN", "AUDIN I2S Decoder OUT",
+				"AUDIN FIFO2 I2S IN", "AUDIN I2S Decoder OUT";
+
 		dai-link-0 {
 			sound-dai = <&aiu AIU_CPU CPU_I2S_FIFO>;
 		};
@@ -209,6 +215,18 @@ codec-0 {
 				sound-dai = <&hdmi_tx>;
 			};
 		};
+
+		dai-link-3 {
+			sound-dai = <&audin_fifo0>;
+		};
+
+		dai-link-4 {
+			sound-dai = <&audin_fifo1>;
+		};
+
+		dai-link-5 {
+			sound-dai = <&audin_fifo2>;
+		};
 	};
 };
 
@@ -216,6 +234,22 @@ &aiu {
 	status = "okay";
 };
 
+&audin_decoder_i2s {
+	status = "okay";
+};
+
+&audin_fifo0 {
+	status = "okay";
+};
+
+&audin_fifo1 {
+	status = "okay";
+};
+
+&audin_fifo2 {
+	status = "okay";
+};
+
 &cec_AO {
 	status = "okay";
 	pinctrl-0 = <&ao_cec_pins>;

-- 
2.39.5


^ permalink raw reply related

* [PATCH RFC v2 10/11] arm64: dts: amlogic: gx: add nodes for AUDIN decoder and FIFO
From: Valerio Setti @ 2026-04-11 14:57 UTC (permalink / raw)
  To: Jerome Brunet, Liam Girdwood, Mark Brown, Jaroslav Kysela,
	Takashi Iwai, Neil Armstrong, Kevin Hilman, Martin Blumenstingl,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Valerio Setti
  Cc: linux-kernel, linux-sound, linux-arm-kernel, linux-amlogic,
	devicetree
In-Reply-To: <20260411-audin-rfc-v2-0-4c8a6ec5fcab@baylibre.com>

Adding nodes for "amlogic,meson-gx-audin-decoder-i2s" and
"amlogic,meson-gx-audin-fifo". These provide support for I2S capture on
the GX platform.

Signed-off-by: Valerio Setti <vsetti@baylibre.com>
---
 arch/arm64/boot/dts/amlogic/meson-gx.dtsi   | 32 +++++++++++++++++++++++++++++
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 26 +++++++++++++++++++++++
 2 files changed, 58 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
index c1d8e81d95cb9b7758d8d12c230be13d4311e5e4..411b3e82f3ce1e535a23d9966ba82099d5be2282 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
@@ -331,6 +331,38 @@ aiu: audio-controller@5400 {
 				status = "disabled";
 			};
 
+			audin_decoder_i2s: audio-controller@a040 {
+				compatible = "amlogic,meson-gx-audin-decoder-i2s";
+				#sound-dai-cells = <0>;
+				sound-name-prefix = "AUDIN I2S Decoder";
+				reg = <0x0 0xa040 0x0 0x4>;
+				status = "disabled";
+			};
+
+			audin_fifo0: audio-controller@a080 {
+				compatible = "amlogic,meson-gx-audin-fifo";
+				#sound-dai-cells = <0>;
+				sound-name-prefix = "AUDIN FIFO0";
+				reg = <0x0 0xa080 0x0 0x1c>;
+				status = "disabled";
+			};
+
+			audin_fifo1: audio-controller@a0cc {
+				compatible = "amlogic,meson-gx-audin-fifo";
+				#sound-dai-cells = <0>;
+				sound-name-prefix = "AUDIN FIFO1";
+				reg = <0x0 0xa0cc 0x0 0x1c>;
+				status = "disabled";
+			};
+
+			audin_fifo2: audio-controller@a114 {
+				compatible = "amlogic,meson-gx-audin-fifo";
+				#sound-dai-cells = <0>;
+				sound-name-prefix = "AUDIN FIFO2";
+				reg = <0x0 0xa114 0x0 0x1c>;
+				status = "disabled";
+			};
+
 			uart_A: serial@84c0 {
 				compatible = "amlogic,meson-gx-uart";
 				reg = <0x0 0x84c0 0x0 0x18>;
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index a9c830a570cc6cd2875553fa9b0e3ef72a2f6478..71a47aa4c2fc72195386a11c905723b3c6f6943c 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -84,6 +84,32 @@ &aiu {
 	resets = <&reset RESET_AIU>;
 };
 
+&audin_decoder_i2s {
+	compatible = "amlogic,meson-gxbb-audin-decoder-i2s",
+		     "amlogic,meson-gx-audin-decoder-i2s";
+};
+
+&audin_fifo0 {
+	compatible = "amlogic,meson-gxbb-audin-fifo",
+		     "amlogic,meson-gx-audin-fifo";
+	clocks = <&clkc CLKID_I2S_SPDIF>;
+	clock-names = "i2s_input_clk";
+};
+
+&audin_fifo1 {
+	compatible = "amlogic,meson-gxbb-audin-fifo",
+		     "amlogic,meson-gx-audin-fifo";
+	clocks = <&clkc CLKID_I2S_SPDIF>;
+	clock-names = "i2s_input_clk";
+};
+
+&audin_fifo2 {
+	compatible = "amlogic,meson-gxbb-audin-fifo",
+		     "amlogic,meson-gx-audin-fifo";
+	clocks = <&clkc CLKID_I2S_SPDIF>;
+	clock-names = "i2s_input_clk";
+};
+
 &aobus {
 	pinctrl_aobus: pinctrl@14 {
 		compatible = "amlogic,meson-gxbb-aobus-pinctrl";

-- 
2.39.5


^ permalink raw reply related

* [PATCH RFC v2 09/11] ASoC: meson: gx-card: add support for AUDIN FIFO
From: Valerio Setti @ 2026-04-11 14:57 UTC (permalink / raw)
  To: Jerome Brunet, Liam Girdwood, Mark Brown, Jaroslav Kysela,
	Takashi Iwai, Neil Armstrong, Kevin Hilman, Martin Blumenstingl,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Valerio Setti
  Cc: linux-kernel, linux-sound, linux-arm-kernel, linux-amlogic,
	devicetree
In-Reply-To: <20260411-audin-rfc-v2-0-4c8a6ec5fcab@baylibre.com>

Slightly modify "gx_card_cpu_identify()" by making the compatible matching
string an input parameter. This allows to easily support also
"meson-gx-audin-fifo" with minimal changes.

Signed-off-by: Valerio Setti <vsetti@baylibre.com>
---
 sound/soc/meson/gx-card.c | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/sound/soc/meson/gx-card.c b/sound/soc/meson/gx-card.c
index b408cc2bbc9193ae56d02b4fcd05af8df3f93d80..1e48dbbf7324dfa6ca66026d944422dadf4204c0 100644
--- a/sound/soc/meson/gx-card.c
+++ b/sound/soc/meson/gx-card.c
@@ -65,10 +65,10 @@ static int gx_card_parse_i2s(struct snd_soc_card *card,
 }
 
 static int gx_card_cpu_identify(struct snd_soc_dai_link_component *c,
-				char *match)
+				char *compatible_match, char *dai_match)
 {
-	if (of_device_is_compatible(c->of_node, DT_PREFIX "aiu")) {
-		if (strstr(c->dai_name, match))
+	if (of_device_is_compatible(c->of_node, compatible_match)) {
+		if (strstr(c->dai_name, dai_match))
 			return 1;
 	}
 
@@ -94,21 +94,23 @@ static int gx_card_add_link(struct snd_soc_card *card, struct device_node *np,
 	if (ret)
 		return ret;
 
-	if (gx_card_cpu_identify(dai_link->cpus, "FIFO"))
+	if (gx_card_cpu_identify(dai_link->cpus, DT_PREFIX "aiu", "FIFO"))
 		return  meson_card_set_fe_link(card, dai_link, np, true);
+	else if (gx_card_cpu_identify(dai_link->cpus, DT_PREFIX "meson-gx-audin-fifo", "FIFO"))
+		return  meson_card_set_fe_link(card, dai_link, np, false);
 
 	ret = meson_card_set_be_link(card, dai_link, np);
 	if (ret)
 		return ret;
 
 	/* Or apply codec to codec params if necessary */
-	if (gx_card_cpu_identify(dai_link->cpus, "CODEC CTRL")) {
+	if (gx_card_cpu_identify(dai_link->cpus, DT_PREFIX "aiu", "CODEC CTRL")) {
 		dai_link->c2c_params = &codec_params;
 		dai_link->num_c2c_params = 1;
 	} else {
 		dai_link->no_pcm = 1;
 		/* Check if the cpu is the i2s encoder and parse i2s data */
-		if (gx_card_cpu_identify(dai_link->cpus, "I2S Encoder"))
+		if (gx_card_cpu_identify(dai_link->cpus, DT_PREFIX "aiu", "I2S Encoder"))
 			ret = gx_card_parse_i2s(card, np, index);
 	}
 

-- 
2.39.5


^ permalink raw reply related

* [PATCH RFC v2 08/11] ASoC: meson: aiu: add I2S Capture DAI
From: Valerio Setti @ 2026-04-11 14:57 UTC (permalink / raw)
  To: Jerome Brunet, Liam Girdwood, Mark Brown, Jaroslav Kysela,
	Takashi Iwai, Neil Armstrong, Kevin Hilman, Martin Blumenstingl,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Valerio Setti
  Cc: linux-kernel, linux-sound, linux-arm-kernel, linux-amlogic,
	devicetree
In-Reply-To: <20260411-audin-rfc-v2-0-4c8a6ec5fcab@baylibre.com>

Add capture stream to CPU_I2S_ENCODER. This is the final step to add
support for I2S capture following the recent addition of
"audin-decoder-i2s" and "audin-fifo".

As for the naming of the stream "I2S Encoder" is kept as base following
the same pattern used for the playback stream and with the goal to minimize
changes.

Signed-off-by: Valerio Setti <vsetti@baylibre.com>
---
 sound/soc/meson/aiu.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/sound/soc/meson/aiu.c b/sound/soc/meson/aiu.c
index bb3e0364190766ab4ce9ea3ebd313eecf220a244..2b6b94957b051976191d9b1e0dbdb4ca01ba2a94 100644
--- a/sound/soc/meson/aiu.c
+++ b/sound/soc/meson/aiu.c
@@ -153,6 +153,13 @@ static struct snd_soc_dai_driver aiu_cpu_dai_drv[] = {
 			.rates = SNDRV_PCM_RATE_8000_192000,
 			.formats = AIU_FORMATS,
 		},
+		.capture = {
+			.stream_name = "I2S Encoder Capture",
+			.channels_min = 2,
+			.channels_max = 2,
+			.rates = SNDRV_PCM_RATE_8000_192000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE,
+		},
 		.ops = &aiu_encoder_i2s_dai_ops,
 	},
 	[CPU_SPDIF_ENCODER] = {

-- 
2.39.5


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox