* [RFC PATCH 1/4] arm64: dts: st: fix the Engicam RMM RGB display pixel clock
2026-10-28 13:59 [RFC PATCH 0/4] Select the STM32MP25 LTDC pixel clock source for the RGB output Dario Binacchi
@ 2026-10-28 13:59 ` Dario Binacchi
2026-10-28 13:59 ` [RFC PATCH 2/4] clk: stm32: add STM32MP25 SYSCFG clock driver Dario Binacchi
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Dario Binacchi @ 2026-10-28 13:59 UTC (permalink / raw)
To: Alexandre Torgue, Stephen Boyd
Cc: Marek Vasut, Gabriel Fernandez, michael, linux-amarula,
Yannick Fertre, Raphael Gallais-Pou, Dario Binacchi,
Conor Dooley, Krzysztof Kozlowski, Maxime Coquelin, Rob Herring,
devicetree, linux-arm-kernel, linux-kernel, linux-stm32
On STM32MP255/257 the LTDC "lcd" clock is a fixed placeholder, since
with the LVDS output the pixel clock comes from the LVDS PHY. With the
RGB output the pixel clock is instead the LTDC kernel clock
(ck_ker_ltdc). Since no consumer references it, the clock is turned off
by clk_disable_unused() and its rate is never set. As a result, the LTDC
does not run and every commit times out:
[CRTC:42:crtc-0] vblank wait timed out
[drm] *ERROR* flip_done timed out
Use ck_ker_ltdc as "lcd" clock for the RGB panel overlay.
Fixes: bc7b07bda4e0 ("arm64: dts: st: support Engicam MicroGEA-STM32MP257D-RMM board")
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---
...2mp257d-engicam-microgea-rmm-overlay-rk050hr345-ct106a.dtso | 3 +++
1 file changed, 3 insertions(+)
diff --git a/arch/arm64/boot/dts/st/stm32mp257d-engicam-microgea-rmm-overlay-rk050hr345-ct106a.dtso b/arch/arm64/boot/dts/st/stm32mp257d-engicam-microgea-rmm-overlay-rk050hr345-ct106a.dtso
index f89641bdb23b..7be955be58ed 100644
--- a/arch/arm64/boot/dts/st/stm32mp257d-engicam-microgea-rmm-overlay-rk050hr345-ct106a.dtso
+++ b/arch/arm64/boot/dts/st/stm32mp257d-engicam-microgea-rmm-overlay-rk050hr345-ct106a.dtso
@@ -10,6 +10,7 @@
/dts-v1/;
/plugin/;
+#include <dt-bindings/clock/st,stm32mp25-rcc.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
@@ -35,6 +36,8 @@ touchscreen@38 {
};
<dc {
+ /* RGB output: the pixel clock is the LTDC kernel clock */
+ clocks = <&rcc CK_KER_LTDC>, <&rcc CK_BUS_LTDC>, <&syscfg>, <&lvds>;
pinctrl-names = "default", "sleep";
pinctrl-0 = <<dc_pins_a>;
pinctrl-1 = <<dc_sleep_pins_a>;
--
2.43.0
^ permalink raw reply [flat|nested] 5+ messages in thread* [RFC PATCH 2/4] clk: stm32: add STM32MP25 SYSCFG clock driver
2026-10-28 13:59 [RFC PATCH 0/4] Select the STM32MP25 LTDC pixel clock source for the RGB output Dario Binacchi
2026-10-28 13:59 ` [RFC PATCH 1/4] arm64: dts: st: fix the Engicam RMM RGB display pixel clock Dario Binacchi
@ 2026-10-28 13:59 ` Dario Binacchi
2026-10-28 13:59 ` [RFC PATCH 3/4] soc: st: stm32mp2-syscfg: register the STM32MP25 clock device Dario Binacchi
2026-10-28 13:59 ` [RFC PATCH 4/4] arm64: dts: st: select the Engicam RMM display pixel clock source Dario Binacchi
3 siblings, 0 replies; 5+ messages in thread
From: Dario Binacchi @ 2026-10-28 13:59 UTC (permalink / raw)
To: Alexandre Torgue, Stephen Boyd
Cc: Marek Vasut, Gabriel Fernandez, michael, linux-amarula,
Yannick Fertre, Raphael Gallais-Pou, Dario Binacchi,
Brian Masney, Jerome Brunet, Maxime Coquelin, linux-arm-kernel,
linux-clk, linux-kernel, linux-stm32
On STM32MP25 the LTDC pixel clock is selected in the SYSCFG
DISPLAYCLKCR register among the DSI byte lane clock, the LVDS PHY pixel
clock (reset value) and the LTDC kernel clock, the latter being the one
needed by the RGB (DPI) output.
The SYSCFG node already provides this clock ("#clock-cells = <0>"),
referenced by the LTDC as "ref" clock, but no driver registers it, so
the selection is stuck at the reset value and a display connected to
the LTDC RGB output can't work.
Add a driver registering this clock as a mux. The SYSCFG node is
already bound to the STM32MP2 SYSCFG driver, so the clock driver is
bound to an auxiliary device created by the latter, which shares the
SYSCFG node and regmap.
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---
drivers/clk/stm32/Kconfig | 12 +++
drivers/clk/stm32/Makefile | 1 +
drivers/clk/stm32/clk-stm32mp25-syscfg.c | 111 +++++++++++++++++++++++
3 files changed, 124 insertions(+)
create mode 100644 drivers/clk/stm32/clk-stm32mp25-syscfg.c
diff --git a/drivers/clk/stm32/Kconfig b/drivers/clk/stm32/Kconfig
index 5dbd75cde657..906044aacaa1 100644
--- a/drivers/clk/stm32/Kconfig
+++ b/drivers/clk/stm32/Kconfig
@@ -39,5 +39,17 @@ config COMMON_CLK_STM32MP257
help
Support for stm32mp25x SoC family clocks.
+config COMMON_CLK_STM32MP25_SYSCFG
+ tristate "Clock driver for stm32mp25x SYSCFG clocks"
+ depends on COMMON_CLK_STM32MP257
+ select AUXILIARY_BUS
+ select MFD_SYSCON
+ default COMMON_CLK_STM32MP257
+ help
+ Support for the clocks provided by the stm32mp25x SYSCFG, i.e.
+ the LTDC pixel clock source selection between the LTDC kernel
+ clock (RGB output), the LVDS PHY pixel clock and the DSI byte
+ lane clock.
+
endif
diff --git a/drivers/clk/stm32/Makefile b/drivers/clk/stm32/Makefile
index e04727b59449..8088d172651f 100644
--- a/drivers/clk/stm32/Makefile
+++ b/drivers/clk/stm32/Makefile
@@ -2,3 +2,4 @@ obj-$(CONFIG_COMMON_CLK_STM32MP135) += clk-stm32mp13.o clk-stm32-core.o reset-st
obj-$(CONFIG_COMMON_CLK_STM32MP157) += clk-stm32mp1.o reset-stm32.o
obj-$(CONFIG_COMMON_CLK_STM32MP215) += clk-stm32mp21.o clk-stm32-core.o reset-stm32.o
obj-$(CONFIG_COMMON_CLK_STM32MP257) += clk-stm32mp25.o clk-stm32-core.o reset-stm32.o
+obj-$(CONFIG_COMMON_CLK_STM32MP25_SYSCFG) += clk-stm32mp25-syscfg.o
diff --git a/drivers/clk/stm32/clk-stm32mp25-syscfg.c b/drivers/clk/stm32/clk-stm32mp25-syscfg.c
new file mode 100644
index 000000000000..1cb2459f0370
--- /dev/null
+++ b/drivers/clk/stm32/clk-stm32mp25-syscfg.c
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * STM32MP25 SYSCFG clocks
+ *
+ * Copyright (C) 2026 Amarula Solutions, Dario Binacchi <dario.binacchi@amarulasolutions.com>
+ */
+
+#include <linux/auxiliary_bus.h>
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+
+#define SYSCFG_DISPLAYCLKCR 0x5000
+#define DISPLAYCLKCR_DPIVSLVDS GENMASK(1, 0)
+
+/*
+ * The LTDC pixel clock source is selected in SYSCFG_DISPLAYCLKCR among
+ * the DSI byte lane clock, the LVDS PHY pixel clock (reset value) and
+ * the LTDC kernel clock, which is used with the RGB (DPI) output.
+ */
+static const char * const clk_pix_ltdc_parents[] = {
+ "txbyteclk", "clk_pix_lvds", "ck_ker_ltdc",
+};
+
+struct stm32mp25_syscfg_mux {
+ struct clk_hw hw;
+ struct regmap *regmap;
+};
+
+static inline struct stm32mp25_syscfg_mux *to_syscfg_mux(struct clk_hw *hw)
+{
+ return container_of(hw, struct stm32mp25_syscfg_mux, hw);
+}
+
+static u8 stm32mp25_syscfg_mux_get_parent(struct clk_hw *hw)
+{
+ struct stm32mp25_syscfg_mux *mux = to_syscfg_mux(hw);
+ unsigned int val;
+
+ regmap_read(mux->regmap, SYSCFG_DISPLAYCLKCR, &val);
+
+ return FIELD_GET(DISPLAYCLKCR_DPIVSLVDS, val);
+}
+
+static int stm32mp25_syscfg_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct stm32mp25_syscfg_mux *mux = to_syscfg_mux(hw);
+
+ return regmap_update_bits(mux->regmap, SYSCFG_DISPLAYCLKCR,
+ DISPLAYCLKCR_DPIVSLVDS,
+ FIELD_PREP(DISPLAYCLKCR_DPIVSLVDS, index));
+}
+
+static const struct clk_ops stm32mp25_syscfg_mux_ops = {
+ .get_parent = stm32mp25_syscfg_mux_get_parent,
+ .set_parent = stm32mp25_syscfg_mux_set_parent,
+ .determine_rate = clk_hw_determine_rate_no_reparent,
+};
+
+static int stm32mp25_syscfg_clk_probe(struct auxiliary_device *adev,
+ const struct auxiliary_device_id *id)
+{
+ struct device *dev = &adev->dev;
+ struct clk_init_data init = { };
+ struct stm32mp25_syscfg_mux *mux;
+ int ret;
+
+ mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);
+ if (!mux)
+ return -ENOMEM;
+
+ mux->regmap = syscon_node_to_regmap(dev->of_node);
+ if (IS_ERR(mux->regmap))
+ return dev_err_probe(dev, PTR_ERR(mux->regmap),
+ "failed to get the SYSCFG regmap\n");
+
+ init.name = "clk_pix_ltdc";
+ init.ops = &stm32mp25_syscfg_mux_ops;
+ init.parent_names = clk_pix_ltdc_parents;
+ init.num_parents = ARRAY_SIZE(clk_pix_ltdc_parents);
+ init.flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT;
+ mux->hw.init = &init;
+
+ ret = devm_clk_hw_register(dev, &mux->hw);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to register %s\n",
+ init.name);
+
+ return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, &mux->hw);
+}
+
+static const struct auxiliary_device_id stm32mp25_syscfg_clk_ids[] = {
+ { .name = "stm32mp2_syscfg.clk" },
+ { }
+};
+MODULE_DEVICE_TABLE(auxiliary, stm32mp25_syscfg_clk_ids);
+
+static struct auxiliary_driver stm32mp25_syscfg_clk_driver = {
+ .probe = stm32mp25_syscfg_clk_probe,
+ .id_table = stm32mp25_syscfg_clk_ids,
+};
+module_auxiliary_driver(stm32mp25_syscfg_clk_driver);
+
+MODULE_AUTHOR("Dario Binacchi <dario.binacchi@amarulasolutions.com>");
+MODULE_DESCRIPTION("STM32MP25 SYSCFG clock driver");
+MODULE_LICENSE("GPL");
--
2.43.0
^ permalink raw reply [flat|nested] 5+ messages in thread* [RFC PATCH 3/4] soc: st: stm32mp2-syscfg: register the STM32MP25 clock device
2026-10-28 13:59 [RFC PATCH 0/4] Select the STM32MP25 LTDC pixel clock source for the RGB output Dario Binacchi
2026-10-28 13:59 ` [RFC PATCH 1/4] arm64: dts: st: fix the Engicam RMM RGB display pixel clock Dario Binacchi
2026-10-28 13:59 ` [RFC PATCH 2/4] clk: stm32: add STM32MP25 SYSCFG clock driver Dario Binacchi
@ 2026-10-28 13:59 ` Dario Binacchi
2026-10-28 13:59 ` [RFC PATCH 4/4] arm64: dts: st: select the Engicam RMM display pixel clock source Dario Binacchi
3 siblings, 0 replies; 5+ messages in thread
From: Dario Binacchi @ 2026-10-28 13:59 UTC (permalink / raw)
To: Alexandre Torgue, Stephen Boyd
Cc: Marek Vasut, Gabriel Fernandez, michael, linux-amarula,
Yannick Fertre, Raphael Gallais-Pou, Dario Binacchi,
Fabrice Gasnier, Maxime Coquelin, linux-arm-kernel, linux-kernel,
linux-stm32
The STM32MP25 SYSCFG provides the LTDC pixel clock mux, whose driver is
an auxiliary driver since the SYSCFG node is bound to this driver.
Create the auxiliary device for the clock driver on STM32MP25.
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---
drivers/soc/st/Kconfig | 1 +
drivers/soc/st/stm32mp2-syscfg.c | 28 ++++++++++++++++++++++++++--
2 files changed, 27 insertions(+), 2 deletions(-)
diff --git a/drivers/soc/st/Kconfig b/drivers/soc/st/Kconfig
index 2a9d6a77be45..62bbe8c63238 100644
--- a/drivers/soc/st/Kconfig
+++ b/drivers/soc/st/Kconfig
@@ -5,6 +5,7 @@ config SOC_STM32MP2
tristate "STM32MP2 SoC family support"
depends on ARCH_STM32 || COMPILE_TEST
default ARCH_STM32 && ARM64
+ select AUXILIARY_BUS
select SOC_BUS
help
If you say yes here, you get support for the ST STM32MP2 family
diff --git a/drivers/soc/st/stm32mp2-syscfg.c b/drivers/soc/st/stm32mp2-syscfg.c
index 770321a4a6f7..300a949744c5 100644
--- a/drivers/soc/st/stm32mp2-syscfg.c
+++ b/drivers/soc/st/stm32mp2-syscfg.c
@@ -3,18 +3,42 @@
* Copyright 2026 Marek Vasut
*/
+#include <linux/auxiliary_bus.h>
#include <linux/module.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
+
+struct stm32mp2_syscfg_data {
+ bool has_clk;
+};
static int stm32mp2_syscfg_probe(struct platform_device *pdev)
{
- return devm_of_platform_populate(&pdev->dev);
+ const struct stm32mp2_syscfg_data *data;
+ struct device *dev = &pdev->dev;
+ int ret;
+
+ ret = devm_of_platform_populate(dev);
+ if (ret)
+ return ret;
+
+ data = device_get_match_data(dev);
+ if (data && data->has_clk &&
+ !devm_auxiliary_device_create(dev, "clk", NULL))
+ return dev_err_probe(dev, -ENODEV,
+ "failed to register the clock device\n");
+
+ return 0;
}
+static const struct stm32mp2_syscfg_data stm32mp25_syscfg_data = {
+ .has_clk = true,
+};
+
static const struct of_device_id stm32mp2_syscfg_ids[] = {
{ .compatible = "st,stm32mp23-syscfg" },
- { .compatible = "st,stm32mp25-syscfg" },
+ { .compatible = "st,stm32mp25-syscfg", .data = &stm32mp25_syscfg_data },
{ }
};
MODULE_DEVICE_TABLE(of, stm32mp2_syscfg_ids);
--
2.43.0
^ permalink raw reply [flat|nested] 5+ messages in thread* [RFC PATCH 4/4] arm64: dts: st: select the Engicam RMM display pixel clock source
2026-10-28 13:59 [RFC PATCH 0/4] Select the STM32MP25 LTDC pixel clock source for the RGB output Dario Binacchi
` (2 preceding siblings ...)
2026-10-28 13:59 ` [RFC PATCH 3/4] soc: st: stm32mp2-syscfg: register the STM32MP25 clock device Dario Binacchi
@ 2026-10-28 13:59 ` Dario Binacchi
3 siblings, 0 replies; 5+ messages in thread
From: Dario Binacchi @ 2026-10-28 13:59 UTC (permalink / raw)
To: Alexandre Torgue, Stephen Boyd
Cc: Marek Vasut, Gabriel Fernandez, michael, linux-amarula,
Yannick Fertre, Raphael Gallais-Pou, Dario Binacchi,
Conor Dooley, Krzysztof Kozlowski, Maxime Coquelin, Rob Herring,
devicetree, linux-arm-kernel, linux-kernel, linux-stm32
On STM32MP255/257 the LTDC pixel clock is selected by the SYSCFG
pixel clock mux, whose reset value is the LVDS PHY pixel clock. With
the RGB panel the LTDC is then clocked by the unused LVDS PHY, and every
commit times out:
[CRTC:42:crtc-0] vblank wait timed out
[drm] *ERROR* flip_done timed out
Select the LTDC kernel clock as pixel clock source in the RGB panel
overlay and, for consistency, without relying on the reset value, the
LVDS PHY pixel clock in the LVDS panel overlay.
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---
...57d-engicam-microgea-rmm-overlay-am-1280800w8tzqw-t00h.dtso | 3 +++
...2mp257d-engicam-microgea-rmm-overlay-rk050hr345-ct106a.dtso | 2 ++
2 files changed, 5 insertions(+)
diff --git a/arch/arm64/boot/dts/st/stm32mp257d-engicam-microgea-rmm-overlay-am-1280800w8tzqw-t00h.dtso b/arch/arm64/boot/dts/st/stm32mp257d-engicam-microgea-rmm-overlay-am-1280800w8tzqw-t00h.dtso
index 7655c1bf56b1..b44e1d3ddb1b 100644
--- a/arch/arm64/boot/dts/st/stm32mp257d-engicam-microgea-rmm-overlay-am-1280800w8tzqw-t00h.dtso
+++ b/arch/arm64/boot/dts/st/stm32mp257d-engicam-microgea-rmm-overlay-am-1280800w8tzqw-t00h.dtso
@@ -32,6 +32,9 @@ &framebuffer {
};
<dc {
+ /* LVDS output: the pixel clock is the LVDS PHY one */
+ assigned-clocks = <&syscfg>;
+ assigned-clock-parents = <&lvds>;
status = "okay";
port {
diff --git a/arch/arm64/boot/dts/st/stm32mp257d-engicam-microgea-rmm-overlay-rk050hr345-ct106a.dtso b/arch/arm64/boot/dts/st/stm32mp257d-engicam-microgea-rmm-overlay-rk050hr345-ct106a.dtso
index 7be955be58ed..7855086c33c7 100644
--- a/arch/arm64/boot/dts/st/stm32mp257d-engicam-microgea-rmm-overlay-rk050hr345-ct106a.dtso
+++ b/arch/arm64/boot/dts/st/stm32mp257d-engicam-microgea-rmm-overlay-rk050hr345-ct106a.dtso
@@ -38,6 +38,8 @@ touchscreen@38 {
<dc {
/* RGB output: the pixel clock is the LTDC kernel clock */
clocks = <&rcc CK_KER_LTDC>, <&rcc CK_BUS_LTDC>, <&syscfg>, <&lvds>;
+ assigned-clocks = <&syscfg>;
+ assigned-clock-parents = <&rcc CK_KER_LTDC>;
pinctrl-names = "default", "sleep";
pinctrl-0 = <<dc_pins_a>;
pinctrl-1 = <<dc_sleep_pins_a>;
--
2.43.0
^ permalink raw reply [flat|nested] 5+ messages in thread