public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
* [PATCH 00/26] Support display (and even more) on the BSH SMM S2/PRO boards
@ 2024-09-13  9:55 Dario Binacchi
  2024-09-13  9:55 ` [PATCH 01/26] clk: Propagate clk_set_rate() if CLK_SET_PARENT_RATE present for gate and mux Dario Binacchi
                   ` (26 more replies)
  0 siblings, 27 replies; 48+ messages in thread
From: Dario Binacchi @ 2024-09-13  9:55 UTC (permalink / raw)
  To: u-boot
  Cc: Fabio Estevam, linux-amarula, michael, Miquel Raynal,
	Dario Binacchi, AKASHI Takahiro, Alexander Dahl,
	Anatolij Gustschin, Andrzej Hajda, Anton Bambura,
	Ashok Reddy Soma, Devarsh Thakkar, Eugen Hristev, Fabio Estevam,
	Heinrich Schuchardt, Hou Zhiqiang, Igor Prusov, Igor Prusov,
	Jaehoon Chung, Jan Kiszka, Joe Hershberger, Jonas Schwöbel,
	Julien Masson, Liu Ying, Lukasz Majewski, Maksim Kiselev,
	Marcel Ziswiler, Marco Felsch, Marek Vasut, Marek Vasut,
	Martyn Welch, Mattijs Korpershoek, Minkyu Kang,
	NXP i.MX U-Boot Team, Neil Armstrong, Nicolas Heemeryck,
	Nikhil M Jain, Patrick Barsanti, Peng Fan, Peter Robinson,
	Sakari Ailus, Sam Protsenko, Sean Anderson, Simon Glass,
	Stefan Bosch, Stefano Babic, Svyatoslav Ryhel,
	Sébastien Szymanski, Tim Harvey, Tom Rini, Vinod Koul,
	Yang Xiwen, Ye Li, u-boot-amlogic


This series was created out of the need to supportsimple-framebuffer for
BSH boards SMM_S2 and SMM_S2PRO. To achieve this goal, it was necessary
to develop additional code and/or drivers for all the required components
(i. e. clock, power domain, video, etc.). This series has a Linux
counterpart that will also be submitted upstream as soon as possible.
Furthermore, given the overlap in topics with the recent series [1], we
are open to collaborate on the common parts to ensure proper development.

[1] https://lore.kernel.org/all/20240910101344.110633-1-miquel.raynal@bootlin.com/T/#mb7cd440abc6fcc0de205f577eb3225e1c1c76823


Dario Binacchi (6):
  boot: fdt_simplefb: add a debug message
  video: mxsfb: support simple frame-buffer
  video: bridge: samsung: support simple frame-buffer
  imx8mn_bsh_smm_s2/pro: support simple frame-buffer
  imx8mn_bsh_smm_s2/pro: enable simple frame-buffer
  imx8mn_bsh_smm_s2/pro: add splash screen with BSH logo

Michael Trimarchi (20):
  clk: Propagate clk_set_rate() if CLK_SET_PARENT_RATE present for gate
    and mux
  clk: imx8mn: Prevent clock critical path from disabling during
    reparent and set_rate
  clk: imx8mm: Prevent clock critical path from disabling during
    reparent and set_rate
  clk: clk-uclass: Implement CLK_OPS_PARENT_ENABLE
  clk: imx8mm: Mark IMX8MM_SYS_PLL2 and IMX8MM_SYS_PLL3 as enabled
  clk: imx8mn: Mark IMX8MN_SYS_PLL2 and IMX8MN_SYS_PLL3 as enabled
  clk: imx8mn: add video clocks support
  power: Add iMX8M block ctrl driver for dispmix
  video: Add video link framework
  video: bridge: Add check_timing interface
  video: dsi_host: add disable host interface
  video: Update mxsfb video drivers for iMX8MM/iMX8MN display
  video: Enable DM_UC_FLAG_SEQ_ALIAS for display and bridge
  phy: dphy: add support to calculate the timing based on hs_clk_rate
  phy: dphy: Correct lpx parameter and its derivatives(ta_{get,go,sure})
  phy: dphy: Correct clk_pre parameter
  lib: div64: sync with Linux
  video: bridge: Add Samsung DSIM bridge
  video: Add Synaptics R63353 panel driver
  imx8mn_bsh_smm_s2/pro: Enable display on reference design

 .../dts/imx8mn-bsh-smm-s2-u-boot-common.dtsi  |   23 +
 board/bsh/imx8mn_smm_s2/imx8mn_smm_s2.c       |   99 ++
 boot/fdt_simplefb.c                           |    2 +
 common/stdio.c                                |    4 +
 configs/imx8mn_bsh_smm_s2_defconfig           |   21 +
 configs/imx8mn_bsh_smm_s2pro_defconfig        |   21 +
 drivers/clk/clk-gate.c                        |    1 +
 drivers/clk/clk-mux.c                         |    2 +-
 drivers/clk/clk-uclass.c                      |   67 +-
 drivers/clk/clk.c                             |    9 +
 drivers/clk/imx/clk-imx8mm.c                  |   73 +-
 drivers/clk/imx/clk-imx8mn.c                  |  131 +-
 drivers/phy/meson-axg-mipi-dphy.c             |    2 +-
 drivers/phy/phy-core-mipi-dphy.c              |   36 +-
 drivers/power/domain/Kconfig                  |    6 +
 drivers/power/domain/Makefile                 |    1 +
 drivers/power/domain/imx8m-blk-ctrl.c         |  438 +++++
 drivers/power/domain/imx8m-power-domain.c     |  213 ++-
 drivers/video/Kconfig                         |   14 +
 drivers/video/Makefile                        |    2 +
 drivers/video/bridge/Kconfig                  |   13 +
 drivers/video/bridge/Makefile                 |    1 +
 drivers/video/bridge/samsung-dsi-host.c       | 1576 +++++++++++++++++
 drivers/video/bridge/samsung-dsim.c           |  151 ++
 drivers/video/bridge/samsung-dsim.h           |   20 +
 drivers/video/bridge/video-bridge-uclass.c    |   11 +
 drivers/video/display-uclass.c                |    1 +
 drivers/video/dsi-host-uclass.c               |   10 +
 drivers/video/mxsfb.c                         |  144 +-
 drivers/video/synaptics-r63353.c              |  228 +++
 drivers/video/video_link.c                    |  529 ++++++
 include/clk.h                                 |    9 +
 include/configs/imx8mn_bsh_smm_s2.h           |    1 +
 include/configs/imx8mn_bsh_smm_s2_common.h    |    4 +
 include/configs/imx8mn_bsh_smm_s2pro.h        |    1 +
 include/dsi_host.h                            |    8 +
 include/linux/clk-provider.h                  |    1 +
 include/linux/math64.h                        |  110 ++
 include/phy-mipi-dphy.h                       |    3 +
 include/video_bridge.h                        |   20 +
 include/video_link.h                          |   19 +
 tools/logos/bsh.bmp                           |  Bin 0 -> 10644 bytes
 42 files changed, 3942 insertions(+), 83 deletions(-)
 create mode 100644 drivers/power/domain/imx8m-blk-ctrl.c
 create mode 100644 drivers/video/bridge/samsung-dsi-host.c
 create mode 100644 drivers/video/bridge/samsung-dsim.c
 create mode 100644 drivers/video/bridge/samsung-dsim.h
 create mode 100644 drivers/video/synaptics-r63353.c
 create mode 100644 drivers/video/video_link.c
 create mode 100644 include/video_link.h
 create mode 100644 tools/logos/bsh.bmp

-- 
2.43.0


^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH 01/26] clk: Propagate clk_set_rate() if CLK_SET_PARENT_RATE present for gate and mux
  2024-09-13  9:55 [PATCH 00/26] Support display (and even more) on the BSH SMM S2/PRO boards Dario Binacchi
@ 2024-09-13  9:55 ` Dario Binacchi
  2024-09-13  9:55 ` [PATCH 02/26] clk: imx8mn: Prevent clock critical path from disabling during reparent and set_rate Dario Binacchi
                   ` (25 subsequent siblings)
  26 siblings, 0 replies; 48+ messages in thread
From: Dario Binacchi @ 2024-09-13  9:55 UTC (permalink / raw)
  To: u-boot
  Cc: Fabio Estevam, linux-amarula, michael, Miquel Raynal,
	Dario Binacchi, Alexander Dahl, Ashok Reddy Soma, Eugen Hristev,
	Igor Prusov, Jan Kiszka, Julien Masson, Lukasz Majewski,
	Marek Vasut, Mattijs Korpershoek, Sean Anderson, Simon Glass,
	Tom Rini, Yang Xiwen

From: Michael Trimarchi <michael@amarulasolutions.com>

Gate and mux does not have .set_rate operation, but they could have
CLK_SET_PARENT_RATE flag set. In that case it's usually possible to find a
parent up the tree which is capable of setting the rate (div, pll, etc).
Add clk_generic_set_rate to allow them to trasverse the clock tree.

Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---

 drivers/clk/clk-gate.c       |  1 +
 drivers/clk/clk-mux.c        |  2 +-
 drivers/clk/clk-uclass.c     | 20 ++++++++++++++++++++
 drivers/clk/clk.c            |  9 +++++++++
 include/clk.h                |  9 +++++++++
 include/linux/clk-provider.h |  1 +
 6 files changed, 41 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
index bf1c6a93b468..bd0d3d44ac8c 100644
--- a/drivers/clk/clk-gate.c
+++ b/drivers/clk/clk-gate.c
@@ -115,6 +115,7 @@ const struct clk_ops clk_gate_ops = {
 	.enable = clk_gate_enable,
 	.disable = clk_gate_disable,
 	.get_rate = clk_generic_get_rate,
+	.set_rate = clk_generic_set_rate,
 };
 
 struct clk *clk_register_gate(struct device *dev, const char *name,
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
index 62477e15d27a..4feb8e8c821d 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -150,13 +150,13 @@ static int clk_mux_set_parent(struct clk *clk, struct clk *parent)
 #else
 	writel(reg, mux->reg);
 #endif
-
 	return 0;
 }
 
 const struct clk_ops clk_mux_ops = {
 	.get_rate = clk_generic_get_rate,
 	.set_parent = clk_mux_set_parent,
+	.set_rate = clk_generic_set_rate,
 };
 
 struct clk *clk_hw_register_mux_table(struct device *dev, const char *name,
diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index 16169dac2340..e8db9b0ff2fd 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -515,6 +515,26 @@ ulong clk_get_parent_rate(struct clk *clk)
 	return pclk->rate;
 }
 
+ulong clk_set_parent_rate(struct clk *clk, ulong rate)
+{
+	const struct clk_ops *ops;
+	struct clk *pclk;
+
+	debug("%s(clk=%p)\n", __func__, clk);
+	if (!clk_valid(clk))
+		return 0;
+
+	pclk = clk_get_parent(clk);
+	if (IS_ERR(pclk))
+		return -ENODEV;
+
+	ops = clk_dev_ops(pclk->dev);
+	if (!ops->set_rate)
+		return -ENOSYS;
+
+	return clk_set_rate(pclk, rate);
+}
+
 ulong clk_round_rate(struct clk *clk, ulong rate)
 {
 	const struct clk_ops *ops;
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index b8c2e8d531b9..67c6b23231ff 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -13,6 +13,7 @@
 #include <dm/uclass.h>
 #include <dm/lists.h>
 #include <dm/device-internal.h>
+#include <linux/clk-provider.h>
 
 int clk_register(struct clk *clk, const char *drv_name,
 		 const char *name, const char *parent_name)
@@ -60,6 +61,14 @@ ulong clk_generic_get_rate(struct clk *clk)
 	return clk_get_parent_rate(clk);
 }
 
+ulong clk_generic_set_rate(struct clk *clk, ulong rate)
+{
+	if (clk->flags & CLK_SET_RATE_PARENT)
+		return clk_set_parent_rate(clk, rate);
+
+	return clk_get_parent_rate(clk);
+}
+
 const char *clk_hw_get_name(const struct clk *hw)
 {
 	assert(hw);
diff --git a/include/clk.h b/include/clk.h
index 045e923a529b..f0fd524ee519 100644
--- a/include/clk.h
+++ b/include/clk.h
@@ -452,6 +452,15 @@ struct clk *clk_get_parent(struct clk *clk);
  */
 ulong clk_get_parent_rate(struct clk *clk);
 
+/**
+ * clk_set_parent_rate() - Set parent of current clock rate.
+ * @clk:	A clock struct that was previously successfully requested by
+ *		clk_request/get_by_*().
+ *
+ * Return: clock rate in Hz, or -ve error code.
+ */
+ulong clk_set_parent_rate(struct clk *clk, ulong rate);
+
 /**
  * clk_round_rate() - Adjust a rate to the exact rate a clock can provide
  * @clk: A clock struct that was previously successfully requested by
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 59f9c241b846..459fa2d15ceb 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -253,6 +253,7 @@ struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
 
 const char *clk_hw_get_name(const struct clk *hw);
 ulong clk_generic_get_rate(struct clk *clk);
+ulong clk_generic_set_rate(struct clk *clk, ulong rate);
 
 struct clk *dev_get_clk_ptr(struct udevice *dev);
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 02/26] clk: imx8mn: Prevent clock critical path from disabling during reparent and set_rate
  2024-09-13  9:55 [PATCH 00/26] Support display (and even more) on the BSH SMM S2/PRO boards Dario Binacchi
  2024-09-13  9:55 ` [PATCH 01/26] clk: Propagate clk_set_rate() if CLK_SET_PARENT_RATE present for gate and mux Dario Binacchi
@ 2024-09-13  9:55 ` Dario Binacchi
  2024-09-13  9:55 ` [PATCH 03/26] clk: imx8mm: " Dario Binacchi
                   ` (24 subsequent siblings)
  26 siblings, 0 replies; 48+ messages in thread
From: Dario Binacchi @ 2024-09-13  9:55 UTC (permalink / raw)
  To: u-boot
  Cc: Fabio Estevam, linux-amarula, michael, Miquel Raynal,
	Dario Binacchi, Fabio Estevam, Hou Zhiqiang, Lukasz Majewski,
	Nicolas Heemeryck, Sean Anderson, Tom Rini

From: Michael Trimarchi <michael@amarulasolutions.com>

This commit ensures that critical clock paths are not disabled during
reparent and set_rate operations within the clock framework, paving the
way for the inclusion of new features.

Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---

 drivers/clk/imx/clk-imx8mn.c | 26 +++++++++++++++++++++-----
 1 file changed, 21 insertions(+), 5 deletions(-)

diff --git a/drivers/clk/imx/clk-imx8mn.c b/drivers/clk/imx/clk-imx8mn.c
index 125215e84f41..c96a2ebaa19a 100644
--- a/drivers/clk/imx/clk-imx8mn.c
+++ b/drivers/clk/imx/clk-imx8mn.c
@@ -29,10 +29,19 @@ static const char * const imx8mn_a53_sels[] = {"clock-osc-24m", "arm_pll_out", "
 					       "sys_pll2_1000m", "sys_pll1_800m", "sys_pll1_400m",
 					       "audio_pll1_out", "sys_pll3_out", };
 
+static const char * const imx8mn_noc_sels[] = {"osc_24m", "sys_pll1_800m", "sys_pll3_out",
+					       "sys_pll2_1000m", "sys_pll2_500m", "audio_pll1_out",
+					       "video_pll_out", "audio_pll2_out", };
+
 static const char * const imx8mn_ahb_sels[] = {"clock-osc-24m", "sys_pll1_133m", "sys_pll1_800m",
 					       "sys_pll1_400m", "sys_pll2_125m", "sys_pll3_out",
 					       "audio_pll1_out", "video_pll_out", };
 
+static const char * const imx8mn_main_axi_sels[] = {"osc_24m", "sys_pll2_333m", "sys_pll1_800m",
+						    "sys_pll2_250m", "sys_pll2_1000m",
+						    "audio_pll1_out", "video_pll_out",
+						    "sys_pll1_100m",};
+
 static const char * const imx8mn_enet_axi_sels[] = {"clock-osc-24m", "sys_pll1_266m", "sys_pll1_800m",
 						    "sys_pll2_250m", "sys_pll2_200m", "audio_pll1_out",
 						    "video_pll_out", "sys_pll3_out", };
@@ -67,6 +76,9 @@ static const char * const imx8mn_usdhc2_sels[] = {"clock-osc-24m", "sys_pll1_400
 						  "sys_pll2_500m", "sys_pll3_out", "sys_pll1_266m",
 						  "audio_pll2_out", "sys_pll1_100m", };
 
+static const char * const imx8mn_gic_sels[] = {"clock-osc-24m", "sys_pll2_200m", "sys_pll1_40m",
+					       "sys_pll2_100m", "sys_pll1_800m", "clk_ext2",
+					       "clk_ext4", "audio_pll2_out" };
 #if CONFIG_IS_ENABLED(DM_SPI)
 static const char * const imx8mn_ecspi1_sels[] = {"clock-osc-24m", "sys_pll2_200m", "sys_pll1_40m",
 						  "sys_pll1_160m", "sys_pll1_800m", "sys_pll3_out",
@@ -286,15 +298,18 @@ static int imx8mn_clk_probe(struct udevice *dev)
 	clk_dm(IMX8MN_CLK_IPG_ROOT,
 	       imx_clk_divider2("ipg_root", "ahb", base + 0x9080, 0, 1));
 
+	/* BUS */
+	clk_dm(IMX8MN_CLK_MAIN_AXI,
+	       imx8m_clk_composite_critical("main_axi", imx8mn_main_axi_sels, base + 0x8800));
 	clk_dm(IMX8MN_CLK_ENET_AXI,
-	       imx8m_clk_composite("enet_axi", imx8mn_enet_axi_sels,
-				   base + 0x8880));
+	       imx8m_clk_composite("enet_axi", imx8mn_enet_axi_sels, base + 0x8880));
 	clk_dm(IMX8MN_CLK_NAND_USDHC_BUS,
-	       imx8m_clk_composite_critical("nand_usdhc_bus",
-					    imx8mn_nand_usdhc_sels,
+	       imx8m_clk_composite_critical("nand_usdhc_bus", imx8mn_nand_usdhc_sels,
 					    base + 0x8900));
 	clk_dm(IMX8MN_CLK_USB_BUS,
 		imx8m_clk_composite("usb_bus", imx8mn_usb_bus_sels, base + 0x8b80));
+	clk_dm(IMX8MN_CLK_NOC,
+	       imx8m_clk_composite_critical("noc", imx8mn_noc_sels, base + 0x8d00));
 
 	/* IP */
 	clk_dm(IMX8MN_CLK_USDHC1,
@@ -389,7 +404,8 @@ static int imx8mn_clk_probe(struct udevice *dev)
 	clk_dm(IMX8MN_CLK_PWM4_ROOT,
 	       imx_clk_gate4("pwm4_root_clk", "pwm4", base + 0x42b0, 0));
 #endif
-
+	clk_dm(IMX8MN_CLK_GIC,
+	       imx8m_clk_composite_critical("gic", imx8mn_gic_sels, base + 0xb200));
 #if CONFIG_IS_ENABLED(DM_SPI)
 	clk_dm(IMX8MN_CLK_ECSPI1,
 	       imx8m_clk_composite("ecspi1", imx8mn_ecspi1_sels, base + 0xb280));
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 03/26] clk: imx8mm: Prevent clock critical path from disabling during reparent and set_rate
  2024-09-13  9:55 [PATCH 00/26] Support display (and even more) on the BSH SMM S2/PRO boards Dario Binacchi
  2024-09-13  9:55 ` [PATCH 01/26] clk: Propagate clk_set_rate() if CLK_SET_PARENT_RATE present for gate and mux Dario Binacchi
  2024-09-13  9:55 ` [PATCH 02/26] clk: imx8mn: Prevent clock critical path from disabling during reparent and set_rate Dario Binacchi
@ 2024-09-13  9:55 ` Dario Binacchi
  2024-09-13 10:09   ` Marek Vasut
  2024-09-13  9:55 ` [PATCH 04/26] clk: clk-uclass: Implement CLK_OPS_PARENT_ENABLE Dario Binacchi
                   ` (23 subsequent siblings)
  26 siblings, 1 reply; 48+ messages in thread
From: Dario Binacchi @ 2024-09-13  9:55 UTC (permalink / raw)
  To: u-boot
  Cc: Fabio Estevam, linux-amarula, michael, Miquel Raynal,
	Dario Binacchi, Hou Zhiqiang, Lukasz Majewski, Marek Vasut,
	Sean Anderson, Tim Harvey, Tom Rini

From: Michael Trimarchi <michael@amarulasolutions.com>

This commit ensures that critical clock paths are not disabled during
reparent and set_rate operations within the clock framework, paving the
way for the inclusion of new features.

Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---

 drivers/clk/imx/clk-imx8mm.c | 64 +++++++++++++++++++++++++++++-------
 1 file changed, 52 insertions(+), 12 deletions(-)

diff --git a/drivers/clk/imx/clk-imx8mm.c b/drivers/clk/imx/clk-imx8mm.c
index a91c6767fac5..432348a15cad 100644
--- a/drivers/clk/imx/clk-imx8mm.c
+++ b/drivers/clk/imx/clk-imx8mm.c
@@ -27,11 +27,25 @@ static const char * const imx8mm_a53_sels[] = {"clock-osc-24m", "arm_pll_out", "
 					       "sys_pll2_1000m", "sys_pll1_800m", "sys_pll1_400m",
 					       "audio_pll1_out", "sys_pll3_out", };
 
+#ifndef CONFIG_SPL_BUILD
+static const char * const imx8mm_noc_sels[] = {"clock-osc-24m", "sys_pll1_800m", "sys_pll3_out",
+					       "sys_pll2_1000m", "sys_pll2_500m", "audio_pll1_out",
+					       "video_pll1_out", "audio_pll2_out", };
+
+static const char * const imx8mm_noc_apb_sels[] = {"clock-osc-24m", "sys_pll1_400m", "sys_pll3_out",
+						   "sys_pll2_333m", "sys_pll2_200m",
+						   "sys_pll1_800m", "audio_pll1_out",
+						   "video_pll1_out", };
+
 static const char * const imx8mm_ahb_sels[] = {"clock-osc-24m", "sys_pll1_133m", "sys_pll1_800m",
 					       "sys_pll1_400m", "sys_pll2_125m", "sys_pll3_out",
 					       "audio_pll1_out", "video_pll1_out", };
 
-#ifndef CONFIG_SPL_BUILD
+static const char * const imx8mm_main_axi_sels[] = {"clock-osc-24m", "sys_pll2_333m",
+						    "sys_pll1_800m", "sys_pll2_250m",
+						    "sys_pll2_1000m", "audio_pll1_out",
+						    "video_pll1_out", "sys_pll1_100m",};
+
 static const char * const imx8mm_enet_axi_sels[] = {"clock-osc-24m", "sys_pll1_266m", "sys_pll1_800m",
 						    "sys_pll2_250m", "sys_pll2_200m", "audio_pll1_out",
 						    "video_pll1_out", "sys_pll3_out", };
@@ -47,6 +61,11 @@ static const char * const imx8mm_enet_timer_sels[] = {"clock-osc-24m", "sys_pll2
 static const char * const imx8mm_enet_phy_sels[] = {"clock-osc-24m", "sys_pll2_50m", "sys_pll2_125m",
 						    "sys_pll2_200m", "sys_pll2_500m", "video_pll1_out",
 						    "audio_pll2_out", };
+
+static const char * const imx8mm_dram_apb_sels[] = {"clock-osc-24m", "sys_pll2_200m",
+						    "sys_pll1_40m", "sys_pll1_160m",
+						    "sys_pll1_800m", "sys_pll3_out",
+						    "sys_pll2_250m", "audio_pll2_out", };
 #endif
 
 static const char * const imx8mm_nand_usdhc_sels[] = {"clock-osc-24m", "sys_pll1_266m", "sys_pll1_800m",
@@ -82,8 +101,9 @@ static const char * const imx8mm_i2c4_sels[] = {"clock-osc-24m", "sys_pll1_160m"
 						"audio_pll2_out", "sys_pll1_133m", };
 
 #if CONFIG_IS_ENABLED(PCIE_DW_IMX)
-static const char * const imx8mm_pcie1_ctrl_sels[] = {"clock-osc-24m", "sys_pll2_250m", "sys_pll2_200m",
-						      "sys_pll1_266m", "sys_pll1_800m", "sys_pll2_500m",
+static const char * const imx8mm_pcie1_ctrl_sels[] = {"clock-osc-24m", "sys_pll2_250m",
+						      "sys_pll2_200m", "sys_pll1_266m",
+						      "sys_pll1_800m", "sys_pll2_500m",
 						      "sys_pll2_333m", "sys_pll3_out", };
 
 static const char * const imx8mm_pcie1_phy_sels[] = {"clock-osc-24m", "sys_pll2_100m", "sys_pll2_500m",
@@ -135,6 +155,10 @@ static const char * const imx8mm_usb_phy_sels[] = {"clock-osc-24m", "sys_pll1_10
 						   "sys_pll2_100m", "sys_pll2_200m", "clk_ext2",
 						   "clk_ext3", "audio_pll2_out", };
 
+static const char * const imx8mm_gic_sels[] = {"clock-osc-24m", "sys_pll2_200m", "sys_pll1_40m",
+					       "sys_pll2_100m", "sys_pll1_800m", "clk_ext2",
+					       "clk_ext4", "audio_pll2_out" };
+
 #if CONFIG_IS_ENABLED(DM_SPI)
 static const char * const imx8mm_ecspi1_sels[] = {"clock-osc-24m", "sys_pll2_200m", "sys_pll1_40m",
 						  "sys_pll1_160m", "sys_pll1_800m", "sys_pll3_out",
@@ -283,18 +307,34 @@ static int imx8mm_clk_probe(struct udevice *dev)
 	       imx_clk_divider2("arm_a53_div", "arm_a53_cg",
 				base + 0x8000, 0, 3));
 
-	clk_dm(IMX8MM_CLK_AHB,
-	       imx8m_clk_composite_critical("ahb", imx8mm_ahb_sels,
-					    base + 0x9000));
 	clk_dm(IMX8MM_CLK_IPG_ROOT,
 	       imx_clk_divider2("ipg_root", "ahb", base + 0x9080, 0, 1));
 
+#ifndef CONFIG_SPL_BUILD
+	/* BUS */
+	clk_dm(IMX8MM_CLK_MAIN_AXI,
+	       imx8m_clk_composite_critical("main_axi",
+					    imx8mm_main_axi_sels, base + 0x8800));
+	clk_dm(IMX8MM_CLK_ENET_AXI,
+	       imx8m_clk_composite("enet_axi", imx8mm_enet_axi_sels, base + 0x8880));
+	clk_dm(IMX8MM_CLK_NOC,
+	       imx8m_clk_composite_critical("noc", imx8mm_noc_sels, base + 0x8d00));
+	clk_dm(IMX8MM_CLK_NOC_APB,
+	       imx8m_clk_composite_critical("noc_apb", imx8mm_noc_apb_sels,
+					    base + 0x8d80));
+	clk_dm(IMX8MM_CLK_AHB,
+	       imx8m_clk_composite_critical("ahb", imx8mm_ahb_sels, base + 0x9000));
+	clk_dm(IMX8MM_CLK_DRAM_APB,
+	       imx8m_clk_composite_critical("dram_apb", imx8mm_dram_apb_sels,
+					    base + 0xa080));
+#endif
+
 	clk_dm(IMX8MM_CLK_NAND_USDHC_BUS,
-	       imx8m_clk_composite_critical("nand_usdhc_bus",
-					    imx8mm_nand_usdhc_sels,
+	       imx8m_clk_composite_critical("nand_usdhc_bus", imx8mm_nand_usdhc_sels,
 					    base + 0x8900));
+
 	clk_dm(IMX8MM_CLK_USB_BUS,
-		imx8m_clk_composite("usb_bus", imx8mm_usb_bus_sels, base + 0x8b80));
+	       imx8m_clk_composite("usb_bus", imx8mm_usb_bus_sels, base + 0x8b80));
 
 	/* IP */
 #if CONFIG_IS_ENABLED(PCIE_DW_IMX)
@@ -358,9 +398,6 @@ static int imx8mm_clk_probe(struct udevice *dev)
 
 	/* clks not needed in SPL stage */
 #ifndef CONFIG_SPL_BUILD
-	clk_dm(IMX8MM_CLK_ENET_AXI,
-	       imx8m_clk_composite("enet_axi", imx8mm_enet_axi_sels,
-				   base + 0x8880));
 	clk_dm(IMX8MM_CLK_ENET_REF,
 	       imx8m_clk_composite("enet_ref", imx8mm_enet_ref_sels,
 	       base + 0xa980));
@@ -396,6 +433,9 @@ static int imx8mm_clk_probe(struct udevice *dev)
 	       imx_clk_gate4("pcie1_root_clk", "pcie1_ctrl", base + 0x4250, 0));
 #endif
 
+	clk_dm(IMX8MM_CLK_GIC,
+	       imx8m_clk_composite_critical("gic", imx8mm_gic_sels, base + 0xb200));
+
 #if CONFIG_IS_ENABLED(DM_SPI)
 	clk_dm(IMX8MM_CLK_ECSPI1,
 	       imx8m_clk_composite("ecspi1", imx8mm_ecspi1_sels, base + 0xb280));
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 04/26] clk: clk-uclass: Implement CLK_OPS_PARENT_ENABLE
  2024-09-13  9:55 [PATCH 00/26] Support display (and even more) on the BSH SMM S2/PRO boards Dario Binacchi
                   ` (2 preceding siblings ...)
  2024-09-13  9:55 ` [PATCH 03/26] clk: imx8mm: " Dario Binacchi
@ 2024-09-13  9:55 ` Dario Binacchi
  2024-09-13  9:55 ` [PATCH 05/26] clk: imx8mm: Mark IMX8MM_SYS_PLL2 and IMX8MM_SYS_PLL3 as enabled Dario Binacchi
                   ` (22 subsequent siblings)
  26 siblings, 0 replies; 48+ messages in thread
From: Dario Binacchi @ 2024-09-13  9:55 UTC (permalink / raw)
  To: u-boot
  Cc: Fabio Estevam, linux-amarula, michael, Miquel Raynal,
	Dario Binacchi, Ashok Reddy Soma, Eugen Hristev, Julien Masson,
	Lukasz Majewski, Maksim Kiselev, Mattijs Korpershoek,
	Sam Protsenko, Sean Anderson, Tom Rini

From: Michael Trimarchi <michael@amarulasolutions.com>

There are scenario that we need to enable the new parent clock
before reparent, or we need to do the same with clk_set_rate. The
patch cover those scenario

Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---

 drivers/clk/clk-uclass.c | 47 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 46 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index e8db9b0ff2fd..b571a3620222 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -582,7 +582,9 @@ static void clk_clean_rate_cache(struct clk *clk)
 ulong clk_set_rate(struct clk *clk, ulong rate)
 {
 	const struct clk_ops *ops;
+	struct clk *pclk;
 	struct clk *clkp;
+	ulong ret;
 
 	debug("%s(clk=%p, rate=%lu)\n", __func__, clk, rate);
 	if (!clk_valid(clk))
@@ -597,11 +599,37 @@ ulong clk_set_rate(struct clk *clk, ulong rate)
 	/* Clean up cached rates for us and all child clocks */
 	clk_clean_rate_cache(clkp);
 
-	return ops->set_rate(clk, rate);
+	if (clk->flags & CLK_SET_RATE_UNGATE) {
+		ret = clk_enable(clk);
+		if (ret)
+			return ret;
+	}
+
+	pclk = clk_get_parent(clk);
+	if (pclk) {
+		if (clk->flags & CLK_OPS_PARENT_ENABLE) {
+			ret = clk_enable(pclk);
+			if (ret)
+				goto out;
+		}
+	}
+
+	ret = ops->set_rate(clk, rate);
+
+	if (pclk && clk->flags & CLK_OPS_PARENT_ENABLE)
+		clk_disable(pclk);
+
+out:
+	if (clk->flags & CLK_SET_RATE_UNGATE)
+		clk_disable(clk);
+
+	return ret;
 }
 
 int clk_set_parent(struct clk *clk, struct clk *parent)
 {
+	struct clk *old_parent;
+
 	const struct clk_ops *ops;
 	int ret;
 
@@ -613,6 +641,15 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
 	if (!ops->set_parent)
 		return -ENOSYS;
 
+	if (clk->enable_count)
+		clk_enable(parent);
+
+	old_parent = clk_get_parent(clk);
+	if (clk->flags & CLK_OPS_PARENT_ENABLE) {
+		clk_enable(old_parent);
+		clk_enable(parent);
+	}
+
 	ret = ops->set_parent(clk, parent);
 	if (ret)
 		return ret;
@@ -620,6 +657,14 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
 	if (CONFIG_IS_ENABLED(CLK_CCF))
 		ret = device_reparent(clk->dev, parent->dev);
 
+	if (clk->flags & CLK_OPS_PARENT_ENABLE) {
+		clk_disable(parent);
+		clk_disable(old_parent);
+	}
+
+	if (clk->enable_count)
+		clk_disable(old_parent);
+
 	return ret;
 }
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 05/26] clk: imx8mm: Mark IMX8MM_SYS_PLL2 and IMX8MM_SYS_PLL3 as enabled
  2024-09-13  9:55 [PATCH 00/26] Support display (and even more) on the BSH SMM S2/PRO boards Dario Binacchi
                   ` (3 preceding siblings ...)
  2024-09-13  9:55 ` [PATCH 04/26] clk: clk-uclass: Implement CLK_OPS_PARENT_ENABLE Dario Binacchi
@ 2024-09-13  9:55 ` Dario Binacchi
  2024-09-13 10:07   ` Marek Vasut
  2024-09-13  9:55 ` [PATCH 06/26] clk: imx8mn: Mark IMX8MN_SYS_PLL2 and IMX8MN_SYS_PLL3 " Dario Binacchi
                   ` (21 subsequent siblings)
  26 siblings, 1 reply; 48+ messages in thread
From: Dario Binacchi @ 2024-09-13  9:55 UTC (permalink / raw)
  To: u-boot
  Cc: Fabio Estevam, linux-amarula, michael, Miquel Raynal,
	Dario Binacchi, Hou Zhiqiang, Lukasz Majewski, Marek Vasut,
	Sean Anderson, Tim Harvey, Tom Rini

From: Michael Trimarchi <michael@amarulasolutions.com>

Both clock are enabled by the bootloader and we need to increase their
reference count to avoid disable during reparent operation.

Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---

 drivers/clk/imx/clk-imx8mm.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/clk/imx/clk-imx8mm.c b/drivers/clk/imx/clk-imx8mm.c
index 432348a15cad..0e71ceefe96c 100644
--- a/drivers/clk/imx/clk-imx8mm.c
+++ b/drivers/clk/imx/clk-imx8mm.c
@@ -176,6 +176,8 @@ static const char * const imx8mm_ecspi3_sels[] = {"clock-osc-24m", "sys_pll2_200
 static int imx8mm_clk_probe(struct udevice *dev)
 {
 	void __iomem *base;
+	struct clk *clk;
+	int ret;
 
 	base = (void *)ANATOP_BASE_ADDR;
 
@@ -458,6 +460,13 @@ static int imx8mm_clk_probe(struct udevice *dev)
 	clk_dm(IMX8MM_CLK_QSPI_ROOT,
 	       imx_clk_gate4("qspi_root_clk", "qspi", base + 0x42f0, 0));
 #endif
+	ret = clk_get_by_id(IMX8MM_SYS_PLL2, &clk);
+	if (!ret)
+		clk_enable(clk);
+
+	ret = clk_get_by_id(IMX8MM_SYS_PLL3, &clk);
+	if (!ret)
+		clk_enable(clk);
 
 	clk_dm(IMX8MM_CLK_ARM,
 	       imx_clk_mux2_flags("arm_core", base + 0x9880, 24, 1,
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 06/26] clk: imx8mn: Mark IMX8MN_SYS_PLL2 and IMX8MN_SYS_PLL3 as enabled
  2024-09-13  9:55 [PATCH 00/26] Support display (and even more) on the BSH SMM S2/PRO boards Dario Binacchi
                   ` (4 preceding siblings ...)
  2024-09-13  9:55 ` [PATCH 05/26] clk: imx8mm: Mark IMX8MM_SYS_PLL2 and IMX8MM_SYS_PLL3 as enabled Dario Binacchi
@ 2024-09-13  9:55 ` Dario Binacchi
  2024-09-13  9:55 ` [PATCH 07/26] clk: imx8mn: add video clocks support Dario Binacchi
                   ` (20 subsequent siblings)
  26 siblings, 0 replies; 48+ messages in thread
From: Dario Binacchi @ 2024-09-13  9:55 UTC (permalink / raw)
  To: u-boot
  Cc: Fabio Estevam, linux-amarula, michael, Miquel Raynal,
	Dario Binacchi, Fabio Estevam, Hou Zhiqiang, Lukasz Majewski,
	Nicolas Heemeryck, Sean Anderson, Tom Rini

From: Michael Trimarchi <michael@amarulasolutions.com>

Both clock are enabled by the bootloader and we need to increase their
reference count to avoid disable during reparent operation.

Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---

 drivers/clk/imx/clk-imx8mn.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/clk/imx/clk-imx8mn.c b/drivers/clk/imx/clk-imx8mn.c
index c96a2ebaa19a..449ebf2d0733 100644
--- a/drivers/clk/imx/clk-imx8mn.c
+++ b/drivers/clk/imx/clk-imx8mn.c
@@ -154,6 +154,7 @@ static const char * const imx8mn_usb_phy_sels[] = {"clock-osc-24m", "sys_pll1_10
 static int imx8mn_clk_probe(struct udevice *dev)
 {
 	struct clk osc_24m_clk;
+	struct clk *clk;
 	void __iomem *base;
 	int ret;
 
@@ -420,6 +421,13 @@ static int imx8mn_clk_probe(struct udevice *dev)
 	clk_dm(IMX8MN_CLK_ECSPI3_ROOT,
 	       imx_clk_gate4("ecspi3_root_clk", "ecspi3", base + 0x4090, 0));
 #endif
+	ret = clk_get_by_id(IMX8MN_SYS_PLL2, &clk);
+	if (!ret)
+		clk_enable(clk);
+
+	ret = clk_get_by_id(IMX8MN_SYS_PLL3, &clk);
+	if (!ret)
+		clk_enable(clk);
 
 	clk_dm(IMX8MN_CLK_ARM,
 	       imx_clk_mux2_flags("arm_core", base + 0x9880, 24, 1,
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 07/26] clk: imx8mn: add video clocks support
  2024-09-13  9:55 [PATCH 00/26] Support display (and even more) on the BSH SMM S2/PRO boards Dario Binacchi
                   ` (5 preceding siblings ...)
  2024-09-13  9:55 ` [PATCH 06/26] clk: imx8mn: Mark IMX8MN_SYS_PLL2 and IMX8MN_SYS_PLL3 " Dario Binacchi
@ 2024-09-13  9:55 ` Dario Binacchi
  2024-09-13  9:55 ` [PATCH 08/26] power: Add iMX8M block ctrl driver for dispmix Dario Binacchi
                   ` (19 subsequent siblings)
  26 siblings, 0 replies; 48+ messages in thread
From: Dario Binacchi @ 2024-09-13  9:55 UTC (permalink / raw)
  To: u-boot
  Cc: Fabio Estevam, linux-amarula, michael, Miquel Raynal,
	Dario Binacchi, Fabio Estevam, Hou Zhiqiang, Lukasz Majewski,
	Nicolas Heemeryck, Sean Anderson, Tom Rini

From: Michael Trimarchi <michael@amarulasolutions.com>

Add clocks support for the video subsystem.

Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---

 drivers/clk/imx/clk-imx8mn.c | 97 +++++++++++++++++++++++++++++++++---
 1 file changed, 90 insertions(+), 7 deletions(-)

diff --git a/drivers/clk/imx/clk-imx8mn.c b/drivers/clk/imx/clk-imx8mn.c
index 449ebf2d0733..7ea4c90fa137 100644
--- a/drivers/clk/imx/clk-imx8mn.c
+++ b/drivers/clk/imx/clk-imx8mn.c
@@ -17,6 +17,7 @@
 static u32 share_count_nand;
 
 static const char * const pll_ref_sels[] = { "clock-osc-24m", "dummy", "dummy", "dummy", };
+static const char * const video_pll_bypass_sels[] = {"video_pll", "video_pll_ref_sel", };
 static const char * const dram_pll_bypass_sels[] = {"dram_pll", "dram_pll_ref_sel", };
 static const char * const arm_pll_bypass_sels[] = {"arm_pll", "arm_pll_ref_sel", };
 static const char * const sys_pll1_bypass_sels[] = {"sys_pll1", "sys_pll1_ref_sel", };
@@ -47,17 +48,52 @@ static const char * const imx8mn_enet_axi_sels[] = {"clock-osc-24m", "sys_pll1_2
 						    "video_pll_out", "sys_pll3_out", };
 
 #ifndef CONFIG_SPL_BUILD
-static const char * const imx8mn_enet_ref_sels[] = {"clock-osc-24m", "sys_pll2_125m", "sys_pll2_50m",
-						    "sys_pll2_100m", "sys_pll1_160m", "audio_pll1_out",
+static const char * const imx8mn_disp_axi_sels[] = {"clock-osc-24m", "sys_pll2_1000m",
+						    "sys_pll1_800m", "sys_pll3_out", "sys_pll1_40m",
+						    "audio_pll2_out", "clk_ext1", "clk_ext4", };
+
+static const char * const imx8mn_disp_apb_sels[] = {"clock-osc-24m", "sys_pll2_125m",
+						    "sys_pll1_800m", "sys_pll3_out", "sys_pll1_40m",
+						    "audio_pll2_out", "clk_ext1", "clk_ext3", };
+
+static const char * const imx8mn_disp_pixel_sels[] = {"clock-osc-24m", "video_pll_out",
+						      "audio_pll2_out", "audio_pll1_out",
+						      "sys_pll1_800m", "sys_pll2_1000m",
+						      "sys_pll3_out", "clk_ext4", };
+
+static const char * const imx8mn_dsi_core_sels[] = {"clock-osc-24m", "sys_pll1_266m",
+						    "sys_pll2_250m", "sys_pll1_800m",
+						    "sys_pll2_1000m", "sys_pll3_out",
+						    "audio_pll2_out", "video_pll_out", };
+
+static const char * const imx8mn_dsi_phy_sels[] = {"clock-osc-24m", "sys_pll2_125m",
+						   "sys_pll2_100m", "sys_pll1_800m",
+						   "sys_pll2_1000m", "clk_ext2",
+						   "audio_pll2_out", "video_pll_out", };
+
+static const char * const imx8mn_dsi_dbi_sels[] = {"clock-osc-24m", "sys_pll1_266m",
+						   "sys_pll2_100m", "sys_pll1_800m",
+						   "sys_pll2_1000m", "sys_pll3_out",
+						   "audio_pll2_out", "video_pll_out", };
+
+static const char * const imx8mn_camera_pixel_sels[] = {"clock-osc-24m", "sys_pll1_266m",
+							"sys_pll2_250m", "sys_pll1_800m",
+							"sys_pll2_1000m", "sys_pll3_out",
+							"audio_pll2_out", "video_pll_out", };
+
+static const char * const imx8mn_enet_ref_sels[] = {"clock-osc-24m", "sys_pll2_125m",
+						    "sys_pll2_50m", "sys_pll2_100m",
+						    "sys_pll1_160m", "audio_pll1_out",
 						    "video_pll_out", "clk_ext4", };
 
-static const char * const imx8mn_enet_timer_sels[] = {"clock-osc-24m", "sys_pll2_100m", "audio_pll1_out",
-						      "clk_ext1", "clk_ext2", "clk_ext3",
-						      "clk_ext4", "video_pll_out", };
+static const char * const imx8mn_enet_timer_sels[] = {"clock-osc-24m", "sys_pll2_100m",
+						      "audio_pll1_out", "clk_ext1", "clk_ext2",
+						      "clk_ext3", "clk_ext4", "video_pll_out", };
 
 static const char * const imx8mn_enet_phy_sels[] = {"clock-osc-24m", "sys_pll2_50m", "sys_pll2_125m",
-						    "sys_pll2_200m", "sys_pll2_500m", "audio_pll1_out",
-						    "video_pll_out", "audio_pll2_out", };
+						    "sys_pll2_200m", "sys_pll2_500m",
+						    "audio_pll1_out", "video_pll_out",
+						    "audio_pll2_out", };
 #endif
 
 static const char * const imx8mn_nand_usdhc_sels[] = {"clock-osc-24m", "sys_pll1_266m", "sys_pll1_800m",
@@ -151,6 +187,10 @@ static const char * const imx8mn_usb_phy_sels[] = {"clock-osc-24m", "sys_pll1_10
 						   "sys_pll2_100m", "sys_pll2_200m", "clk_ext2",
 						   "clk_ext3", "audio_pll2_out", };
 
+#ifndef CONFIG_SPL_BUILD
+static unsigned int share_count_disp;
+#endif
+
 static int imx8mn_clk_probe(struct udevice *dev)
 {
 	struct clk osc_24m_clk;
@@ -191,8 +231,19 @@ static int imx8mn_clk_probe(struct udevice *dev)
 	clk_dm(IMX8MN_SYS_PLL3,
 	       imx_clk_pll14xx("sys_pll3", "sys_pll3_ref_sel",
 			       base + 0x114, &imx_1416x_pll));
+	clk_dm(IMX8MN_VIDEO_PLL_REF_SEL,
+	       imx_clk_mux("video_pll_ref_sel", base + 0x28, 0, 2,
+			   pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
+	clk_dm(IMX8MN_VIDEO_PLL1,
+	       imx_clk_pll14xx("video_pll", "video_pll_ref_sel",
+			       base + 0x28, &imx_1443x_pll));
 
 	/* PLL bypass out */
+	clk_dm(IMX8MN_VIDEO_PLL_BYPASS,
+	       imx_clk_mux_flags("video_pll_bypass", base + 0x28, 16, 1,
+				 video_pll_bypass_sels,
+				 ARRAY_SIZE(video_pll_bypass_sels),
+				 CLK_SET_RATE_PARENT));
 	clk_dm(IMX8MN_DRAM_PLL_BYPASS,
 	       imx_clk_mux_flags("dram_pll_bypass", base + 0x50, 4, 1,
 				 dram_pll_bypass_sels,
@@ -220,6 +271,9 @@ static int imx8mn_clk_probe(struct udevice *dev)
 				 CLK_SET_RATE_PARENT));
 
 	/* PLL out gate */
+	clk_dm(IMX8MN_VIDEO_PLL_OUT,
+	       imx_clk_gate("video_pll_out", "video_pll_bypass",
+			    base + 0x28, 13));
 	clk_dm(IMX8MN_DRAM_PLL_OUT,
 	       imx_clk_gate("dram_pll_out", "dram_pll_bypass",
 			    base + 0x50, 13));
@@ -376,6 +430,35 @@ static int imx8mn_clk_probe(struct udevice *dev)
 
 	/* clks not needed in SPL stage */
 #ifndef CONFIG_SPL_BUILD
+	clk_dm(IMX8MN_CLK_DISP_AXI,
+	       imx8m_clk_composite("disp_axi", imx8mn_disp_axi_sels, base + 0x8a00));
+	clk_dm(IMX8MN_CLK_DISP_APB,
+	       imx8m_clk_composite("disp_apb", imx8mn_disp_apb_sels, base + 0x8a80));
+	clk_dm(IMX8MN_CLK_DISP_PIXEL,
+	       __imx8m_clk_composite("disp_pixel", imx8mn_disp_pixel_sels, base + 0xa500,
+				     CLK_SET_RATE_PARENT));
+	clk_dm(IMX8MN_CLK_DSI_CORE,
+	       imx8m_clk_composite("dsi_core", imx8mn_dsi_core_sels, base + 0xbb00));
+	clk_dm(IMX8MN_CLK_DSI_PHY_REF,
+	       imx8m_clk_composite("dsi_phy_ref", imx8mn_dsi_phy_sels, base + 0xbb80));
+	clk_dm(IMX8MN_CLK_DSI_DBI,
+	       imx8m_clk_composite("dsi_dbi", imx8mn_dsi_dbi_sels, base + 0xbc00));
+	clk_dm(IMX8MN_CLK_CAMERA_PIXEL,
+	       imx8m_clk_composite("camera_pixel", imx8mn_camera_pixel_sels, base + 0xbd00));
+
+	clk_dm(IMX8MN_CLK_DISP_AXI_ROOT,
+	       imx_clk_gate2_shared2("disp_axi_root_clk", "disp_axi", base + 0x45d0, 0,
+				     &share_count_disp));
+	clk_dm(IMX8MN_CLK_DISP_APB_ROOT,
+	       imx_clk_gate2_shared2("disp_apb_root_clk", "disp_apb", base + 0x45d0, 0,
+				     &share_count_disp));
+	clk_dm(IMX8MN_CLK_CAMERA_PIXEL_ROOT,
+	       imx_clk_gate2_shared2("camera_pixel_clk", "camera_pixel", base + 0x45d0, 0,
+				     &share_count_disp));
+	clk_dm(IMX8MN_CLK_DISP_PIXEL_ROOT,
+	       imx_clk_gate2_shared2("disp_pixel_clk", "disp_pixel", base + 0x45d0, 0,
+				     &share_count_disp));
+
 	clk_dm(IMX8MN_CLK_ENET_REF,
 	       imx8m_clk_composite("enet_ref", imx8mn_enet_ref_sels,
 	       base + 0xa980));
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 08/26] power: Add iMX8M block ctrl driver for dispmix
  2024-09-13  9:55 [PATCH 00/26] Support display (and even more) on the BSH SMM S2/PRO boards Dario Binacchi
                   ` (6 preceding siblings ...)
  2024-09-13  9:55 ` [PATCH 07/26] clk: imx8mn: add video clocks support Dario Binacchi
@ 2024-09-13  9:55 ` Dario Binacchi
  2024-09-24  9:05   ` Heiko Schocher
  2024-09-13  9:55 ` [PATCH 09/26] video: Add video link framework Dario Binacchi
                   ` (18 subsequent siblings)
  26 siblings, 1 reply; 48+ messages in thread
From: Dario Binacchi @ 2024-09-13  9:55 UTC (permalink / raw)
  To: u-boot
  Cc: Fabio Estevam, linux-amarula, michael, Miquel Raynal, Ye Li,
	Dario Binacchi, AKASHI Takahiro, Jaehoon Chung, Tom Rini

From: Michael Trimarchi <michael@amarulasolutions.com>

Add iMX8 block ctrl driver for displaymix on iMX8MM/iMX8MN and
mediamix on iMX8MP.

To support blk ctrl driver, the power domain driver on iMX8M needs
update to add relevant PGC domains

Signed-off-by: Ye Li <ye.li@nxp.com>
Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---

 drivers/power/domain/Kconfig              |   6 +
 drivers/power/domain/Makefile             |   1 +
 drivers/power/domain/imx8m-blk-ctrl.c     | 438 ++++++++++++++++++++++
 drivers/power/domain/imx8m-power-domain.c | 213 ++++++++++-
 4 files changed, 656 insertions(+), 2 deletions(-)
 create mode 100644 drivers/power/domain/imx8m-blk-ctrl.c

diff --git a/drivers/power/domain/Kconfig b/drivers/power/domain/Kconfig
index bd82d2f7044b..fb006b6e8e28 100644
--- a/drivers/power/domain/Kconfig
+++ b/drivers/power/domain/Kconfig
@@ -40,6 +40,12 @@ config IMX8M_POWER_DOMAIN
 	  Enable support for manipulating NXP i.MX8M on-SoC power domains via
 	  requests to the ATF.
 
+config IMX8M_BLK_CTRL
+	bool "Enable i.MX8M block control driver"
+	depends on POWER_DOMAIN && ARCH_IMX8M
+	help
+	  Enable support for manipulating NXP i.MX8M on-SoC block control driver
+
 config IMX8MP_HSIOMIX_BLKCTRL
 	bool "Enable i.MX8MP HSIOMIX domain driver"
 	depends on POWER_DOMAIN && IMX8MP
diff --git a/drivers/power/domain/Makefile b/drivers/power/domain/Makefile
index 2daab73eb758..46849fd2a4db 100644
--- a/drivers/power/domain/Makefile
+++ b/drivers/power/domain/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_APPLE_PMGR_POWER_DOMAIN) += apple-pmgr.o
 obj-$(CONFIG_BCM6328_POWER_DOMAIN) += bcm6328-power-domain.o
 obj-$(CONFIG_IMX8_POWER_DOMAIN) += imx8-power-domain-legacy.o imx8-power-domain.o
 obj-$(CONFIG_IMX8M_POWER_DOMAIN) += imx8m-power-domain.o
+obj-$(CONFIG_IMX8M_BLK_CTRL) += imx8m-blk-ctrl.o
 obj-$(CONFIG_IMX8MP_HSIOMIX_BLKCTRL) += imx8mp-hsiomix.o
 obj-$(CONFIG_MTK_POWER_DOMAIN) += mtk-power-domain.o
 obj-$(CONFIG_MESON_GX_VPU_POWER_DOMAIN) += meson-gx-pwrc-vpu.o
diff --git a/drivers/power/domain/imx8m-blk-ctrl.c b/drivers/power/domain/imx8m-blk-ctrl.c
new file mode 100644
index 000000000000..4c89078b991b
--- /dev/null
+++ b/drivers/power/domain/imx8m-blk-ctrl.c
@@ -0,0 +1,438 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2023 NXP
+ */
+
+#include <dm.h>
+#include <malloc.h>
+#include <power-domain-uclass.h>
+#include <asm/io.h>
+#include <dm/device-internal.h>
+#include <dm/device.h>
+#include <dt-bindings/power/imx8mm-power.h>
+#include <dt-bindings/power/imx8mn-power.h>
+#include <dt-bindings/power/imx8mp-power.h>
+#include <clk.h>
+#include <linux/delay.h>
+
+#define BLK_SFT_RSTN	0x0
+#define BLK_CLK_EN	0x4
+#define BLK_MIPI_RESET_DIV	0x8 /* Mini/Nano/Plus DISPLAY_BLK_CTRL only */
+
+#define DOMAIN_MAX_CLKS 4
+
+struct imx8m_blk_ctrl_domain {
+	struct clk clks[DOMAIN_MAX_CLKS];
+	struct power_domain power_dev;
+};
+
+struct imx8m_blk_ctrl {
+	void __iomem *base;
+	struct power_domain bus_power_dev;
+	struct imx8m_blk_ctrl_domain *domains;
+};
+
+struct imx8m_blk_ctrl_domain_data {
+	const char *name;
+	const char * const *clk_names;
+	const char *gpc_name;
+	int num_clks;
+	u32 rst_mask;
+	u32 clk_mask;
+	u32 mipi_phy_rst_mask;
+};
+
+struct imx8m_blk_ctrl_data {
+	int max_reg;
+	const struct imx8m_blk_ctrl_domain_data *domains;
+	int num_domains;
+	u32 bus_rst_mask;
+	u32 bus_clk_mask;
+};
+
+static int imx8m_blk_ctrl_request(struct power_domain *power_domain)
+{
+	return 0;
+}
+
+static int imx8m_blk_ctrl_free(struct power_domain *power_domain)
+{
+	return 0;
+}
+
+static int imx8m_blk_ctrl_enable_domain_clk(struct udevice *dev, ulong domain_id, bool enable)
+{
+	int ret, i;
+	struct imx8m_blk_ctrl *priv = (struct imx8m_blk_ctrl *)dev_get_priv(dev);
+	struct imx8m_blk_ctrl_data *drv_data =
+		(struct imx8m_blk_ctrl_data *)dev_get_driver_data(dev);
+
+	debug("%s num_clk %u\n", __func__, drv_data->domains[domain_id].num_clks);
+
+	for (i = 0; i < drv_data->domains[domain_id].num_clks; i++) {
+		debug("%s clk %s\n", __func__, drv_data->domains[domain_id].clk_names[i]);
+		if (enable)
+			ret = clk_enable(&priv->domains[domain_id].clks[i]);
+		else
+			ret = clk_disable(&priv->domains[domain_id].clks[i]);
+		if (ret && ret != -ENOENT) {
+			printf("Failed to %s domain clk %s\n", enable ? "enable" : "disable",
+			       drv_data->domains[domain_id].clk_names[i]);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int imx8m_blk_ctrl_power_on(struct power_domain *power_domain)
+{
+	struct udevice *dev = power_domain->dev;
+	struct imx8m_blk_ctrl *priv = (struct imx8m_blk_ctrl *)dev_get_priv(dev);
+	struct imx8m_blk_ctrl_data *drv_data =
+		(struct imx8m_blk_ctrl_data *)dev_get_driver_data(dev);
+	int ret;
+
+	debug("%s, id %lu\n", __func__, power_domain->id);
+
+	if (!priv->domains[power_domain->id].power_dev.dev)
+		return -ENODEV;
+
+	ret = power_domain_on(&priv->bus_power_dev);
+	if (ret < 0) {
+		printf("Failed to power up bus domain %d\n", ret);
+		return ret;
+	}
+
+	/* Enable bus clock and deassert bus reset */
+	setbits_le32(priv->base + BLK_CLK_EN, drv_data->bus_clk_mask);
+	setbits_le32(priv->base + BLK_SFT_RSTN, drv_data->bus_rst_mask);
+
+	/* wait for reset to propagate */
+	udelay(5);
+
+	/* put devices into reset */
+	clrbits_le32(priv->base + BLK_SFT_RSTN, drv_data->domains[power_domain->id].rst_mask);
+	if (drv_data->domains[power_domain->id].mipi_phy_rst_mask)
+		clrbits_le32(priv->base + BLK_MIPI_RESET_DIV, d
+			     rv_data->domains[power_domain->id].mipi_phy_rst_mask);
+
+	/* enable upstream and blk-ctrl clocks to allow reset to propagate */
+	ret = imx8m_blk_ctrl_enable_domain_clk(dev, power_domain->id, true);
+	if (ret) {
+		printf("failed to enable clocks\n");
+		goto bus_powerdown;
+	}
+
+	/* ungate clk */
+	setbits_le32(priv->base + BLK_CLK_EN, drv_data->domains[power_domain->id].clk_mask);
+
+	/* power up upstream GPC domain */
+	ret = power_domain_on(&priv->domains[power_domain->id].power_dev);
+	if (ret < 0) {
+		printf("Failed to power up peripheral domain %d\n", ret);
+		goto clk_disable;
+	}
+
+	/* wait for reset to propagate */
+	udelay(5);
+
+	/* release reset */
+	setbits_le32(priv->base + BLK_SFT_RSTN, drv_data->domains[power_domain->id].rst_mask);
+	if (drv_data->domains[power_domain->id].mipi_phy_rst_mask)
+		setbits_le32(priv->base + BLK_MIPI_RESET_DIV,
+			     drv_data->domains[power_domain->id].mipi_phy_rst_mask);
+
+	return 0;
+clk_disable:
+	imx8m_blk_ctrl_enable_domain_clk(dev, power_domain->id, false);
+bus_powerdown:
+	power_domain_off(&priv->bus_power_dev);
+	return ret;
+}
+
+static int imx8m_blk_ctrl_power_off(struct power_domain *power_domain)
+{
+	struct udevice *dev = power_domain->dev;
+	struct imx8m_blk_ctrl *priv = (struct imx8m_blk_ctrl *)dev_get_priv(dev);
+	struct imx8m_blk_ctrl_data *drv_data =
+		(struct imx8m_blk_ctrl_data *)dev_get_driver_data(dev);
+
+	debug("%s, id %lu\n", __func__, power_domain->id);
+
+	if (!priv->domains[power_domain->id].power_dev.dev)
+		return -ENODEV;
+
+	/* put devices into reset and disable clocks */
+	if (drv_data->domains[power_domain->id].mipi_phy_rst_mask)
+		clrbits_le32(priv->base + BLK_MIPI_RESET_DIV,
+			     drv_data->domains[power_domain->id].mipi_phy_rst_mask);
+
+	/* assert reset */
+	clrbits_le32(priv->base + BLK_SFT_RSTN, drv_data->domains[power_domain->id].rst_mask);
+
+	/* gate clk */
+	clrbits_le32(priv->base + BLK_CLK_EN, drv_data->domains[power_domain->id].clk_mask);
+
+	/* power down upstream GPC domain */
+	power_domain_off(&priv->domains[power_domain->id].power_dev);
+
+	imx8m_blk_ctrl_enable_domain_clk(dev, power_domain->id, false);
+
+	/* power down bus domain */
+	power_domain_off(&priv->bus_power_dev);
+
+	return 0;
+}
+
+static int imx8m_blk_ctrl_probe(struct udevice *dev)
+{
+	int ret, i, j;
+	struct imx8m_blk_ctrl *priv = (struct imx8m_blk_ctrl *)dev_get_priv(dev);
+	struct imx8m_blk_ctrl_data *drv_data =
+		(struct imx8m_blk_ctrl_data *)dev_get_driver_data(dev);
+
+	priv->base = dev_read_addr_ptr(dev);
+	if (!priv->base)
+		return -EINVAL;
+
+	priv->domains = kcalloc(drv_data->num_domains,
+				sizeof(struct imx8m_blk_ctrl_domain), GFP_KERNEL);
+
+	ret = power_domain_get_by_name(dev, &priv->bus_power_dev, "bus");
+	if (ret) {
+		printf("Failed to power_domain_get_by_name %s\n", "bus");
+		return ret;
+	}
+
+	for (j = 0; j < drv_data->num_domains; j++) {
+		ret = power_domain_get_by_name(dev, &priv->domains[j].power_dev,
+					       drv_data->domains[j].gpc_name);
+		if (ret)
+			continue;
+
+		for (i = 0; i < drv_data->domains[j].num_clks; i++) {
+			ret = clk_get_by_name(dev, drv_data->domains[j].clk_names[i],
+					      &priv->domains[j].clks[i]);
+			if (ret) {
+				printf("Failed to get clk %s\n", drv_data->domains[j].clk_names[i]);
+				return ret;
+			}
+		}
+	}
+
+	return 0;
+}
+
+static int imx8m_blk_ctrl_remove(struct udevice *dev)
+{
+	struct imx8m_blk_ctrl *priv = (struct imx8m_blk_ctrl *)dev_get_priv(dev);
+
+	kfree(priv->domains);
+
+	return 0;
+}
+
+static const struct imx8m_blk_ctrl_domain_data imx8mm_disp_blk_ctl_domain_data[] = {
+	[IMX8MM_DISPBLK_PD_CSI_BRIDGE] = {
+		.name = "dispblk-csi-bridge",
+		.clk_names = (const char *[]){ "csi-bridge-axi", "csi-bridge-apb",
+					       "csi-bridge-core", },
+		.num_clks = 3,
+		.gpc_name = "csi-bridge",
+		.rst_mask = BIT(0) | BIT(1) | BIT(2),
+		.clk_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5),
+	},
+	[IMX8MM_DISPBLK_PD_LCDIF] = {
+		.name = "dispblk-lcdif",
+		.clk_names = (const char *[]){ "lcdif-axi", "lcdif-apb", "lcdif-pix", },
+		.num_clks = 3,
+		.gpc_name = "lcdif",
+		.clk_mask = BIT(6) | BIT(7),
+	},
+	[IMX8MM_DISPBLK_PD_MIPI_DSI] = {
+		.name = "dispblk-mipi-dsi",
+		.clk_names = (const char *[]){ "dsi-pclk", "dsi-ref", },
+		.num_clks = 2,
+		.gpc_name = "mipi-dsi",
+		.rst_mask = BIT(5),
+		.clk_mask = BIT(8) | BIT(9),
+		.mipi_phy_rst_mask = BIT(17),
+	},
+	[IMX8MM_DISPBLK_PD_MIPI_CSI] = {
+		.name = "dispblk-mipi-csi",
+		.clk_names = (const char *[]){ "csi-aclk", "csi-pclk" },
+		.num_clks = 2,
+		.gpc_name = "mipi-csi",
+		.rst_mask = BIT(3) | BIT(4),
+		.clk_mask = BIT(10) | BIT(11),
+		.mipi_phy_rst_mask = BIT(16),
+	},
+};
+
+static const struct imx8m_blk_ctrl_data imx8mm_disp_blk_ctl_dev_data = {
+	.max_reg = 0x2c,
+	.domains = imx8mm_disp_blk_ctl_domain_data,
+	.num_domains = ARRAY_SIZE(imx8mm_disp_blk_ctl_domain_data),
+	.bus_rst_mask = BIT(6),
+	.bus_clk_mask = BIT(12),
+};
+
+static const struct imx8m_blk_ctrl_domain_data imx8mn_disp_blk_ctl_domain_data[] = {
+	[IMX8MN_DISPBLK_PD_MIPI_DSI] = {
+		.name = "dispblk-mipi-dsi",
+		.clk_names = (const char *[]){ "dsi-pclk", "dsi-ref", },
+		.num_clks = 2,
+		.gpc_name = "mipi-dsi",
+		.rst_mask = BIT(0) | BIT(1),
+		.clk_mask = BIT(0) | BIT(1),
+		.mipi_phy_rst_mask = BIT(17),
+	},
+	[IMX8MN_DISPBLK_PD_MIPI_CSI] = {
+		.name = "dispblk-mipi-csi",
+		.clk_names = (const char *[]){ "csi-aclk", "csi-pclk" },
+		.num_clks = 2,
+		.gpc_name = "mipi-csi",
+		.rst_mask = BIT(2) | BIT(3),
+		.clk_mask = BIT(2) | BIT(3),
+		.mipi_phy_rst_mask = BIT(16),
+	},
+	[IMX8MN_DISPBLK_PD_LCDIF] = {
+		.name = "dispblk-lcdif",
+		.clk_names = (const char *[]){ "lcdif-axi", "lcdif-apb", "lcdif-pix", },
+		.num_clks = 3,
+		.gpc_name = "lcdif",
+		.rst_mask = BIT(4) | BIT(5),
+		.clk_mask = BIT(4) | BIT(5),
+	},
+	[IMX8MN_DISPBLK_PD_ISI] = {
+		.name = "dispblk-isi",
+		.clk_names = (const char *[]){ "disp_axi", "disp_apb", "disp_axi_root",
+						"disp_apb_root"},
+		.num_clks = 4,
+		.gpc_name = "isi",
+		.rst_mask = BIT(6) | BIT(7),
+		.clk_mask = BIT(6) | BIT(7),
+	},
+};
+
+static const struct imx8m_blk_ctrl_data imx8mn_disp_blk_ctl_dev_data = {
+	.max_reg = 0x84,
+	.domains = imx8mn_disp_blk_ctl_domain_data,
+	.num_domains = ARRAY_SIZE(imx8mn_disp_blk_ctl_domain_data),
+	.bus_rst_mask = BIT(8),
+	.bus_clk_mask = BIT(8),
+};
+
+static const struct imx8m_blk_ctrl_domain_data imx8mp_media_blk_ctl_domain_data[] = {
+	[IMX8MP_MEDIABLK_PD_MIPI_DSI_1] = {
+		.name = "mediablk-mipi-dsi-1",
+		.clk_names = (const char *[]){ "apb", "phy", },
+		.num_clks = 2,
+		.gpc_name = "mipi-dsi1",
+		.rst_mask = BIT(0) | BIT(1),
+		.clk_mask = BIT(0) | BIT(1),
+		.mipi_phy_rst_mask = BIT(17),
+	},
+	[IMX8MP_MEDIABLK_PD_MIPI_CSI2_1] = {
+		.name = "mediablk-mipi-csi2-1",
+		.clk_names = (const char *[]){ "apb", "cam1" },
+		.num_clks = 2,
+		.gpc_name = "mipi-csi1",
+		.rst_mask = BIT(2) | BIT(3),
+		.clk_mask = BIT(2) | BIT(3),
+		.mipi_phy_rst_mask = BIT(16),
+	},
+	[IMX8MP_MEDIABLK_PD_LCDIF_1] = {
+		.name = "mediablk-lcdif-1",
+		.clk_names = (const char *[]){ "disp1", "apb", "axi", },
+		.num_clks = 3,
+		.gpc_name = "lcdif1",
+		.rst_mask = BIT(4) | BIT(5) | BIT(23),
+		.clk_mask = BIT(4) | BIT(5) | BIT(23),
+	},
+	[IMX8MP_MEDIABLK_PD_ISI] = {
+		.name = "mediablk-isi",
+		.clk_names = (const char *[]){ "axi", "apb" },
+		.num_clks = 2,
+		.gpc_name = "isi",
+		.rst_mask = BIT(6) | BIT(7),
+		.clk_mask = BIT(6) | BIT(7),
+	},
+	[IMX8MP_MEDIABLK_PD_MIPI_CSI2_2] = {
+		.name = "mediablk-mipi-csi2-2",
+		.clk_names = (const char *[]){ "apb", "cam2" },
+		.num_clks = 2,
+		.gpc_name = "mipi-csi2",
+		.rst_mask = BIT(9) | BIT(10),
+		.clk_mask = BIT(9) | BIT(10),
+		.mipi_phy_rst_mask = BIT(30),
+	},
+	[IMX8MP_MEDIABLK_PD_LCDIF_2] = {
+		.name = "mediablk-lcdif-2",
+		.clk_names = (const char *[]){ "disp2", "apb", "axi", },
+		.num_clks = 3,
+		.gpc_name = "lcdif2",
+		.rst_mask = BIT(11) | BIT(12) | BIT(24),
+		.clk_mask = BIT(11) | BIT(12) | BIT(24),
+	},
+	[IMX8MP_MEDIABLK_PD_ISP] = {
+		.name = "mediablk-isp",
+		.clk_names = (const char *[]){ "isp", "axi", "apb" },
+		.num_clks = 3,
+		.gpc_name = "isp",
+		.rst_mask = BIT(16) | BIT(17) | BIT(18),
+		.clk_mask = BIT(16) | BIT(17) | BIT(18),
+	},
+	[IMX8MP_MEDIABLK_PD_DWE] = {
+		.name = "mediablk-dwe",
+		.clk_names = (const char *[]){ "axi", "apb" },
+		.num_clks = 2,
+		.gpc_name = "dwe",
+		.rst_mask = BIT(19) | BIT(20) | BIT(21),
+		.clk_mask = BIT(19) | BIT(20) | BIT(21),
+	},
+	[IMX8MP_MEDIABLK_PD_MIPI_DSI_2] = {
+		.name = "mediablk-mipi-dsi-2",
+		.clk_names = (const char *[]){ "phy", },
+		.num_clks = 1,
+		.gpc_name = "mipi-dsi2",
+		.rst_mask = BIT(22),
+		.clk_mask = BIT(22),
+		.mipi_phy_rst_mask = BIT(29),
+	},
+};
+
+static const struct imx8m_blk_ctrl_data imx8mp_media_blk_ctl_dev_data = {
+	.max_reg = 0x138,
+	.domains = imx8mp_media_blk_ctl_domain_data,
+	.num_domains = ARRAY_SIZE(imx8mp_media_blk_ctl_domain_data),
+	.bus_rst_mask = BIT(8),
+	.bus_clk_mask = BIT(8),
+};
+
+static const struct udevice_id imx8m_blk_ctrl_ids[] = {
+	{.compatible = "fsl,imx8mm-disp-blk-ctrl", .data = (ulong)&imx8mm_disp_blk_ctl_dev_data},
+	{.compatible = "fsl,imx8mn-disp-blk-ctrl", .data = (ulong)&imx8mn_disp_blk_ctl_dev_data},
+	{.compatible = "fsl,imx8mp-media-blk-ctrl", .data = (ulong)&imx8mp_media_blk_ctl_dev_data},
+	{}
+};
+
+struct power_domain_ops imx8m_blk_ctrl_ops = {
+	.request = imx8m_blk_ctrl_request,
+	.rfree = imx8m_blk_ctrl_free,
+	.on = imx8m_blk_ctrl_power_on,
+	.off = imx8m_blk_ctrl_power_off,
+};
+
+U_BOOT_DRIVER(imx8m_blk_ctrl) = {
+	.name = "imx8m_blk_ctrl",
+	.id = UCLASS_POWER_DOMAIN,
+	.of_match = imx8m_blk_ctrl_ids,
+	.bind = dm_scan_fdt_dev,
+	.probe = imx8m_blk_ctrl_probe,
+	.remove = imx8m_blk_ctrl_remove,
+	.priv_auto	= sizeof(struct imx8m_blk_ctrl),
+	.ops = &imx8m_blk_ctrl_ops,
+	.flags  = DM_FLAG_DEFAULT_PD_CTRL_OFF,
+};
diff --git a/drivers/power/domain/imx8m-power-domain.c b/drivers/power/domain/imx8m-power-domain.c
index 8b6870c86463..40fec70d954a 100644
--- a/drivers/power/domain/imx8m-power-domain.c
+++ b/drivers/power/domain/imx8m-power-domain.c
@@ -32,17 +32,31 @@ DECLARE_GLOBAL_DATA_PTR;
 #define IMX8M_OTG1_A53_DOMAIN			BIT(4)
 #define IMX8M_PCIE1_A53_DOMAIN			BIT(3)
 
+#define IMX8MM_VPUH1_A53_DOMAIN			BIT(15)
+#define IMX8MM_VPUG2_A53_DOMAIN			BIT(14)
+#define IMX8MM_VPUG1_A53_DOMAIN			BIT(13)
+#define IMX8MM_DISPMIX_A53_DOMAIN		BIT(12)
+#define IMX8MM_VPUMIX_A53_DOMAIN		BIT(10)
+#define IMX8MM_GPUMIX_A53_DOMAIN		BIT(9)
+#define IMX8MM_GPU_A53_DOMAIN			(BIT(8) | BIT(11))
+#define IMX8MM_DDR1_A53_DOMAIN			BIT(7)
 #define IMX8MM_OTG2_A53_DOMAIN			BIT(5)
 #define IMX8MM_OTG1_A53_DOMAIN			BIT(4)
 #define IMX8MM_PCIE_A53_DOMAIN			BIT(3)
+#define IMX8MM_MIPI_A53_DOMAIN			BIT(2)
 
+#define IMX8MN_DISPMIX_A53_DOMAIN		BIT(12)
+#define IMX8MN_GPUMIX_A53_DOMAIN		BIT(9)
+#define IMX8MN_DDR1_A53_DOMAIN		BIT(7)
 #define IMX8MN_OTG1_A53_DOMAIN			BIT(4)
 #define IMX8MN_MIPI_A53_DOMAIN			BIT(2)
 
 #define IMX8MP_HSIOMIX_A53_DOMAIN		BIT(19)
+#define IMX8MP_MEDIAMIX_A53_DOMAIN		BIT(12)
 #define IMX8MP_USB2_PHY_A53_DOMAIN		BIT(5)
 #define IMX8MP_USB1_PHY_A53_DOMAIN		BIT(4)
 #define IMX8MP_PCIE_PHY_A53_DOMAIN		BIT(3)
+#define IMX8MP_MIPI_PHY1_A53_DOMAIN		BIT(2)
 
 #define IMX8MP_GPC_PU_PGC_SW_PUP_REQ		0x0d8
 #define IMX8MP_GPC_PU_PGC_SW_PDN_REQ		0x0e4
@@ -50,35 +64,72 @@ DECLARE_GLOBAL_DATA_PTR;
 #define GPC_PU_PGC_SW_PUP_REQ			0x0f8
 #define GPC_PU_PGC_SW_PDN_REQ			0x104
 
+#define IMX8M_PCIE2_SW_Pxx_REQ			BIT(13)
+#define IMX8M_MIPI_CSI2_SW_Pxx_REQ		BIT(12)
+#define IMX8M_MIPI_CSI1_SW_Pxx_REQ		BIT(11)
+#define IMX8M_DISP_SW_Pxx_REQ			BIT(10)
+#define IMX8M_HDMI_SW_Pxx_REQ			BIT(9)
+#define IMX8M_VPU_SW_Pxx_REQ			BIT(8)
+#define IMX8M_GPU_SW_Pxx_REQ			BIT(7)
+#define IMX8M_DDR2_SW_Pxx_REQ			BIT(6)
+#define IMX8M_DDR1_SW_Pxx_REQ			BIT(5)
 #define IMX8M_PCIE2_SW_Pxx_REQ			BIT(13)
 #define IMX8M_OTG2_SW_Pxx_REQ			BIT(3)
 #define IMX8M_OTG1_SW_Pxx_REQ			BIT(2)
 #define IMX8M_PCIE1_SW_Pxx_REQ			BIT(1)
 
+#define IMX8MM_VPUH1_SW_Pxx_REQ			BIT(13)
+#define IMX8MM_VPUG2_SW_Pxx_REQ			BIT(12)
+#define IMX8MM_VPUG1_SW_Pxx_REQ			BIT(11)
+#define IMX8MM_DISPMIX_SW_Pxx_REQ		BIT(10)
+#define IMX8MM_VPUMIX_SW_Pxx_REQ		BIT(8)
+#define IMX8MM_GPUMIX_SW_Pxx_REQ		BIT(7)
+#define IMX8MM_GPU_SW_Pxx_REQ			(BIT(6) | BIT(9))
+#define IMX8MM_DDR1_SW_Pxx_REQ			BIT(5)
 #define IMX8MM_OTG2_SW_Pxx_REQ			BIT(3)
 #define IMX8MM_OTG1_SW_Pxx_REQ			BIT(2)
 #define IMX8MM_PCIE_SW_Pxx_REQ			BIT(1)
+#define IMX8MM_MIPI_SW_Pxx_REQ			BIT(0)
 
+#define IMX8MN_DISPMIX_SW_Pxx_REQ		BIT(10)
+#define IMX8MN_GPUMIX_SW_Pxx_REQ		BIT(7)
+#define IMX8MN_DDR1_SW_Pxx_REQ			BIT(5)
 #define IMX8MN_OTG1_SW_Pxx_REQ			BIT(2)
 #define IMX8MN_MIPI_SW_Pxx_REQ			BIT(0)
 
 #define IMX8MP_HSIOMIX_Pxx_REQ			BIT(17)
+#define IMX8MP_MEDIMIX_Pxx_REQ			BIT(10)
 #define IMX8MP_USB2_PHY_Pxx_REQ			BIT(3)
 #define IMX8MP_USB1_PHY_Pxx_REQ			BIT(2)
 #define IMX8MP_PCIE_PHY_SW_Pxx_REQ		BIT(1)
+#define IMX8MP_MIPI_PHY1_SW_Pxx_REQ		BIT(0)
 
 #define GPC_M4_PU_PDN_FLG			0x1bc
 
 #define IMX8MP_GPC_PU_PWRHSK			0x190
 #define GPC_PU_PWRHSK				0x1fc
 
+#define IMX8MM_GPUMIX_HSK_PWRDNACKN		BIT(29)
+#define IMX8MM_GPU_HSK_PWRDNACKN		(BIT(27) | BIT(28))
+#define IMX8MM_VPUMIX_HSK_PWRDNACKN		BIT(26)
+#define IMX8MM_DISPMIX_HSK_PWRDNACKN		BIT(25)
 #define IMX8MM_HSIO_HSK_PWRDNACKN		(BIT(23) | BIT(24))
+#define IMX8MM_GPUMIX_HSK_PWRDNREQN		BIT(11)
+#define IMX8MM_GPU_HSK_PWRDNREQN		(BIT(9) | BIT(10))
+#define IMX8MM_VPUMIX_HSK_PWRDNREQN		BIT(8)
+#define IMX8MM_DISPMIX_HSK_PWRDNREQN		BIT(7)
 #define IMX8MM_HSIO_HSK_PWRDNREQN		(BIT(5) | BIT(6))
 
+#define IMX8MN_GPUMIX_HSK_PWRDNACKN		(BIT(29) | BIT(27))
+#define IMX8MN_DISPMIX_HSK_PWRDNACKN		BIT(25)
 #define IMX8MN_HSIO_HSK_PWRDNACKN		BIT(23)
+#define IMX8MN_GPUMIX_HSK_PWRDNREQN		(BIT(11) | BIT(9))
+#define IMX8MN_DISPMIX_HSK_PWRDNREQN		BIT(7)
 #define IMX8MN_HSIO_HSK_PWRDNREQN		BIT(5)
 
+#define IMX8MP_MEDIAMIX_PWRDNACKN		BIT(30)
 #define IMX8MP_HSIOMIX_PWRDNACKN		BIT(28)
+#define IMX8MP_MEDIAMIX_PWRDNREQN		BIT(14)
 #define IMX8MP_HSIOMIX_PWRDNREQN		BIT(12)
 
 /*
@@ -92,15 +143,31 @@ DECLARE_GLOBAL_DATA_PTR;
 #define IMX8M_PGC_OTG2			19
 #define IMX8M_PGC_PCIE2			29
 
+#define IMX8MM_PGC_MIPI			16
 #define IMX8MM_PGC_PCIE			17
 #define IMX8MM_PGC_OTG1			18
 #define IMX8MM_PGC_OTG2			19
-
+#define IMX8MM_PGC_DDR1			21
+#define IMX8MM_PGC_GPU2D		22
+#define IMX8MM_PGC_GPUMIX		23
+#define IMX8MM_PGC_VPUMIX		24
+#define IMX8MM_PGC_GPU3D		25
+#define IMX8MM_PGC_DISPMIX		26
+#define IMX8MM_PGC_VPUG1		27
+#define IMX8MM_PGC_VPUG2		28
+#define IMX8MM_PGC_VPUH1		29
+
+#define IMX8MN_PGC_MIPI			16
 #define IMX8MN_PGC_OTG1			18
+#define IMX8MN_PGC_DDR1			21
+#define IMX8MN_PGC_GPUMIX		23
+#define IMX8MN_PGC_DISPMIX		26
 
+#define IMX8MP_PGC_MIPI1		12
 #define IMX8MP_PGC_PCIE			13
 #define IMX8MP_PGC_USB1			14
 #define IMX8MP_PGC_USB2			15
+#define IMX8MP_PGC_MEDIAMIX		22
 #define IMX8MP_PGC_HSIOMIX		29
 
 #define GPC_PGC_CTRL(n)			(0x800 + (n) * 0x40)
@@ -142,6 +209,7 @@ struct imx8m_power_domain_plat {
 	void __iomem *base;
 	int resource_id;
 	int has_pd;
+	int count;
 };
 
 #if defined(CONFIG_IMX8MM) || defined(CONFIG_IMX8MN) || defined(CONFIG_IMX8MQ)
@@ -230,6 +298,82 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
 		},
 		.pgc   = BIT(IMX8MM_PGC_OTG2),
 	},
+
+	[IMX8MM_POWER_DOMAIN_GPUMIX] = {
+		.bits  = {
+			.pxx = IMX8MM_GPUMIX_SW_Pxx_REQ,
+			.map = IMX8MM_GPUMIX_A53_DOMAIN,
+			.hskreq = IMX8MM_GPUMIX_HSK_PWRDNREQN,
+			.hskack = IMX8MM_GPUMIX_HSK_PWRDNACKN,
+		},
+		.pgc   = BIT(IMX8MM_PGC_GPUMIX),
+		.keep_clocks = true,
+	},
+
+	[IMX8MM_POWER_DOMAIN_GPU] = {
+		.bits  = {
+			.pxx = IMX8MM_GPU_SW_Pxx_REQ,
+			.map = IMX8MM_GPU_A53_DOMAIN,
+			.hskreq = IMX8MM_GPU_HSK_PWRDNREQN,
+			.hskack = IMX8MM_GPU_HSK_PWRDNACKN,
+		},
+		.pgc   = BIT(IMX8MM_PGC_GPU2D) | BIT(IMX8MM_PGC_GPU3D),
+	},
+
+	[IMX8MM_POWER_DOMAIN_VPUMIX] = {
+		.bits  = {
+			.pxx = IMX8MM_VPUMIX_SW_Pxx_REQ,
+			.map = IMX8MM_VPUMIX_A53_DOMAIN,
+			.hskreq = IMX8MM_VPUMIX_HSK_PWRDNREQN,
+			.hskack = IMX8MM_VPUMIX_HSK_PWRDNACKN,
+		},
+		.pgc   = BIT(IMX8MM_PGC_VPUMIX),
+		.keep_clocks = true,
+	},
+
+	[IMX8MM_POWER_DOMAIN_VPUG1] = {
+		.bits  = {
+			.pxx = IMX8MM_VPUG1_SW_Pxx_REQ,
+			.map = IMX8MM_VPUG1_A53_DOMAIN,
+		},
+		.pgc   = BIT(IMX8MM_PGC_VPUG1),
+	},
+
+	[IMX8MM_POWER_DOMAIN_VPUG2] = {
+		.bits  = {
+			.pxx = IMX8MM_VPUG2_SW_Pxx_REQ,
+			.map = IMX8MM_VPUG2_A53_DOMAIN,
+		},
+		.pgc   = BIT(IMX8MM_PGC_VPUG2),
+	},
+
+	[IMX8MM_POWER_DOMAIN_VPUH1] = {
+		.bits  = {
+			.pxx = IMX8MM_VPUH1_SW_Pxx_REQ,
+			.map = IMX8MM_VPUH1_A53_DOMAIN,
+		},
+		.pgc   = BIT(IMX8MM_PGC_VPUH1),
+		.keep_clocks = true,
+	},
+
+	[IMX8MM_POWER_DOMAIN_DISPMIX] = {
+		.bits  = {
+			.pxx = IMX8MM_DISPMIX_SW_Pxx_REQ,
+			.map = IMX8MM_DISPMIX_A53_DOMAIN,
+			.hskreq = IMX8MM_DISPMIX_HSK_PWRDNREQN,
+			.hskack = IMX8MM_DISPMIX_HSK_PWRDNACKN,
+		},
+		.pgc   = BIT(IMX8MM_PGC_DISPMIX),
+		.keep_clocks = true,
+	},
+
+	[IMX8MM_POWER_DOMAIN_MIPI] = {
+		.bits  = {
+			.pxx = IMX8MM_MIPI_SW_Pxx_REQ,
+			.map = IMX8MM_MIPI_A53_DOMAIN,
+		},
+		.pgc   = BIT(IMX8MM_PGC_MIPI),
+	},
 };
 
 static const struct imx_pgc_domain_data imx8mm_pgc_domain_data = {
@@ -258,6 +402,36 @@ static const struct imx_pgc_domain imx8mn_pgc_domains[] = {
 		},
 		.pgc   = BIT(IMX8MN_PGC_OTG1),
 	},
+
+	[IMX8MN_POWER_DOMAIN_GPUMIX] = {
+		.bits  = {
+			.pxx = IMX8MN_GPUMIX_SW_Pxx_REQ,
+			.map = IMX8MN_GPUMIX_A53_DOMAIN,
+			.hskreq = IMX8MN_GPUMIX_HSK_PWRDNREQN,
+			.hskack = IMX8MN_GPUMIX_HSK_PWRDNACKN,
+		},
+		.pgc   = BIT(IMX8MN_PGC_GPUMIX),
+		.keep_clocks = true,
+	},
+
+	[IMX8MN_POWER_DOMAIN_DISPMIX] = {
+		.bits  = {
+			.pxx = IMX8MN_DISPMIX_SW_Pxx_REQ,
+			.map = IMX8MN_DISPMIX_A53_DOMAIN,
+			.hskreq = IMX8MN_DISPMIX_HSK_PWRDNREQN,
+			.hskack = IMX8MN_DISPMIX_HSK_PWRDNACKN,
+		},
+		.pgc   = BIT(IMX8MN_PGC_DISPMIX),
+		.keep_clocks = true,
+	},
+
+	[IMX8MN_POWER_DOMAIN_MIPI] = {
+		.bits  = {
+			.pxx = IMX8MN_MIPI_SW_Pxx_REQ,
+			.map = IMX8MN_MIPI_A53_DOMAIN,
+		},
+		.pgc   = BIT(IMX8MN_PGC_MIPI),
+	},
 };
 
 static const struct imx_pgc_domain_data imx8mn_pgc_domain_data = {
@@ -268,7 +442,15 @@ static const struct imx_pgc_domain_data imx8mn_pgc_domain_data = {
 #endif
 
 #ifdef CONFIG_IMX8MP
-static const struct imx_pgc_domain imx8mp_pgc_domains[] = {
+static const struct imx_pgc_domain imx8mp_pgc_domains[19] = {
+	[IMX8MP_POWER_DOMAIN_MIPI_PHY1] = {
+		.bits = {
+			.pxx = IMX8MP_MIPI_PHY1_SW_Pxx_REQ,
+			.map = IMX8MP_MIPI_PHY1_A53_DOMAIN,
+		},
+		.pgc = BIT(IMX8MP_PGC_MIPI1),
+	},
+
 	[IMX8MP_POWER_DOMAIN_PCIE_PHY] = {
 		.bits = {
 			.pxx = IMX8MP_PCIE_PHY_SW_Pxx_REQ,
@@ -293,6 +475,17 @@ static const struct imx_pgc_domain imx8mp_pgc_domains[] = {
 		.pgc = BIT(IMX8MP_PGC_USB2),
 	},
 
+	[IMX8MP_POWER_DOMAIN_MEDIAMIX] = {
+		.bits = {
+			.pxx = IMX8MP_MEDIMIX_Pxx_REQ,
+			.map = IMX8MP_MEDIAMIX_A53_DOMAIN,
+			.hskreq = IMX8MP_MEDIAMIX_PWRDNREQN,
+			.hskack = IMX8MP_MEDIAMIX_PWRDNACKN,
+		},
+		.pgc = BIT(IMX8MP_PGC_MEDIAMIX),
+		.keep_clocks = true,
+	},
+
 	[IMX8MP_POWER_DOMAIN_HSIOMIX] = {
 		.bits = {
 			.pxx = IMX8MP_HSIOMIX_Pxx_REQ,
@@ -329,6 +522,11 @@ static int imx8m_power_domain_on(struct power_domain *power_domain)
 	u32 pgc;
 	int ret;
 
+	if (pdata->count > 0) { /* Already on */
+		pdata->count++;
+		return 0;
+	}
+
 	if (pdata->clk.count) {
 		ret = clk_enable_bulk(&pdata->clk);
 		if (ret) {
@@ -373,6 +571,8 @@ static int imx8m_power_domain_on(struct power_domain *power_domain)
 	if (!domain->keep_clocks && pdata->clk.count)
 		clk_disable_bulk(&pdata->clk);
 
+	pdata->count++;
+
 	return 0;
 
 out_clk_disable:
@@ -391,6 +591,13 @@ static int imx8m_power_domain_off(struct power_domain *power_domain)
 	u32 pgc;
 	int ret;
 
+	if (!pdata->count) { /* Already off */
+		return 0;
+	} else if (pdata->count > 1) {
+		pdata->count--;
+		return 0;
+	}
+
 	/* Enable reset clocks for all devices in the domain */
 	if (!domain->keep_clocks && pdata->clk.count) {
 		ret = clk_enable_bulk(&pdata->clk);
@@ -439,6 +646,8 @@ static int imx8m_power_domain_off(struct power_domain *power_domain)
 	if (pdata->has_pd)
 		power_domain_off(&pdata->pd);
 
+	pdata->count--;
+
 	return 0;
 
 out_clk_disable:
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 09/26] video: Add video link framework
  2024-09-13  9:55 [PATCH 00/26] Support display (and even more) on the BSH SMM S2/PRO boards Dario Binacchi
                   ` (7 preceding siblings ...)
  2024-09-13  9:55 ` [PATCH 08/26] power: Add iMX8M block ctrl driver for dispmix Dario Binacchi
@ 2024-09-13  9:55 ` Dario Binacchi
  2024-09-13  9:55 ` [PATCH 10/26] video: bridge: Add check_timing interface Dario Binacchi
                   ` (17 subsequent siblings)
  26 siblings, 0 replies; 48+ messages in thread
From: Dario Binacchi @ 2024-09-13  9:55 UTC (permalink / raw)
  To: u-boot
  Cc: Fabio Estevam, linux-amarula, michael, Miquel Raynal, Ye Li,
	Dario Binacchi, Anatolij Gustschin, Anton Bambura,
	Heinrich Schuchardt, Jonas Schwöbel, Marek Vasut,
	Simon Glass, Svyatoslav Ryhel, Tom Rini

From: Michael Trimarchi <michael@amarulasolutions.com>

The video link framework bases a port-endpoint gragh in DTB to
connect the video components in uclass like: video, display, bridge,
and panel.

Using the port-endpoint gragh, we manage multiple video link and
user can select one of them for splash screen.

Signed-off-by: Ye Li <ye.li@nxp.com>
Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---

 common/stdio.c             |   4 +
 drivers/video/Kconfig      |   6 +
 drivers/video/Makefile     |   1 +
 drivers/video/video_link.c | 529 +++++++++++++++++++++++++++++++++++++
 include/video_link.h       |  19 ++
 5 files changed, 559 insertions(+)
 create mode 100644 drivers/video/video_link.c
 create mode 100644 include/video_link.h

diff --git a/common/stdio.c b/common/stdio.c
index a61220ce4b9c..66360c97ed12 100644
--- a/common/stdio.c
+++ b/common/stdio.c
@@ -17,6 +17,7 @@
 #include <stdio_dev.h>
 #include <serial.h>
 #include <splash.h>
+#include <video_link.h>
 #include <i2c.h>
 #include <asm/global_data.h>
 #include <dm/device-internal.h>
@@ -340,6 +341,9 @@ int stdio_add_devices(void)
 		struct udevice *vdev;
 		int ret;
 
+		if (IS_ENABLED(CONFIG_VIDEO_LINK))
+			video_link_init();
+
 		if (!IS_ENABLED(CONFIG_SYS_CONSOLE_IS_IN_ENV)) {
 			for (ret = uclass_first_device_check(UCLASS_VIDEO,
 							     &vdev);
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 6e79694fd192..cafdc15f9fe2 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -833,6 +833,12 @@ config VIDEO_SEPS525
 source "drivers/video/zynqmp/Kconfig"
 source "drivers/video/nexell/Kconfig"
 
+config VIDEO_LINK
+	bool "Enable video link framework support"
+	help
+	   This option enables a video link framework basing on port-endpoint graph
+	   to connect video components.
+
 config CONSOLE_SCROLL_LINES
 	int "Number of lines to scroll the console by"
 	default 1
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index f3f70cd04a17..9fd3645994f1 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -27,6 +27,7 @@ obj-$(CONFIG_$(SPL_TPL_)SIMPLE_PANEL) += simple_panel.o
 obj-$(CONFIG_VIDEO_LOGO) += u_boot_logo.o
 obj-$(CONFIG_$(SPL_TPL_)BMP) += bmp.o
 
+obj-$(CONFIG_VIDEO_LINK) += video_link.o
 endif
 
 obj-$(CONFIG_BACKLIGHT_LM3533) += lm3533_backlight.o
diff --git a/drivers/video/video_link.c b/drivers/video/video_link.c
new file mode 100644
index 000000000000..001a759faab9
--- /dev/null
+++ b/drivers/video/video_link.c
@@ -0,0 +1,529 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2020 NXP
+ *
+ */
+
+#include <command.h>
+#include <linux/errno.h>
+
+#include <dm.h>
+#include <dm/uclass-internal.h>
+#include <dm/device-internal.h>
+#include <dm/ofnode.h>
+#include <dm/read.h>
+#include <video.h>
+#include <panel.h>
+#include <env.h>
+
+struct of_endpoint {
+	unsigned int port;
+	unsigned int id;
+	ofnode local_node;
+};
+
+#define MAX_LINKS 3
+#define MAX_LINK_DEVICES 5
+
+struct video_link {
+	struct udevice *link_devs[MAX_LINK_DEVICES];
+	int dev_num;
+};
+
+struct video_link video_links[MAX_LINKS];
+struct video_link temp_stack;
+ulong video_links_num;
+ulong curr_video_link;
+bool video_off;
+
+ofnode ofnode_get_child_by_name(ofnode parent, const char *name)
+{
+	ofnode child;
+	const char *child_name;
+
+	for (child = ofnode_first_subnode(parent);
+	     ofnode_valid(child);
+	     child = ofnode_next_subnode(child)) {
+		child_name = ofnode_get_name(child);
+
+		if (!strncmp(child_name, name, strlen(name)))
+			break;
+	}
+	return child;
+}
+
+ofnode ofnode_graph_get_next_endpoint(ofnode parent,
+				      ofnode prev)
+{
+	ofnode endpoint;
+	ofnode port;
+	const char *name;
+
+	if (!ofnode_valid(prev)) {
+		ofnode node;
+
+		node = ofnode_find_subnode(parent, "ports");
+		if (ofnode_valid(node))
+			parent = node;
+
+		port = ofnode_get_child_by_name(parent, "port");
+		if (!ofnode_valid(port)) {
+			debug("no port node found in 0x%lx\n", parent.of_offset);
+			return ofnode_null();
+		}
+
+		endpoint = ofnode_first_subnode(port);
+		if (ofnode_valid(endpoint)) {
+			debug("get next endpoint %s\n", ofnode_get_name(endpoint));
+			return endpoint;
+		}
+	} else {
+		port = ofnode_get_parent(prev);
+		endpoint = ofnode_next_subnode(prev);
+		if (ofnode_valid(endpoint)) {
+			debug("get next endpoint %s\n", ofnode_get_name(endpoint));
+			return endpoint;
+		}
+	}
+
+	debug("port %s\n", ofnode_get_name(port));
+
+	while (1) {
+		do {
+			port = ofnode_next_subnode(port);
+			if (!ofnode_valid(port))
+				return ofnode_null();
+
+			name = ofnode_get_name(port);
+		} while (strncmp(name, "port", 4));
+
+		/*
+		 * Now that we have a port node, get the next endpoint by
+		 * getting the next child. If the previous endpoint is NULL this
+		 * will return the first child.
+		 */
+		endpoint = ofnode_first_subnode(port);
+		if (ofnode_valid(endpoint)) {
+			debug("get next endpoint %s\n", ofnode_get_name(endpoint));
+			return endpoint;
+		}
+	}
+
+	return ofnode_null();
+}
+
+#define for_each_endpoint_of_node(parent, child) \
+	for (child = ofnode_graph_get_next_endpoint(parent, ofnode_null()); ofnode_valid(child); \
+	     child = ofnode_graph_get_next_endpoint(parent, child))
+
+int ofnode_graph_get_endpoint_count(ofnode node)
+{
+	ofnode endpoint;
+	int num = 0;
+
+	for_each_endpoint_of_node(node, endpoint)
+		num++;
+
+	return num;
+}
+
+int ofnode_graph_parse_endpoint(ofnode node,
+				struct of_endpoint *endpoint)
+{
+	ofnode port_node = ofnode_get_parent(node);
+
+	memset(endpoint, 0, sizeof(*endpoint));
+
+	endpoint->local_node = node;
+	/*
+	 * It doesn't matter whether the two calls below succeed.
+	 * If they don't then the default value 0 is used.
+	 */
+	ofnode_read_u32(port_node, "reg", &endpoint->port);
+	ofnode_read_u32(node, "reg", &endpoint->id);
+
+	return 0;
+}
+
+ofnode ofnode_graph_get_endpoint_by_regs(const ofnode parent,
+					 int port_reg, int reg)
+{
+	struct of_endpoint endpoint;
+	ofnode node;
+
+	for_each_endpoint_of_node(parent, node) {
+		ofnode_graph_parse_endpoint(node, &endpoint);
+		if (((port_reg == -1) || endpoint.port == port_reg) &&
+		    ((reg == -1) || endpoint.id == reg)) {
+			debug("get node %s\n", ofnode_get_name(node));
+
+			return node;
+		}
+	}
+
+	return ofnode_null();
+}
+
+ofnode ofnode_graph_get_remote_endpoint(ofnode node)
+{
+	ofnode remote;
+	u32 phandle;
+	int ret;
+
+	ret = ofnode_read_u32(node, "remote-endpoint", &phandle);
+	if (ret) {
+		printf("required remote-endpoint property isn't provided\n");
+		return ofnode_null();
+	}
+
+	remote = ofnode_get_by_phandle(phandle);
+	if (!ofnode_valid(remote)) {
+		printf("failed to find remote-endpoint\n");
+		return ofnode_null();
+	}
+
+	return remote;
+}
+
+ofnode ofnode_graph_get_port_parent(ofnode node)
+{
+	unsigned int depth;
+
+	if (!ofnode_valid(node))
+		return ofnode_null();
+
+	/*
+	 * Preserve usecount for passed in node as of_get_next_parent()
+	 * will do of_node_put() on it.
+	 */
+
+	/* Walk 3 levels up only if there is 'ports' node. */
+	for (depth = 3; depth && ofnode_valid(node); depth--) {
+		node = ofnode_get_parent(node);
+		const char *name = ofnode_get_name(node);
+
+		if (depth == 2 && strcmp(name, "ports"))
+			break;
+	}
+	return node;
+}
+
+ofnode ofnode_graph_get_remote_port_parent(ofnode node)
+{
+	ofnode np, pp;
+
+	/* Get remote endpoint node. */
+	np = ofnode_graph_get_remote_endpoint(node);
+
+	pp = ofnode_graph_get_port_parent(np);
+
+	return pp;
+}
+
+int find_device_by_ofnode(ofnode node, struct udevice **pdev)
+{
+	int ret;
+
+	if (!ofnode_is_enabled(node))
+		return -2;
+
+	ret = uclass_find_device_by_ofnode(UCLASS_DISPLAY, node, pdev);
+	if (!ret)
+		return 0;
+
+	ret = uclass_find_device_by_ofnode(UCLASS_DSI_HOST, node, pdev);
+	if (!ret)
+		return 0;
+
+	ret = uclass_find_device_by_ofnode(UCLASS_VIDEO_BRIDGE, node, pdev);
+	if (!ret)
+		return 0;
+
+	ret = uclass_find_device_by_ofnode(UCLASS_PANEL, node, pdev);
+	if (!ret)
+		return 0;
+
+	return -1;
+}
+
+static void video_link_stack_push(struct udevice *dev)
+{
+	if (temp_stack.dev_num < MAX_LINK_DEVICES) {
+		temp_stack.link_devs[temp_stack.dev_num] = dev;
+		temp_stack.dev_num++;
+	}
+}
+
+static void video_link_stack_pop(void)
+{
+	if (temp_stack.dev_num > 0) {
+		temp_stack.link_devs[temp_stack.dev_num] = NULL;
+		temp_stack.dev_num--;
+	}
+}
+
+static int duplicate_video_link(void)
+{
+	if (video_links_num < MAX_LINKS) {
+		video_links[video_links_num] = temp_stack;
+		video_links_num++;
+
+		debug("duplicate links num %lu,  temp_stack num %d\n",
+		      video_links_num, temp_stack.dev_num);
+		return 0;
+	}
+
+	return -ENODEV;
+}
+
+static void video_link_add_node(struct udevice *peer_dev, struct udevice *dev, ofnode dev_node)
+{
+	int ret = 0;
+	ofnode remote, endpoint_node;
+	struct udevice *remote_dev;
+	bool find = false;
+
+	debug("endpoint cnt %d\n", ofnode_graph_get_endpoint_count(dev_node));
+
+	video_link_stack_push(dev);
+
+	for_each_endpoint_of_node(dev_node, endpoint_node) {
+		remote = ofnode_graph_get_remote_port_parent(endpoint_node);
+		if (!ofnode_valid(remote))
+			continue;
+
+		debug("remote %s\n", ofnode_get_name(remote));
+		ret = find_device_by_ofnode(remote, &remote_dev);
+		if (!ret) {
+			debug("remote dev %s\n", remote_dev->name);
+
+			if (peer_dev && peer_dev == remote_dev)
+				continue;
+
+			/* it is possible that ofnode of remote_dev is not equal to remote */
+			video_link_add_node(dev, remote_dev, remote);
+
+			find = true;
+		}
+	}
+
+	/* leaf node or no valid new endpoint, now copy the entire stack to a new video link */
+	if (!find) {
+		ret = duplicate_video_link();
+		if (ret)
+			printf("video link is full\n");
+	}
+
+	video_link_stack_pop();
+}
+
+struct udevice *video_link_get_next_device(struct udevice *curr_dev)
+{
+	int i, ret;
+
+	if (video_off)
+		return NULL;
+
+	if (curr_video_link >= video_links_num) {
+		printf("current video link is not correct\n");
+		return NULL;
+	}
+
+	for (i = 0; i < video_links[curr_video_link].dev_num; i++) {
+		if (video_links[curr_video_link].link_devs[i] == curr_dev) {
+			if ((i + 1) < video_links[curr_video_link].dev_num) {
+				ret = device_probe(video_links[curr_video_link].link_devs[i + 1]);
+				if (ret) {
+					printf("probe device is failed, ret %d\n", ret);
+					return NULL;
+				}
+
+				return video_links[curr_video_link].link_devs[i + 1];
+			}
+
+			debug("fail to find next device, already last one\n");
+			return NULL;
+		}
+	}
+
+	return NULL;
+}
+
+struct udevice *video_link_get_video_device(void)
+{
+	int ret;
+
+	if (video_off)
+		return NULL;
+
+	if (curr_video_link >= video_links_num)
+		return NULL;
+
+	if (video_links[curr_video_link].dev_num == 0)
+		return NULL;
+
+	ret = device_probe(video_links[curr_video_link].link_devs[0]);
+	if (ret) {
+		printf("probe video device failed, ret %d\n", ret);
+		return NULL;
+	}
+
+	return video_links[curr_video_link].link_devs[0];
+}
+
+int video_link_get_display_timings(struct display_timing *timings)
+{
+	int i = 0;
+	int ret;
+	struct udevice *dev;
+
+	if (video_off)
+		return -EPERM;
+
+	if (curr_video_link >= video_links_num)
+		return -ENODEV;
+
+	if (video_links[curr_video_link].dev_num == 0)
+		return -ENODEV;
+
+	for (i = video_links[curr_video_link].dev_num - 1; i >= 0 ; i--) {
+		dev = video_links[curr_video_link].link_devs[i];
+		if (device_get_uclass_id(dev) == UCLASS_PANEL) {
+			ret = device_probe(video_links[curr_video_link].link_devs[i]);
+			if (ret) {
+				printf("fail to probe panel device %s\n", dev->name);
+				return ret;
+			}
+
+			ret = panel_get_display_timing(dev, timings);
+			if (ret) {
+				ret = ofnode_decode_display_timing(dev_ofnode(dev), 0, timings);
+				if (ret) {
+					printf("fail to get panel timing %s\n", dev->name);
+					return ret;
+				}
+			}
+
+			return 0;
+		} else if (device_get_uclass_id(dev) == UCLASS_DISPLAY ||
+			   device_get_uclass_id(dev) == UCLASS_VIDEO) {
+			ret = ofnode_decode_display_timing(dev_ofnode(dev), 0, timings);
+			if (!ret)
+				return 0;
+		}
+	}
+
+	return -EINVAL;
+}
+
+static void list_videolink(bool current_only)
+{
+	ulong index = 0;
+	int j;
+	bool match;
+
+	/* dump the link */
+	debug("video link number: %lu\n", video_links_num);
+
+	for (index = 0; index < video_links_num; index++) {
+		match = false;
+		if (curr_video_link == index)
+			match = true;
+		else if (current_only)
+			continue;
+
+		printf("[%c]-Video Link %lu", (match) ? '*' : ' ', index);
+
+		if (match) {
+			struct udevice *video_dev = video_link_get_video_device();
+
+			if (video_dev) {
+				printf(" (%u x %u)", video_get_xsize(video_dev),
+				       video_get_ysize(video_dev));
+			}
+		}
+
+		printf("\n");
+
+		for (j = 0; j < video_links[index].dev_num; j++) {
+			printf("\t[%d] %s, %s\n", j, video_links[index].link_devs[j]->name,
+			       dev_get_uclass_name(video_links[index].link_devs[j]));
+		}
+	}
+}
+
+static int do_videolink(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
+{
+	char cmd = 'l';
+	int ret = 0;
+
+	if (argc > 1)
+		cmd = argv[1][0];
+
+	switch (cmd) {
+	case 'l':		/* list */
+		list_videolink(false);
+		break;
+	default:
+		ret = CMD_RET_USAGE;
+		break;
+	}
+
+	return ret;
+}
+
+int video_link_init(void)
+{
+	struct udevice *dev;
+	ulong env_id;
+	int off;
+
+	memset(&video_links, 0, sizeof(video_links));
+	memset(&temp_stack, 0, sizeof(temp_stack));
+
+	for (uclass_find_first_device(UCLASS_VIDEO, &dev);
+	     dev;
+	     uclass_find_next_device(&dev)) {
+		video_link_add_node(NULL, dev, dev_ofnode(dev));
+	}
+
+	if (video_links_num == 0) {
+		printf("Fail to setup video link\n");
+		return -ENODEV;
+	}
+
+	/* Read the env variable for default video link */
+	off = env_get_yesno("video_off");
+	if (off == 1) {
+		video_off = true;
+		return 0;
+	}
+
+	env_id = env_get_ulong("video_link", 10, 0);
+	if (env_id < video_links_num)
+		curr_video_link = env_id;
+
+	list_videolink(true);
+
+	return 0;
+}
+
+int video_link_shut_down(void)
+{
+	struct udevice *video_dev = video_link_get_video_device();
+
+	if (video_dev)
+		device_remove(video_dev, DM_REMOVE_NORMAL);
+
+	return 0;
+}
+
+#if CONFIG_IS_ENABLED(SYS_LONGHELP)
+static char video_link_help_text[] =
+	"list\n"
+	"    -  show video link info, set video_link variable to select link";
+#endif
+
+U_BOOT_CMD(videolink,	5,	1,	do_videolink,
+	   "list and select video link", video_link_help_text
+);
diff --git a/include/video_link.h b/include/video_link.h
new file mode 100644
index 000000000000..5350bfa9e9d1
--- /dev/null
+++ b/include/video_link.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2020 NXP
+ */
+
+#ifndef __VIDEO_LINK
+#define __VIDEO_LINK
+
+int video_link_init(void);
+
+int video_link_shut_down(void);
+
+struct udevice *video_link_get_next_device(struct udevice *curr_dev);
+
+struct udevice *video_link_get_video_device(void);
+
+int video_link_get_display_timings(struct display_timing *timings);
+
+#endif
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 10/26] video: bridge: Add check_timing interface
  2024-09-13  9:55 [PATCH 00/26] Support display (and even more) on the BSH SMM S2/PRO boards Dario Binacchi
                   ` (8 preceding siblings ...)
  2024-09-13  9:55 ` [PATCH 09/26] video: Add video link framework Dario Binacchi
@ 2024-09-13  9:55 ` Dario Binacchi
  2024-09-13  9:55 ` [PATCH 11/26] video: dsi_host: add disable host interface Dario Binacchi
                   ` (16 subsequent siblings)
  26 siblings, 0 replies; 48+ messages in thread
From: Dario Binacchi @ 2024-09-13  9:55 UTC (permalink / raw)
  To: u-boot
  Cc: Fabio Estevam, linux-amarula, michael, Miquel Raynal, Ye Li,
	Dario Binacchi, Anatolij Gustschin, Peter Robinson, Tom Rini

From: Michael Trimarchi <michael@amarulasolutions.com>

Add new interface check_timing to video bridge uclass. For bridge device
who may update timing needs to implement the callback. So host device can
sync the timing with the bridge.

Signed-off-by: Ye Li <ye.li@nxp.com>
Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---

 drivers/video/bridge/video-bridge-uclass.c | 10 ++++++++++
 include/video_bridge.h                     | 20 ++++++++++++++++++++
 2 files changed, 30 insertions(+)

diff --git a/drivers/video/bridge/video-bridge-uclass.c b/drivers/video/bridge/video-bridge-uclass.c
index 2084a2e03ee8..7432107238cc 100644
--- a/drivers/video/bridge/video-bridge-uclass.c
+++ b/drivers/video/bridge/video-bridge-uclass.c
@@ -48,6 +48,16 @@ int video_bridge_check_attached(struct udevice *dev)
 	return ops->check_attached(dev);
 }
 
+int video_bridge_check_timing(struct udevice *dev, struct display_timing *timing)
+{
+	struct video_bridge_ops *ops = video_bridge_get_ops(dev);
+
+	if (ops->check_timing)
+		return ops->check_timing(dev, timing);
+
+	return 0;
+}
+
 int video_bridge_read_edid(struct udevice *dev, u8 *buf, int buf_size)
 {
 	struct video_bridge_ops *ops = video_bridge_get_ops(dev);
diff --git a/include/video_bridge.h b/include/video_bridge.h
index 3b429eac578a..8b71b04a1119 100644
--- a/include/video_bridge.h
+++ b/include/video_bridge.h
@@ -44,6 +44,17 @@ struct video_bridge_ops {
 	 */
 	int (*check_attached)(struct udevice *dev);
 
+	/**
+	 * check_timing() - check if the timing need update after the bridge device attached
+	 *
+	 * This method is optional - if not provided then return 0
+	 *
+	 * @dev:	Device to check
+	 * @active:	The timing to be checked and updated
+	 * Return: 0 if OK, -ve on error
+	 */
+	int (*check_timing)(struct udevice *dev, struct display_timing *timing);
+
 	/**
 	 * set_backlight() - Set the backlight brightness
 	 *
@@ -98,6 +109,15 @@ int video_bridge_set_active(struct udevice *dev, bool active);
  */
 int video_bridge_check_attached(struct udevice *dev);
 
+/**
+ * check_timing() - check if the timing need update after the bridge device attached
+ *
+ * @dev:	Device to check
+ * @active:	The timing to be checked and updated
+ * Return: 0 if OK, -ve on error
+ */
+int video_bridge_check_timing(struct udevice *dev, struct display_timing *timing);
+
 /**
  * video_bridge_read_edid() - Read information from EDID
  *
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 11/26] video: dsi_host: add disable host interface
  2024-09-13  9:55 [PATCH 00/26] Support display (and even more) on the BSH SMM S2/PRO boards Dario Binacchi
                   ` (9 preceding siblings ...)
  2024-09-13  9:55 ` [PATCH 10/26] video: bridge: Add check_timing interface Dario Binacchi
@ 2024-09-13  9:55 ` Dario Binacchi
  2024-09-13  9:55 ` [PATCH 12/26] video: Update mxsfb video drivers for iMX8MM/iMX8MN display Dario Binacchi
                   ` (15 subsequent siblings)
  26 siblings, 0 replies; 48+ messages in thread
From: Dario Binacchi @ 2024-09-13  9:55 UTC (permalink / raw)
  To: u-boot
  Cc: Fabio Estevam, linux-amarula, michael, Miquel Raynal, Ye Li,
	Dario Binacchi, Anatolij Gustschin, Peter Robinson, Tom Rini

From: Michael Trimarchi <michael@amarulasolutions.com>

Current operations structure has provided disable callback, but
there is no API from dsi_host uclass to use it.

Add this disable host interface, so that dsi bridge can call it
to disable host

Signed-off-by: Ye Li <ye.li@nxp.com>
Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---

 drivers/video/dsi-host-uclass.c | 10 ++++++++++
 include/dsi_host.h              |  8 ++++++++
 2 files changed, 18 insertions(+)

diff --git a/drivers/video/dsi-host-uclass.c b/drivers/video/dsi-host-uclass.c
index fde275ad7e2e..745991f8dd94 100644
--- a/drivers/video/dsi-host-uclass.c
+++ b/drivers/video/dsi-host-uclass.c
@@ -34,6 +34,16 @@ int dsi_host_enable(struct udevice *dev)
 	return ops->enable(dev);
 }
 
+int dsi_host_disable(struct udevice *dev)
+{
+	struct dsi_host_ops *ops = dsi_host_get_ops(dev);
+
+	if (!ops->disable)
+		return -ENOSYS;
+
+	return ops->disable(dev);
+}
+
 UCLASS_DRIVER(dsi_host) = {
 	.id		= UCLASS_DSI_HOST,
 	.name		= "dsi_host",
diff --git a/include/dsi_host.h b/include/dsi_host.h
index 83f8839db68d..5873ab698d9e 100644
--- a/include/dsi_host.h
+++ b/include/dsi_host.h
@@ -70,4 +70,12 @@ int dsi_host_init(struct udevice *dev,
  */
 int dsi_host_enable(struct udevice *dev);
 
+/**
+ * dsi_host_disable
+ *
+ * @dev:	dsi host device
+ * @return 0 if OK, -ve on error
+ */
+int dsi_host_disable(struct udevice *dev);
+
 #endif
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 12/26] video: Update mxsfb video drivers for iMX8MM/iMX8MN display
  2024-09-13  9:55 [PATCH 00/26] Support display (and even more) on the BSH SMM S2/PRO boards Dario Binacchi
                   ` (10 preceding siblings ...)
  2024-09-13  9:55 ` [PATCH 11/26] video: dsi_host: add disable host interface Dario Binacchi
@ 2024-09-13  9:55 ` Dario Binacchi
  2024-09-13  9:55 ` [PATCH 13/26] video: Enable DM_UC_FLAG_SEQ_ALIAS for display and bridge Dario Binacchi
                   ` (14 subsequent siblings)
  26 siblings, 0 replies; 48+ messages in thread
From: Dario Binacchi @ 2024-09-13  9:55 UTC (permalink / raw)
  To: u-boot
  Cc: Fabio Estevam, linux-amarula, michael, Miquel Raynal, Ye Li,
	Dario Binacchi, Anatolij Gustschin, Peter Robinson,
	Sébastien Szymanski, Tom Rini

From: Michael Trimarchi <michael@amarulasolutions.com>

Update mxsfb for LCD video driver

Signed-off-by: Ye Li <ye.li@nxp.com>
Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---

 drivers/video/mxsfb.c | 139 ++++++++++++++++++++++++++++--------------
 1 file changed, 93 insertions(+), 46 deletions(-)

diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c
index 792d6314d15e..45431f0a1047 100644
--- a/drivers/video/mxsfb.c
+++ b/drivers/video/mxsfb.c
@@ -21,8 +21,13 @@
 #include <asm/global_data.h>
 #include <asm/mach-imx/dma.h>
 #include <asm/io.h>
+#include <reset.h>
+#include <panel.h>
+#include <video_bridge.h>
+#include <video_link.h>
 
 #include "videomodes.h"
+#include <dm/device-internal.h>
 
 #define	PS2KHZ(ps)	(1000000000UL / (ps))
 #define HZ2PS(hz)	(1000000000UL / ((hz) / 1000))
@@ -30,6 +35,11 @@
 #define BITS_PP		18
 #define BYTES_PP	4
 
+struct mxsfb_priv {
+	fdt_addr_t reg_base;
+	struct udevice *disp_dev;
+};
+
 struct mxs_dma_desc desc;
 
 /**
@@ -56,9 +66,10 @@ __weak void mxsfb_system_setup(void)
  */
 
 static void mxs_lcd_init(struct udevice *dev, u32 fb_addr,
-			 struct display_timing *timings, int bpp)
+			 struct display_timing *timings, int bpp, bool bridge)
 {
-	struct mxs_lcdif_regs *regs = (struct mxs_lcdif_regs *)MXS_LCDIF_BASE;
+	struct mxsfb_priv *priv = dev_get_priv(dev);
+	struct mxs_lcdif_regs *regs = (struct mxs_lcdif_regs *)priv->reg_base;
 	const enum display_flags flags = timings->flags;
 	uint32_t word_len = 0, bus_width = 0;
 	uint8_t valid_data = 0;
@@ -109,7 +120,7 @@ static void mxs_lcd_init(struct udevice *dev, u32 fb_addr,
 	}
 #else
 	/* Kick in the LCDIF clock */
-	mxs_set_lcdclk(MXS_LCDIF_BASE, timings->pixelclock.typ / 1000);
+	mxs_set_lcdclk(priv->reg_base, timings->pixelclock.typ / 1000);
 #endif
 
 	/* Restart the LCDIF block */
@@ -142,26 +153,30 @@ static void mxs_lcd_init(struct udevice *dev, u32 fb_addr,
 		LCDIF_CTRL_BYPASS_COUNT | LCDIF_CTRL_LCDIF_MASTER,
 		&regs->hw_lcdif_ctrl);
 
-	writel(valid_data << LCDIF_CTRL1_BYTE_PACKING_FORMAT_OFFSET,
+	writel((valid_data << LCDIF_CTRL1_BYTE_PACKING_FORMAT_OFFSET) |
+		LCDIF_CTRL1_RECOVER_ON_UNDERFLOW,
 		&regs->hw_lcdif_ctrl1);
 
+	if (bridge)
+		writel(LCDIF_CTRL2_OUTSTANDING_REQS_REQ_16, &regs->hw_lcdif_ctrl2);
+
 	mxsfb_system_setup();
 
 	writel((timings->vactive.typ << LCDIF_TRANSFER_COUNT_V_COUNT_OFFSET) |
 		timings->hactive.typ, &regs->hw_lcdif_transfer_count);
 
-	vdctrl0 = LCDIF_VDCTRL0_ENABLE_PRESENT | LCDIF_VDCTRL0_ENABLE_POL |
+	vdctrl0 = LCDIF_VDCTRL0_ENABLE_PRESENT |
 		  LCDIF_VDCTRL0_VSYNC_PERIOD_UNIT |
 		  LCDIF_VDCTRL0_VSYNC_PULSE_WIDTH_UNIT |
 		  timings->vsync_len.typ;
 
-	if(flags & DISPLAY_FLAGS_HSYNC_HIGH)
+	if (flags & DISPLAY_FLAGS_HSYNC_HIGH)
 		vdctrl0 |= LCDIF_VDCTRL0_HSYNC_POL;
-	if(flags & DISPLAY_FLAGS_VSYNC_HIGH)
+	if (flags & DISPLAY_FLAGS_VSYNC_HIGH)
 		vdctrl0 |= LCDIF_VDCTRL0_VSYNC_POL;
-	if(flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)
+	if (flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)
 		vdctrl0 |= LCDIF_VDCTRL0_DOTCLK_POL;
-	if(flags & DISPLAY_FLAGS_DE_HIGH)
+	if (flags & DISPLAY_FLAGS_DE_HIGH)
 		vdctrl0 |= LCDIF_VDCTRL0_ENABLE_POL;
 
 	writel(vdctrl0, &regs->hw_lcdif_vdctrl0);
@@ -198,10 +213,10 @@ static void mxs_lcd_init(struct udevice *dev, u32 fb_addr,
 }
 
 static int mxs_probe_common(struct udevice *dev, struct display_timing *timings,
-			    int bpp, u32 fb)
+			    int bpp, u32 fb, bool bridge)
 {
 	/* Start framebuffer */
-	mxs_lcd_init(dev, fb, timings, bpp);
+	mxs_lcd_init(dev, fb, timings, bpp, bridge);
 
 #ifdef CONFIG_VIDEO_MXS_MODE_SYSTEM
 	/*
@@ -212,7 +227,8 @@ static int mxs_probe_common(struct udevice *dev, struct display_timing *timings,
 	 * sets the RUN bit, then waits until it gets cleared and repeats this
 	 * infinitelly. This way, we get smooth continuous updates of the LCD.
 	 */
-	struct mxs_lcdif_regs *regs = (struct mxs_lcdif_regs *)MXS_LCDIF_BASE;
+	struct mxsfb_priv *priv = dev_get_priv(dev);
+	struct mxs_lcdif_regs *regs = (struct mxs_lcdif_regs *)priv->reg_base;
 
 	memset(&desc, 0, sizeof(struct mxs_dma_desc));
 	desc.address = (dma_addr_t)&desc;
@@ -229,9 +245,9 @@ static int mxs_probe_common(struct udevice *dev, struct display_timing *timings,
 	return 0;
 }
 
-static int mxs_remove_common(u32 fb)
+static int mxs_remove_common(phys_addr_t reg_base, u32 fb)
 {
-	struct mxs_lcdif_regs *regs = (struct mxs_lcdif_regs *)MXS_LCDIF_BASE;
+	struct mxs_lcdif_regs *regs = (struct mxs_lcdif_regs *)(reg_base);
 	int timeout = 1000000;
 
 	if (!fb)
@@ -258,6 +274,7 @@ static int mxs_of_get_timings(struct udevice *dev,
 	int ret = 0;
 	u32 display_phandle;
 	ofnode display_node;
+	struct mxsfb_priv *priv = dev_get_priv(dev);
 
 	ret = ofnode_read_u32(dev_ofnode(dev), "display", &display_phandle);
 	if (ret) {
@@ -278,10 +295,19 @@ static int mxs_of_get_timings(struct udevice *dev,
 		return -EINVAL;
 	}
 
-	ret = ofnode_decode_display_timing(display_node, 0, timings);
-	if (ret) {
-		dev_err(dev, "failed to get any display timings\n");
-		return -EINVAL;
+	priv->disp_dev = video_link_get_next_device(dev);
+	if (priv->disp_dev) {
+		ret = video_link_get_display_timings(timings);
+		if (ret) {
+			dev_err(dev, "failed to get any video link display timings\n");
+			return -EINVAL;
+		}
+	} else {
+		ret = ofnode_decode_display_timing(display_node, 0, timings);
+		if (ret) {
+			dev_err(dev, "failed to get any display timings\n");
+			return -EINVAL;
+		}
 	}
 
 	return ret;
@@ -291,20 +317,58 @@ static int mxs_video_probe(struct udevice *dev)
 {
 	struct video_uc_plat *plat = dev_get_uclass_plat(dev);
 	struct video_priv *uc_priv = dev_get_uclass_priv(dev);
+	struct mxsfb_priv *priv = dev_get_priv(dev);
 
 	struct display_timing timings;
 	u32 bpp = 0;
 	u32 fb_start, fb_end;
 	int ret;
+	bool enable_bridge = false;
 
 	debug("%s() plat: base 0x%lx, size 0x%x\n",
 	       __func__, plat->base, plat->size);
 
+	priv->reg_base = dev_read_addr(dev);
+	if (priv->reg_base == FDT_ADDR_T_NONE) {
+		dev_err(dev, "lcdif base address is not found\n");
+		return -EINVAL;
+	}
+
 	ret = mxs_of_get_timings(dev, &timings, &bpp);
 	if (ret)
 		return ret;
 
-	ret = mxs_probe_common(dev, &timings, bpp, plat->base);
+	if (priv->disp_dev) {
+		if (IS_ENABLED(CONFIG_VIDEO_BRIDGE)) {
+			if (device_get_uclass_id(priv->disp_dev) == UCLASS_VIDEO_BRIDGE) {
+				ret = video_bridge_attach(priv->disp_dev);
+				if (ret) {
+					dev_err(dev, "fail to attach bridge\n");
+					return ret;
+				}
+
+				ret = video_bridge_set_backlight(priv->disp_dev, 80);
+				if (ret) {
+					dev_err(dev, "fail to set backlight\n");
+					return ret;
+				}
+
+				enable_bridge = true;
+				video_bridge_check_timing(priv->disp_dev, &timings);
+			}
+		}
+
+		if (device_get_uclass_id(priv->disp_dev) == UCLASS_PANEL) {
+			ret = panel_enable_backlight(priv->disp_dev);
+			if (ret) {
+				dev_err(dev, "panel %s enable backlight error %d\n",
+					priv->disp_dev->name, ret);
+				return ret;
+			}
+		}
+	}
+
+	ret = mxs_probe_common(dev, &timings, bpp, plat->base, enable_bridge);
 	if (ret)
 		return ret;
 
@@ -343,33 +407,9 @@ static int mxs_video_probe(struct udevice *dev)
 static int mxs_video_bind(struct udevice *dev)
 {
 	struct video_uc_plat *plat = dev_get_uclass_plat(dev);
-	struct display_timing timings;
-	u32 bpp = 0;
-	u32 bytes_pp = 0;
-	int ret;
 
-	ret = mxs_of_get_timings(dev, &timings, &bpp);
-	if (ret)
-		return ret;
-
-	switch (bpp) {
-	case 32:
-	case 24:
-	case 18:
-		bytes_pp = 4;
-		break;
-	case 16:
-		bytes_pp = 2;
-		break;
-	case 8:
-		bytes_pp = 1;
-		break;
-	default:
-		dev_err(dev, "invalid bpp specified (bpp = %i)\n", bpp);
-		return -EINVAL;
-	}
-
-	plat->size = timings.hactive.typ * timings.vactive.typ * bytes_pp;
+	/* Max size supported by LCDIF, because in bind, we can't probe panel */
+	plat->size = 1920 * 1080 * 4 * 2;
 
 	return 0;
 }
@@ -377,8 +417,12 @@ static int mxs_video_bind(struct udevice *dev)
 static int mxs_video_remove(struct udevice *dev)
 {
 	struct video_uc_plat *plat = dev_get_uclass_plat(dev);
+	struct mxsfb_priv *priv = dev_get_priv(dev);
+
+	if (priv->disp_dev)
+		device_remove(priv->disp_dev, DM_REMOVE_NORMAL);
 
-	mxs_remove_common(plat->base);
+	mxs_remove_common(priv->reg_base, plat->base);
 
 	return 0;
 }
@@ -389,6 +433,8 @@ static const struct udevice_id mxs_video_ids[] = {
 	{ .compatible = "fsl,imx6sx-lcdif" },
 	{ .compatible = "fsl,imx7ulp-lcdif" },
 	{ .compatible = "fsl,imxrt-lcdif" },
+	{ .compatible = "fsl,imx8mm-lcdif" },
+	{ .compatible = "fsl,imx8mn-lcdif" },
 	{ /* sentinel */ }
 };
 
@@ -400,4 +446,5 @@ U_BOOT_DRIVER(mxs_video) = {
 	.probe	= mxs_video_probe,
 	.remove = mxs_video_remove,
 	.flags	= DM_FLAG_PRE_RELOC | DM_FLAG_OS_PREPARE,
+	.priv_auto   = sizeof(struct mxsfb_priv),
 };
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 13/26] video: Enable DM_UC_FLAG_SEQ_ALIAS for display and bridge
  2024-09-13  9:55 [PATCH 00/26] Support display (and even more) on the BSH SMM S2/PRO boards Dario Binacchi
                   ` (11 preceding siblings ...)
  2024-09-13  9:55 ` [PATCH 12/26] video: Update mxsfb video drivers for iMX8MM/iMX8MN display Dario Binacchi
@ 2024-09-13  9:55 ` Dario Binacchi
  2024-09-13  9:55 ` [PATCH 14/26] phy: dphy: add support to calculate the timing based on hs_clk_rate Dario Binacchi
                   ` (13 subsequent siblings)
  26 siblings, 0 replies; 48+ messages in thread
From: Dario Binacchi @ 2024-09-13  9:55 UTC (permalink / raw)
  To: u-boot
  Cc: Fabio Estevam, linux-amarula, michael, Miquel Raynal, Ye Li,
	Dario Binacchi, Anatolij Gustschin, Peter Robinson, Tom Rini

From: Michael Trimarchi <michael@amarulasolutions.com>

To support multiple display or bridge devices, enable the flag,
so we can assign the req seq via DTB alias

Signed-off-by: Ye Li <ye.li@nxp.com>
Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---

 drivers/video/bridge/video-bridge-uclass.c | 1 +
 drivers/video/display-uclass.c             | 1 +
 2 files changed, 2 insertions(+)

diff --git a/drivers/video/bridge/video-bridge-uclass.c b/drivers/video/bridge/video-bridge-uclass.c
index 7432107238cc..5e2b76851fed 100644
--- a/drivers/video/bridge/video-bridge-uclass.c
+++ b/drivers/video/bridge/video-bridge-uclass.c
@@ -145,6 +145,7 @@ int video_bridge_set_active(struct udevice *dev, bool active)
 UCLASS_DRIVER(video_bridge) = {
 	.id		= UCLASS_VIDEO_BRIDGE,
 	.name		= "video_bridge",
+	.flags		= DM_UC_FLAG_SEQ_ALIAS,
 	.per_device_auto	= sizeof(struct video_bridge_priv),
 	.pre_probe	= video_bridge_pre_probe,
 };
diff --git a/drivers/video/display-uclass.c b/drivers/video/display-uclass.c
index 61a73e1bc2a6..07f05be7dd17 100644
--- a/drivers/video/display-uclass.c
+++ b/drivers/video/display-uclass.c
@@ -80,5 +80,6 @@ bool display_in_use(struct udevice *dev)
 UCLASS_DRIVER(display) = {
 	.id		= UCLASS_DISPLAY,
 	.name		= "display",
+	.flags          = DM_UC_FLAG_SEQ_ALIAS,
 	.per_device_plat_auto	= sizeof(struct display_plat),
 };
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 14/26] phy: dphy: add support to calculate the timing based on hs_clk_rate
  2024-09-13  9:55 [PATCH 00/26] Support display (and even more) on the BSH SMM S2/PRO boards Dario Binacchi
                   ` (12 preceding siblings ...)
  2024-09-13  9:55 ` [PATCH 13/26] video: Enable DM_UC_FLAG_SEQ_ALIAS for display and bridge Dario Binacchi
@ 2024-09-13  9:55 ` Dario Binacchi
  2024-09-13  9:55 ` [PATCH 15/26] phy: dphy: Correct lpx parameter and its derivatives(ta_{get, go, sure}) Dario Binacchi
                   ` (12 subsequent siblings)
  26 siblings, 0 replies; 48+ messages in thread
From: Dario Binacchi @ 2024-09-13  9:55 UTC (permalink / raw)
  To: u-boot
  Cc: Fabio Estevam, linux-amarula, michael, Miquel Raynal,
	Marco Felsch, Vinod Koul, Sakari Ailus, Dario Binacchi,
	Igor Prusov, Joe Hershberger, Liu Ying, Stefan Bosch, Tom Rini

From: Michael Trimarchi <michael@amarulasolutions.com>

Upstream Linux commit 22168675bae7.

For MIPI-CSI sender use-case it is common to specify the allowed
link-frequencies which should be used for the MIPI link and is
half the hs-clock rate.

This commit adds a helper to calculate the D-PHY timing based on the
hs-clock rate so we don't need to calculate the timings within the
driver.

Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
Acked-by: Vinod Koul <vkoul@kernel.org>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---

 drivers/phy/phy-core-mipi-dphy.c | 30 +++++++++++++++++++++++++-----
 include/phy-mipi-dphy.h          |  3 +++
 2 files changed, 28 insertions(+), 5 deletions(-)

diff --git a/drivers/phy/phy-core-mipi-dphy.c b/drivers/phy/phy-core-mipi-dphy.c
index 8fb985a1e682..727c2b040520 100644
--- a/drivers/phy/phy-core-mipi-dphy.c
+++ b/drivers/phy/phy-core-mipi-dphy.c
@@ -13,21 +13,23 @@
 /*
  * Minimum D-PHY timings based on MIPI D-PHY specification. Derived
  * from the valid ranges specified in Section 6.9, Table 14, Page 41
- * of the D-PHY specification (v2.1).
+ * of the D-PHY specification (v1.2).
  */
-int phy_mipi_dphy_get_default_config(unsigned long pixel_clock,
+static int phy_mipi_dphy_calc_config(unsigned long pixel_clock,
 				     unsigned int bpp,
 				     unsigned int lanes,
+				     unsigned long long hs_clk_rate,
 				     struct phy_configure_opts_mipi_dphy *cfg)
 {
-	unsigned long long hs_clk_rate;
 	unsigned long long ui;
 
 	if (!cfg)
 		return -EINVAL;
 
-	hs_clk_rate = pixel_clock * bpp;
-	do_div(hs_clk_rate, lanes);
+	if (!hs_clk_rate) {
+		hs_clk_rate = pixel_clock * bpp;
+		do_div(hs_clk_rate, lanes);
+	}
 
 	ui = ALIGN(PSEC_PER_SEC, hs_clk_rate);
 	do_div(ui, hs_clk_rate);
@@ -74,6 +76,24 @@ int phy_mipi_dphy_get_default_config(unsigned long pixel_clock,
 	return 0;
 }
 
+int phy_mipi_dphy_get_default_config(unsigned long pixel_clock,
+				     unsigned int bpp,
+				     unsigned int lanes,
+				     struct phy_configure_opts_mipi_dphy *cfg)
+{
+	return phy_mipi_dphy_calc_config(pixel_clock, bpp, lanes, 0, cfg);
+}
+
+int phy_mipi_dphy_get_default_config_for_hsclk(unsigned long long hs_clk_rate,
+					       unsigned int lanes,
+					       struct phy_configure_opts_mipi_dphy *cfg)
+{
+	if (!hs_clk_rate)
+		return -EINVAL;
+
+	return phy_mipi_dphy_calc_config(0, 0, lanes, hs_clk_rate, cfg);
+}
+
 /*
  * Validate D-PHY configuration according to MIPI D-PHY specification
  * (v1.2, Section Section 6.9 "Global Operation Timing Parameters").
diff --git a/include/phy-mipi-dphy.h b/include/phy-mipi-dphy.h
index a877ffee845d..1ac128d78dfe 100644
--- a/include/phy-mipi-dphy.h
+++ b/include/phy-mipi-dphy.h
@@ -279,6 +279,9 @@ int phy_mipi_dphy_get_default_config(unsigned long pixel_clock,
 				     unsigned int bpp,
 				     unsigned int lanes,
 				     struct phy_configure_opts_mipi_dphy *cfg);
+int phy_mipi_dphy_get_default_config_for_hsclk(unsigned long long hs_clk_rate,
+					       unsigned int lanes,
+					       struct phy_configure_opts_mipi_dphy *cfg);
 int phy_mipi_dphy_config_validate(struct phy_configure_opts_mipi_dphy *cfg);
 
 #endif /* __PHY_MIPI_DPHY_H_ */
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 15/26] phy: dphy: Correct lpx parameter and its derivatives(ta_{get, go, sure})
  2024-09-13  9:55 [PATCH 00/26] Support display (and even more) on the BSH SMM S2/PRO boards Dario Binacchi
                   ` (13 preceding siblings ...)
  2024-09-13  9:55 ` [PATCH 14/26] phy: dphy: add support to calculate the timing based on hs_clk_rate Dario Binacchi
@ 2024-09-13  9:55 ` Dario Binacchi
  2024-09-13  9:55 ` [PATCH 16/26] phy: dphy: Correct clk_pre parameter Dario Binacchi
                   ` (11 subsequent siblings)
  26 siblings, 0 replies; 48+ messages in thread
From: Dario Binacchi @ 2024-09-13  9:55 UTC (permalink / raw)
  To: u-boot
  Cc: Fabio Estevam, linux-amarula, michael, Miquel Raynal, Liu Ying,
	Vinod Koul, Dario Binacchi, Andrzej Hajda, Igor Prusov,
	Joe Hershberger, Tom Rini

From: Michael Trimarchi <michael@amarulasolutions.com>

Upstream linux commit 3153fa38e38af5.

According to the comment of the function phy_mipi_dphy_get_default_config(),
it uses minimum D-PHY timings based on MIPI D-PHY specification.  They are
derived from the valid ranges specified in Section 6.9, Table 14, Page 41
of the D-PHY specification (v1.2).  The table 14 explicitly mentions that
the minimum T-LPX parameter is 50 nanoseconds and the minimum TA-SURE
parameter is T-LPX nanoseconds.  Likewise, the kernel doc of the 'lpx' and
'ta_sure' members of struct phy_configure_opts_mipi_dphy mentions that
the minimum values are 50000 picoseconds and @lpx picoseconds respectively.
Also, the function phy_mipi_dphy_config_validate() checks if cfg->lpx is
less than 50000 picoseconds and if cfg->ta_sure is less than cfg->lpx,
which hints the same minimum values.

Without this patch, the function phy_mipi_dphy_get_default_config()
wrongly sets cfg->lpx to 60000 picoseconds and cfg->ta_sure to 2 * cfg->lpx.
So, let's correct them to 50000 picoseconds and cfg->lpx respectively.

Note that I've only tested the patch with RM67191 DSI panel on i.MX8mq EVK.
Help is needed to test with other i.MX8mq, Meson and Rockchip platforms,
as I don't have the hardwares.

Signed-off-by: Liu Ying <victor.liu@nxp.com>
Link: https://lore.kernel.org/r/20220216071257.1647703-1-victor.liu@nxp.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---

 drivers/phy/phy-core-mipi-dphy.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/phy/phy-core-mipi-dphy.c b/drivers/phy/phy-core-mipi-dphy.c
index 727c2b040520..79cab9125002 100644
--- a/drivers/phy/phy-core-mipi-dphy.c
+++ b/drivers/phy/phy-core-mipi-dphy.c
@@ -64,10 +64,10 @@ static int phy_mipi_dphy_calc_config(unsigned long pixel_clock,
 	cfg->hs_trail = max(4 * 8 * ui, 60000 + 4 * 4 * ui);
 
 	cfg->init = 100;
-	cfg->lpx = 60000;
+	cfg->lpx = 50000;
 	cfg->ta_get = 5 * cfg->lpx;
 	cfg->ta_go = 4 * cfg->lpx;
-	cfg->ta_sure = 2 * cfg->lpx;
+	cfg->ta_sure = cfg->lpx;
 	cfg->wakeup = 1000;
 
 	cfg->hs_clk_rate = hs_clk_rate;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 16/26] phy: dphy: Correct clk_pre parameter
  2024-09-13  9:55 [PATCH 00/26] Support display (and even more) on the BSH SMM S2/PRO boards Dario Binacchi
                   ` (14 preceding siblings ...)
  2024-09-13  9:55 ` [PATCH 15/26] phy: dphy: Correct lpx parameter and its derivatives(ta_{get, go, sure}) Dario Binacchi
@ 2024-09-13  9:55 ` Dario Binacchi
  2024-09-13  9:55 ` [PATCH 17/26] lib: div64: sync with Linux Dario Binacchi
                   ` (10 subsequent siblings)
  26 siblings, 0 replies; 48+ messages in thread
From: Dario Binacchi @ 2024-09-13  9:55 UTC (permalink / raw)
  To: u-boot
  Cc: Fabio Estevam, linux-amarula, michael, Miquel Raynal, Liu Ying,
	Andrzej Hajda, Neil Armstrong, Guido Günther,
	Laurent Pinchart, Vinod Koul, Dario Binacchi, Igor Prusov,
	Joe Hershberger, Neil Armstrong, Sakari Ailus, Sean Anderson,
	Tom Rini, u-boot-amlogic

From: Michael Trimarchi <michael@amarulasolutions.com>

Upstream linux commit 9a8406ba1a9a29.

The D-PHY specification (v1.2) explicitly mentions that the T-CLK-PRE
parameter's unit is Unit Interval(UI) and the minimum value is 8.  Also,
kernel doc of the 'clk_pre' member of struct phy_configure_opts_mipi_dphy
mentions that it should be in UI.  However, the dphy core driver wrongly
sets 'clk_pre' to 8000, which seems to hint that it's in picoseconds.

So, let's fix the dphy core driver to correctly reflect the T-CLK-PRE
parameter's minimum value according to the D-PHY specification.

I'm assuming that all impacted custom drivers shall program values in
TxByteClkHS cycles into hardware for the T-CLK-PRE parameter.  The D-PHY
specification mentions that the frequency of TxByteClkHS is exactly 1/8
the High-Speed(HS) bit rate(each HS bit consumes one UI).  So, relevant
custom driver code is changed to program those values as
DIV_ROUND_UP(cfg->clk_pre, BITS_PER_BYTE), then.

Note that I've only tested the patch with RM67191 DSI panel on i.MX8mq EVK.
Help is needed to test with other i.MX8mq, Meson and Rockchip platforms,
as I don't have the hardwares.

Tested-by: Liu Ying <victor.liu@nxp.com> # RM67191 DSI panel on i.MX8mq EVK
Reviewed-by: Andrzej Hajda <andrzej.hajda@intel.com>
Reviewed-by: Neil Armstrong <narmstrong@baylibre.com> # for phy-meson-axg-mipi-dphy.c
Tested-by: Neil Armstrong <narmstrong@baylibre.com> # for phy-meson-axg-mipi-dphy.c
Tested-by: Guido Günther <agx@sigxcpu.org> # Librem 5 (imx8mq) with it's rather picky panel
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Liu Ying <victor.liu@nxp.com>
Link: https://lore.kernel.org/r/20220124024007.1465018-1-victor.liu@nxp.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---

 drivers/phy/meson-axg-mipi-dphy.c | 2 +-
 drivers/phy/phy-core-mipi-dphy.c  | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/phy/meson-axg-mipi-dphy.c b/drivers/phy/meson-axg-mipi-dphy.c
index 3f89de19970b..fb10ccca6ac1 100644
--- a/drivers/phy/meson-axg-mipi-dphy.c
+++ b/drivers/phy/meson-axg-mipi-dphy.c
@@ -237,7 +237,7 @@ static int phy_meson_axg_mipi_dphy_power_on(struct phy *phy)
 		     (DIV_ROUND_UP(priv->config.clk_zero, temp) << 16) |
 		     (DIV_ROUND_UP(priv->config.clk_prepare, temp) << 24));
 	regmap_write(priv->regmap, MIPI_DSI_CLK_TIM1,
-		     DIV_ROUND_UP(priv->config.clk_pre, temp));
+		     DIV_ROUND_UP(priv->config.clk_pre, BITS_PER_BYTE));
 
 	regmap_write(priv->regmap, MIPI_DSI_HS_TIM,
 		     DIV_ROUND_UP(priv->config.hs_exit, temp) |
diff --git a/drivers/phy/phy-core-mipi-dphy.c b/drivers/phy/phy-core-mipi-dphy.c
index 79cab9125002..27cff85709d9 100644
--- a/drivers/phy/phy-core-mipi-dphy.c
+++ b/drivers/phy/phy-core-mipi-dphy.c
@@ -36,7 +36,7 @@ static int phy_mipi_dphy_calc_config(unsigned long pixel_clock,
 
 	cfg->clk_miss = 0;
 	cfg->clk_post = 60000 + 52 * ui;
-	cfg->clk_pre = 8000;
+	cfg->clk_pre = 8;
 	cfg->clk_prepare = 38000;
 	cfg->clk_settle = 95000;
 	cfg->clk_term_en = 0;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 17/26] lib: div64: sync with Linux
  2024-09-13  9:55 [PATCH 00/26] Support display (and even more) on the BSH SMM S2/PRO boards Dario Binacchi
                   ` (15 preceding siblings ...)
  2024-09-13  9:55 ` [PATCH 16/26] phy: dphy: Correct clk_pre parameter Dario Binacchi
@ 2024-09-13  9:55 ` Dario Binacchi
  2024-09-13  9:56 ` [PATCH 18/26] video: bridge: Add Samsung DSIM bridge Dario Binacchi
                   ` (9 subsequent siblings)
  26 siblings, 0 replies; 48+ messages in thread
From: Dario Binacchi @ 2024-09-13  9:55 UTC (permalink / raw)
  To: u-boot
  Cc: Fabio Estevam, linux-amarula, michael, Miquel Raynal,
	Dario Binacchi, Tom Rini

From: Michael Trimarchi <michael@amarulasolutions.com>

Sync with Linux commit fc4a0db4149af ("Merge tag '6.5'").

Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---

 include/linux/math64.h | 110 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 110 insertions(+)

diff --git a/include/linux/math64.h b/include/linux/math64.h
index eaa9fd5b9685..82bd7472a32c 100644
--- a/include/linux/math64.h
+++ b/include/linux/math64.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 #ifndef _LINUX_MATH64_H
 #define _LINUX_MATH64_H
 
@@ -12,6 +13,11 @@
 
 /**
  * div_u64_rem - unsigned 64bit divide with 32bit divisor with remainder
+ * @dividend: unsigned 64bit dividend
+ * @divisor: unsigned 32bit divisor
+ * @remainder: pointer to unsigned 32bit remainder
+ *
+ * Return: sets ``*remainder``, then returns dividend / divisor
  *
  * This is commonly provided by 32bit archs to provide an optimized 64bit
  * divide.
@@ -24,6 +30,11 @@ static inline u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder)
 
 /**
  * div_s64_rem - signed 64bit divide with 32bit divisor with remainder
+ * @dividend: signed 64bit dividend
+ * @divisor: signed 32bit divisor
+ * @remainder: pointer to signed 32bit remainder
+ *
+ * Return: sets ``*remainder``, then returns dividend / divisor
  */
 static inline s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder)
 {
@@ -33,6 +44,11 @@ static inline s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder)
 
 /**
  * div64_u64_rem - unsigned 64bit divide with 64bit divisor and remainder
+ * @dividend: unsigned 64bit dividend
+ * @divisor: unsigned 64bit divisor
+ * @remainder: pointer to unsigned 64bit remainder
+ *
+ * Return: sets ``*remainder``, then returns dividend / divisor
  */
 static inline u64 div64_u64_rem(u64 dividend, u64 divisor, u64 *remainder)
 {
@@ -42,6 +58,10 @@ static inline u64 div64_u64_rem(u64 dividend, u64 divisor, u64 *remainder)
 
 /**
  * div64_u64 - unsigned 64bit divide with 64bit divisor
+ * @dividend: unsigned 64bit dividend
+ * @divisor: unsigned 64bit divisor
+ *
+ * Return: dividend / divisor
  */
 static inline u64 div64_u64(u64 dividend, u64 divisor)
 {
@@ -53,6 +73,10 @@ static inline u64 div64_u64(u64 dividend, u64 divisor)
 
 /**
  * div64_s64 - signed 64bit divide with 64bit divisor
+ * @dividend: signed 64bit dividend
+ * @divisor: signed 64bit divisor
+ *
+ * Return: dividend / divisor
  */
 static inline s64 div64_s64(s64 dividend, s64 divisor)
 {
@@ -92,10 +116,14 @@ extern s64 div64_s64(s64 dividend, s64 divisor);
 
 /**
  * div_u64 - unsigned 64bit divide with 32bit divisor
+ * @dividend: unsigned 64bit dividend
+ * @divisor: unsigned 32bit divisor
  *
  * This is the most common 64bit divide and should be used if possible,
  * as many 32bit archs can optimize this variant better than a full 64bit
  * divide.
+ *
+ * Return: dividend / divisor
  */
 #ifndef div_u64
 static inline u64 div_u64(u64 dividend, u32 divisor)
@@ -107,6 +135,10 @@ static inline u64 div_u64(u64 dividend, u32 divisor)
 
 /**
  * div_s64 - signed 64bit divide with 32bit divisor
+ * @dividend: signed 64bit dividend
+ * @divisor: signed 32bit divisor
+ *
+ * Return: dividend / divisor
  */
 #ifndef div_s64
 static inline s64 div_s64(s64 dividend, s32 divisor)
@@ -228,6 +260,24 @@ static inline u64 mul_u64_u64_shr(u64 a, u64 b, unsigned int shift)
 
 #endif
 
+#ifndef mul_s64_u64_shr
+static inline u64 mul_s64_u64_shr(s64 a, u64 b, unsigned int shift)
+{
+	u64 ret;
+
+	/*
+	 * Extract the sign before the multiplication and put it back
+	 * afterwards if needed.
+	 */
+	ret = mul_u64_u64_shr(abs(a), b, shift);
+
+	if (a < 0)
+		ret = -((s64)ret);
+
+	return ret;
+}
+#endif /* mul_s64_u64_shr */
+
 #ifndef mul_u64_u32_div
 static inline u64 mul_u64_u32_div(u64 a, u32 mul, u32 divisor)
 {
@@ -257,4 +307,64 @@ static inline u64 mul_u64_u32_div(u64 a, u32 mul, u32 divisor)
 }
 #endif /* mul_u64_u32_div */
 
+u64 mul_u64_u64_div_u64(u64 a, u64 mul, u64 div);
+
+/**
+ * DIV64_U64_ROUND_UP - unsigned 64bit divide with 64bit divisor rounded up
+ * @ll: unsigned 64bit dividend
+ * @d: unsigned 64bit divisor
+ *
+ * Divide unsigned 64bit dividend by unsigned 64bit divisor
+ * and round up.
+ *
+ * Return: dividend / divisor rounded up
+ */
+#define DIV64_U64_ROUND_UP(ll, d)	\
+	({ u64 _tmp = (d); div64_u64((ll) + _tmp - 1, _tmp); })
+
+/**
+ * DIV64_U64_ROUND_CLOSEST - unsigned 64bit divide with 64bit divisor rounded to nearest integer
+ * @dividend: unsigned 64bit dividend
+ * @divisor: unsigned 64bit divisor
+ *
+ * Divide unsigned 64bit dividend by unsigned 64bit divisor
+ * and round to closest integer.
+ *
+ * Return: dividend / divisor rounded to nearest integer
+ */
+#define DIV64_U64_ROUND_CLOSEST(dividend, divisor)	\
+	({ u64 _tmp = (divisor); div64_u64((dividend) + _tmp / 2, _tmp); })
+
+/**
+ * DIV_U64_ROUND_CLOSEST - unsigned 64bit divide with 32bit divisor rounded to nearest integer
+ * @dividend: unsigned 64bit dividend
+ * @divisor: unsigned 32bit divisor
+ *
+ * Divide unsigned 64bit dividend by unsigned 32bit divisor
+ * and round to closest integer.
+ *
+ * Return: dividend / divisor rounded to nearest integer
+ */
+#define DIV_U64_ROUND_CLOSEST(dividend, divisor)	\
+	({ u32 _tmp = (divisor); div_u64((u64)(dividend) + _tmp / 2, _tmp); })
+
+/**
+ * DIV_S64_ROUND_CLOSEST - signed 64bit divide with 32bit divisor rounded to nearest integer
+ * @dividend: signed 64bit dividend
+ * @divisor: signed 32bit divisor
+ *
+ * Divide signed 64bit dividend by signed 32bit divisor
+ * and round to closest integer.
+ *
+ * Return: dividend / divisor rounded to nearest integer
+ */
+#define DIV_S64_ROUND_CLOSEST(dividend, divisor)(	\
+{							\
+	s64 __x = (dividend);				\
+	s32 __d = (divisor);				\
+	((__x > 0) == (__d > 0)) ?			\
+		div_s64((__x + (__d / 2)), __d) :	\
+		div_s64((__x - (__d / 2)), __d);	\
+}							\
+)
 #endif /* _LINUX_MATH64_H */
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 18/26] video: bridge: Add Samsung DSIM bridge
  2024-09-13  9:55 [PATCH 00/26] Support display (and even more) on the BSH SMM S2/PRO boards Dario Binacchi
                   ` (16 preceding siblings ...)
  2024-09-13  9:55 ` [PATCH 17/26] lib: div64: sync with Linux Dario Binacchi
@ 2024-09-13  9:56 ` Dario Binacchi
  2024-09-13  9:56 ` [PATCH 19/26] video: Add Synaptics R63353 panel driver Dario Binacchi
                   ` (8 subsequent siblings)
  26 siblings, 0 replies; 48+ messages in thread
From: Dario Binacchi @ 2024-09-13  9:56 UTC (permalink / raw)
  To: u-boot
  Cc: Fabio Estevam, linux-amarula, michael, Miquel Raynal,
	Dario Binacchi, Anatolij Gustschin, Jonas Schwöbel,
	Svyatoslav Ryhel, Tom Rini

From: Michael Trimarchi <michael@amarulasolutions.com>

Samsung MIPI DSIM controller is common DSI IP that can be used in various
SoCs like Exynos, i.MX8M Mini/Nano.

In order to access this DSI controller between various platform SoCs,
the ideal way to incorporate this in the as a bridge that can support
all different platform.

Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---

 drivers/video/bridge/Kconfig            |   13 +
 drivers/video/bridge/Makefile           |    1 +
 drivers/video/bridge/samsung-dsi-host.c | 1567 +++++++++++++++++++++++
 drivers/video/bridge/samsung-dsim.c     |  148 +++
 drivers/video/bridge/samsung-dsim.h     |   20 +
 5 files changed, 1749 insertions(+)
 create mode 100644 drivers/video/bridge/samsung-dsi-host.c
 create mode 100644 drivers/video/bridge/samsung-dsim.c
 create mode 100644 drivers/video/bridge/samsung-dsim.h

diff --git a/drivers/video/bridge/Kconfig b/drivers/video/bridge/Kconfig
index ab9172737201..5cb1e7af9935 100644
--- a/drivers/video/bridge/Kconfig
+++ b/drivers/video/bridge/Kconfig
@@ -44,6 +44,19 @@ config VIDEO_BRIDGE_ANALOGIX_ANX6345
 	 The Analogix ANX6345 is RGB-to-DP converter. It enables an eDP LCD
 	 panel to be connected to an parallel LCD interface.
 
+config VIDEO_BRIDGE_SAMSUNG_DSIM
+	bool "Enable IMX SEC DSI video support"
+	select MIPI_DPHY_HELPERS
+	select VIDEO_BRIDGE
+	select VIDEO_LINK
+	select VIDEO_MIPI_DSI
+	help
+	  Enables the common driver code for the Samsung
+	  MIPI DSI block found in SoCs from various vendors.
+	  As this does not provide any functionality by itself (but
+	  rather requires a SoC-specific glue driver to call it), it
+	  can not be enabled from the configuration menu.
+
 config VIDEO_BRIDGE_SOLOMON_SSD2825
 	bool "Solomon SSD2825 bridge driver"
 	depends on PANEL && DM_GPIO
diff --git a/drivers/video/bridge/Makefile b/drivers/video/bridge/Makefile
index 58697e3cbe90..8f49013299ae 100644
--- a/drivers/video/bridge/Makefile
+++ b/drivers/video/bridge/Makefile
@@ -8,5 +8,6 @@ obj-$(CONFIG_VIDEO_BRIDGE_PARADE_DP501) += dp501.o
 obj-$(CONFIG_VIDEO_BRIDGE_PARADE_PS862X) += ps862x.o
 obj-$(CONFIG_VIDEO_BRIDGE_NXP_PTN3460) += ptn3460.o
 obj-$(CONFIG_VIDEO_BRIDGE_ANALOGIX_ANX6345) += anx6345.o
+obj-$(CONFIG_VIDEO_BRIDGE_SAMSUNG_DSIM) += samsung-dsim.o samsung-dsi-host.o
 obj-$(CONFIG_VIDEO_BRIDGE_SOLOMON_SSD2825) += ssd2825.o
 obj-$(CONFIG_VIDEO_BRIDGE_TOSHIBA_TC358768) += tc358768.o
diff --git a/drivers/video/bridge/samsung-dsi-host.c b/drivers/video/bridge/samsung-dsi-host.c
new file mode 100644
index 000000000000..dd3e33c4edc7
--- /dev/null
+++ b/drivers/video/bridge/samsung-dsi-host.c
@@ -0,0 +1,1567 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2024 Amarula Solutions
+ * Copyright 2018 NXP
+ *
+ */
+
+#define LOG_CATEGORY UCLASS_DSI_HOST
+
+#include <dm.h>
+#include <clk.h>
+#include <dm/device_compat.h>
+#include <asm/io.h>
+#include <log.h>
+#include <phy-mipi-dphy.h>
+#include <linux/err.h>
+#include <linux/bug.h>
+#include <linux/delay.h>
+#include <linux/log2.h>
+#include <linux/math64.h>
+#include <asm/unaligned.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/sys_proto.h>
+#include <div64.h>
+#include <video_bridge.h>
+#include <panel.h>
+#include <dsi_host.h>
+#include <asm/arch/gpio.h>
+#include <dm/device-internal.h>
+#include "samsung-dsim.h"
+
+#define MIPI_FIFO_TIMEOUT		250000 /* 250ms */
+
+#define DRIVER_NAME "samsung_dsi"
+
+/* reg bit manipulation */
+#define REG_MASK(e, s) (((1 << ((e) - (s) + 1)) - 1) << (s))
+#define REG_PUT(x, e, s) (((x) << (s)) & REG_MASK(e, s))
+#define REG_GET(x, e, s) (((x) & REG_MASK(e, s)) >> (s))
+
+#define RGB_STATUS_CMDMODE_INSEL	BIT(31)
+#define RGB_STATUS_GET_RGBSTATE(x)	REG_GET(x, 12,  0)
+
+#define CLKCTRL_DPHY_SEL_1P5G		(0x0 << 29)
+#define CLKCTRL_PLLBYPASS		BIT(29)
+#define CLKCTRL_BYTECLKSRC_DPHY_PLL	REG_PUT(0, 26, 25)
+#define CLKCTRL_SET_LANEESCCLKEN(x)	REG_PUT(x, 23, 19)
+#define CLKCTRL_SET_ESCPRESCALER(x)	REG_PUT(x, 15,  0)
+
+#define ESCMODE_SET_STOPSTATE_CNT(X)	REG_PUT(x, 31, 21)
+#define ESCMODE_FORCESTOPSTATE		BIT(20)
+#define ESCMODE_FORCEBTA		BIT(16)
+#define ESCMODE_CMDLPDT			BIT(7)
+#define ESCMODE_TXLPDT			BIT(6)
+#define ESCMODE_TXTRIGGERRST		BIT(5)
+
+#define MVPORCH_SET_CMDALLOW(x)		REG_PUT(x, 31, 28)
+#define MVPORCH_SET_STABLEVFP(x)	REG_PUT(x, 26, 16)
+#define MVPORCH_SET_MAINVBP(x)		REG_PUT(x, 10,  0)
+
+#define MHPORCH_SET_MAINHFP(x)		REG_PUT(x, 31, 16)
+#define MHPORCH_SET_MAINHBP(x)		REG_PUT(x, 15,  0)
+
+#define MSYNC_SET_MAINVSA(x)		REG_PUT(x, 31, 22)
+#define MSYNC_SET_MAINHSA(x)		REG_PUT(x, 15,  0)
+
+#define INTSRC_PLLSTABLE		BIT(31)
+#define INTSRC_SWRSTRELEASE		BIT(30)
+#define INTSRC_SFRPLFIFOEMPTY		BIT(29)
+#define INTSRC_SFRPHFIFOEMPTY		BIT(28)
+#define INTSRC_FRAMEDONE		BIT(24)
+#define INTSRC_LPDRTOUT			BIT(21)
+#define INTSRC_TATOUT			BIT(20)
+#define INTSRC_RXDATDONE		BIT(18)
+#define INTSRC_MASK			(INTSRC_PLLSTABLE	|	\
+					 INTSRC_SWRSTRELEASE	|	\
+					 INTSRC_SFRPLFIFOEMPTY	|	\
+					 INTSRC_SFRPHFIFOEMPTY	|	\
+					 INTSRC_FRAMEDONE	|	\
+					 INTSRC_LPDRTOUT	|	\
+					 INTSRC_TATOUT		|	\
+					 INTSRC_RXDATDONE)
+
+#define INTMSK_MSKPLLSTABLE		BIT(31)
+#define INTMSK_MSKSWRELEASE		BIT(30)
+#define INTMSK_MSKSFRPLFIFOEMPTY	BIT(29)
+#define INTMSK_MSKSFRPHFIFOEMPTY	BIT(28)
+#define INTMSK_MSKFRAMEDONE		BIT(24)
+#define INTMSK_MSKLPDRTOUT		BIT(21)
+#define INTMSK_MSKTATOUT		BIT(20)
+#define INTMSK_MSKRXDATDONE		BIT(18)
+
+#define PKTHDR_SET_DATA1(x)		REG_PUT(x, 23, 16)
+#define PKTHDR_GET_DATA1(x)		REG_GET(x, 23, 16)
+#define PKTHDR_SET_DATA0(x)		REG_PUT(x, 15,  8)
+#define PKTHDR_GET_DATA0(x)		REG_GET(x, 15,  8)
+#define PKTHDR_GET_WC(x)		REG_GET(x, 23,  8)
+#define PKTHDR_SET_DI(x)		REG_PUT(x,  7,  0)
+#define PKTHDR_GET_DI(x)		REG_GET(x,  7,  0)
+#define PKTHDR_SET_DT(x)		REG_PUT(x,  5,  0)
+#define PKTHDR_GET_DT(x)		REG_GET(x,  5,  0)
+#define PKTHDR_SET_VC(x)		REG_PUT(x,  7,  6)
+#define PKTHDR_GET_VC(x)		REG_GET(x,  7,  6)
+
+#define FIFOCTRL_FULLRX			BIT(25)
+#define FIFOCTRL_EMPTYRX		BIT(24)
+#define FIFOCTRL_FULLHSFR		BIT(23)
+#define FIFOCTRL_EMPTYHSFR		BIT(22)
+#define FIFOCTRL_FULLLSFR		BIT(21)
+#define FIFOCTRL_EMPTYLSFR		BIT(20)
+#define FIFOCTRL_FULLHMAIN		BIT(11)
+#define FIFOCTRL_EMPTYHMAIN		BIT(10)
+#define FIFOCTRL_FULLLMAIN		BIT(9)
+#define FIFOCTRL_EMPTYLMAIN		BIT(8)
+#define FIFOCTRL_NINITRX		BIT(4)
+#define FIFOCTRL_NINITSFR		BIT(3)
+#define FIFOCTRL_NINITI80		BIT(2)
+#define FIFOCTRL_NINITSUB		BIT(1)
+#define FIFOCTRL_NINITMAIN		BIT(0)
+
+#define PLLCTRL_DPDNSWAP_CLK		BIT(25)
+#define PLLCTRL_DPDNSWAP_DAT		BIT(24)
+#define PLLCTRL_PLLEN			BIT(23)
+#define PLLCTRL_SET_PMS(x)		REG_PUT(x, 19,  1)
+#define PLLCTRL_SET_P(x)		REG_PUT(x, 18, 13)
+#define PLLCTRL_SET_M(x)		REG_PUT(x, 12,  3)
+#define PLLCTRL_SET_S(x)		REG_PUT(x,  2,  0)
+
+#define MAX_MAIN_HRESOL		2047
+#define MAX_MAIN_VRESOL		2047
+#define MAX_SUB_HRESOL		1024
+#define MAX_SUB_VRESOL		1024
+
+/* in KHZ */
+#define MAX_ESC_CLK_FREQ	20000
+
+/* dsim all irqs index */
+#define PLLSTABLE		1
+#define SWRSTRELEASE		2
+#define SFRPLFIFOEMPTY		3
+#define SFRPHFIFOEMPTY		4
+#define SYNCOVERRIDE		5
+#define BUSTURNOVER		6
+#define FRAMEDONE		7
+#define LPDRTOUT		8
+#define TATOUT			9
+#define RXDATDONE		10
+#define RXTE			11
+#define RXACK			12
+#define ERRRXECC		13
+#define ERRRXCRC		14
+#define ERRESC3			15
+#define ERRESC2			16
+#define ERRESC1			17
+#define ERRESC0			18
+#define ERRSYNC3		19
+#define ERRSYNC2		20
+#define ERRSYNC1		21
+#define ERRSYNC0		22
+#define ERRCONTROL3		23
+#define ERRCONTROL2		24
+#define ERRCONTROL1		25
+#define ERRCONTROL0		26
+
+#define PS_TO_CYCLE(ps, hz) DIV64_U64_ROUND_CLOSEST(((ps) * (hz)), 1000000000000ULL)
+
+#define MIPI_HFP_PKT_OVERHEAD	6
+#define MIPI_HBP_PKT_OVERHEAD	6
+#define MIPI_HSA_PKT_OVERHEAD	6
+
+/* DSIM_STATUS */
+#define DSIM_STOP_STATE_DAT(x)		(((x) & 0xf) << 0)
+#define DSIM_STOP_STATE_CLK		BIT(8)
+#define DSIM_TX_READY_HS_CLK		BIT(10)
+#define DSIM_PLL_STABLE			BIT(31)
+
+/* DSIM_SWRST */
+#define DSIM_FUNCRST			BIT(16)
+#define DSIM_SWRST			BIT(0)
+
+/* DSIM_TIMEOUT */
+#define DSIM_LPDR_TIMEOUT(x)		((x) << 0)
+#define DSIM_BTA_TIMEOUT(x)		((x) << 16)
+
+/* DSIM_CLKCTRL */
+#define DSIM_ESC_PRESCALER(x)		(((x) & 0xffff) << 0)
+#define DSIM_ESC_PRESCALER_MASK		(0xffff << 0)
+#define DSIM_LANE_ESC_CLK_EN_CLK	BIT(19)
+#define DSIM_LANE_ESC_CLK_EN_DATA(x)	(((x) & 0xf) << 20)
+#define DSIM_LANE_ESC_CLK_EN_DATA_MASK	(0xf << 20)
+#define DSIM_BYTE_CLKEN			BIT(24)
+#define DSIM_BYTE_CLK_SRC(x)		(((x) & 0x3) << 25)
+#define DSIM_BYTE_CLK_SRC_MASK		(0x3 << 25)
+#define DSIM_PLL_BYPASS			BIT(27)
+#define DSIM_ESC_CLKEN			BIT(28)
+#define DSIM_TX_REQUEST_HSCLK		BIT(31)
+
+/* DSIM_CONFIG */
+#define DSIM_LANE_EN_CLK		BIT(0)
+#define DSIM_LANE_EN(x)			(((x) & 0xf) << 1)
+#define DSIM_NUM_OF_DATA_LANE(x)	(((x) & 0x3) << 5)
+#define DSIM_SUB_PIX_FORMAT(x)		(((x) & 0x7) << 8)
+#define DSIM_MAIN_PIX_FORMAT_MASK	(0x7 << 12)
+#define DSIM_MAIN_PIX_FORMAT_RGB888	(0x7 << 12)
+#define DSIM_MAIN_PIX_FORMAT_RGB666	(0x6 << 12)
+#define DSIM_MAIN_PIX_FORMAT_RGB666_P	(0x5 << 12)
+#define DSIM_MAIN_PIX_FORMAT_RGB565	(0x4 << 12)
+#define DSIM_SUB_VC(x)			(((x) & 0x3) << 16)
+#define DSIM_MAIN_VC(x)			(((x) & 0x3) << 18)
+#define DSIM_HSA_DISABLE_MODE		BIT(20)
+#define DSIM_HBP_DISABLE_MODE		BIT(21)
+#define DSIM_HFP_DISABLE_MODE		BIT(22)
+/*
+ * The i.MX 8M Mini Applications Processor Reference Manual,
+ * Rev. 3, 11/2020 Page 4091
+ * The i.MX 8M Nano Applications Processor Reference Manual,
+ * Rev. 2, 07/2022 Page 3058
+ * The i.MX 8M Plus Applications Processor Reference Manual,
+ * Rev. 1, 06/2021 Page 5436
+ * all claims this bit is 'HseDisableMode' with the definition
+ * 0 = Disables transfer
+ * 1 = Enables transfer
+ *
+ * This clearly states that HSE is not a disabled bit.
+ *
+ * The naming convention follows as per the manual and the
+ * driver logic is based on the MIPI_DSI_MODE_VIDEO_HSE flag.
+ */
+#define DSIM_HSE_DISABLE_MODE		BIT(23)
+#define DSIM_AUTO_MODE			BIT(24)
+#define DSIM_VIDEO_MODE			BIT(25)
+#define DSIM_BURST_MODE			BIT(26)
+#define DSIM_SYNC_INFORM		BIT(27)
+#define DSIM_EOT_DISABLE		BIT(28)
+#define DSIM_MFLUSH_VS			BIT(29)
+/* This flag is valid only for exynos3250/3472/5260/5430 */
+#define DSIM_CLKLANE_STOP		BIT(30)
+#define DSIM_NON_CONTINUOUS_CLKLANE	BIT(31)
+
+/* DSIM_ESCMODE */
+#define DSIM_TX_TRIGGER_RST		BIT(4)
+#define DSIM_TX_LPDT_LP			BIT(6)
+#define DSIM_CMD_LPDT_LP		BIT(7)
+#define DSIM_FORCE_BTA			BIT(16)
+#define DSIM_FORCE_STOP_STATE		BIT(20)
+#define DSIM_STOP_STATE_CNT(x)		(((x) & 0x7ff) << 21)
+#define DSIM_STOP_STATE_CNT_MASK	(0x7ff << 21)
+
+/* DSIM_MDRESOL */
+#define DSIM_MAIN_STAND_BY		BIT(31)
+#define DSIM_MAIN_VRESOL(x, num_bits)	(((x) & ((1 << (num_bits)) - 1)) << 16)
+#define DSIM_MAIN_HRESOL(x, num_bits)	(((x) & ((1 << (num_bits)) - 1)) << 0)
+
+/* DSIM_MVPORCH */
+#define DSIM_CMD_ALLOW(x)		((x) << 28)
+#define DSIM_STABLE_VFP(x)		((x) << 16)
+#define DSIM_MAIN_VBP(x)		((x) << 0)
+#define DSIM_CMD_ALLOW_MASK		(0xf << 28)
+#define DSIM_STABLE_VFP_MASK		(0x7ff << 16)
+#define DSIM_MAIN_VBP_MASK		(0x7ff << 0)
+
+/* DSIM_MHPORCH */
+#define DSIM_MAIN_HFP(x)		((x) << 16)
+#define DSIM_MAIN_HBP(x)		((x) << 0)
+#define DSIM_MAIN_HFP_MASK		((0xffff) << 16)
+#define DSIM_MAIN_HBP_MASK		((0xffff) << 0)
+
+/* DSIM_MSYNC */
+#define DSIM_MAIN_VSA(x)		((x) << 22)
+#define DSIM_MAIN_HSA(x)		((x) << 0)
+#define DSIM_MAIN_VSA_MASK		((0x3ff) << 22)
+#define DSIM_MAIN_HSA_MASK		((0xffff) << 0)
+
+/* DSIM_SDRESOL */
+#define DSIM_SUB_STANDY(x)		((x) << 31)
+#define DSIM_SUB_VRESOL(x)		((x) << 16)
+#define DSIM_SUB_HRESOL(x)		((x) << 0)
+#define DSIM_SUB_STANDY_MASK		((0x1) << 31)
+#define DSIM_SUB_VRESOL_MASK		((0x7ff) << 16)
+#define DSIM_SUB_HRESOL_MASK		((0x7ff) << 0)
+
+/* DSIM_INTSRC */
+#define DSIM_INT_PLL_STABLE		BIT(31)
+#define DSIM_INT_SW_RST_RELEASE		BIT(30)
+#define DSIM_INT_SFR_FIFO_EMPTY		BIT(29)
+#define DSIM_INT_SFR_HDR_FIFO_EMPTY	BIT(28)
+#define DSIM_INT_BTA			BIT(25)
+#define DSIM_INT_FRAME_DONE		BIT(24)
+#define DSIM_INT_RX_TIMEOUT		BIT(21)
+#define DSIM_INT_BTA_TIMEOUT		BIT(20)
+#define DSIM_INT_RX_DONE		BIT(18)
+#define DSIM_INT_RX_TE			BIT(17)
+#define DSIM_INT_RX_ACK			BIT(16)
+#define DSIM_INT_RX_ECC_ERR		BIT(15)
+#define DSIM_INT_RX_CRC_ERR		BIT(14)
+
+/* DSIM_FIFOCTRL */
+#define DSIM_RX_DATA_FULL		BIT(25)
+#define DSIM_RX_DATA_EMPTY		BIT(24)
+#define DSIM_SFR_HEADER_FULL		BIT(23)
+#define DSIM_SFR_HEADER_EMPTY		BIT(22)
+#define DSIM_SFR_PAYLOAD_FULL		BIT(21)
+#define DSIM_SFR_PAYLOAD_EMPTY		BIT(20)
+#define DSIM_I80_HEADER_FULL		BIT(19)
+#define DSIM_I80_HEADER_EMPTY		BIT(18)
+#define DSIM_I80_PAYLOAD_FULL		BIT(17)
+#define DSIM_I80_PAYLOAD_EMPTY		BIT(16)
+#define DSIM_SD_HEADER_FULL		BIT(15)
+#define DSIM_SD_HEADER_EMPTY		BIT(14)
+#define DSIM_SD_PAYLOAD_FULL		BIT(13)
+#define DSIM_SD_PAYLOAD_EMPTY		BIT(12)
+#define DSIM_MD_HEADER_FULL		BIT(11)
+#define DSIM_MD_HEADER_EMPTY		BIT(10)
+#define DSIM_MD_PAYLOAD_FULL		BIT(9)
+#define DSIM_MD_PAYLOAD_EMPTY		BIT(8)
+#define DSIM_RX_FIFO			BIT(4)
+#define DSIM_SFR_FIFO			BIT(3)
+#define DSIM_I80_FIFO			BIT(2)
+#define DSIM_SD_FIFO			BIT(1)
+#define DSIM_MD_FIFO			BIT(0)
+
+/* DSIM_PHYACCHR */
+#define DSIM_AFC_EN			BIT(14)
+#define DSIM_AFC_CTL(x)			(((x) & 0x7) << 5)
+
+/* DSIM_PLLCTRL */
+#define DSIM_FREQ_BAND(x)		((x) << 24)
+#define DSIM_PLL_EN			BIT(23)
+#define DSIM_PLL_P(x, offset)		((x) << (offset))
+#define DSIM_PLL_M(x)			((x) << 4)
+#define DSIM_PLL_S(x)			((x) << 1)
+
+/* DSIM_PHYCTRL */
+#define DSIM_PHYCTRL_ULPS_EXIT(x)	(((x) & 0x1ff) << 0)
+#define DSIM_PHYCTRL_B_DPHYCTL_VREG_LP	BIT(30)
+#define DSIM_PHYCTRL_B_DPHYCTL_SLEW_UP	BIT(14)
+
+/* DSIM_PHYTIMING */
+#define DSIM_PHYTIMING_LPX(x)		((x) << 8)
+#define DSIM_PHYTIMING_HS_EXIT(x)	((x) << 0)
+
+/* DSIM_PHYTIMING1 */
+#define DSIM_PHYTIMING1_CLK_PREPARE(x)	((x) << 24)
+#define DSIM_PHYTIMING1_CLK_ZERO(x)	((x) << 16)
+#define DSIM_PHYTIMING1_CLK_POST(x)	((x) << 8)
+#define DSIM_PHYTIMING1_CLK_TRAIL(x)	((x) << 0)
+
+/* DSIM_PHYTIMING2 */
+#define DSIM_PHYTIMING2_HS_PREPARE(x)	((x) << 16)
+#define DSIM_PHYTIMING2_HS_ZERO(x)	((x) << 8)
+#define DSIM_PHYTIMING2_HS_TRAIL(x)	((x) << 0)
+
+#define DSI_MAX_BUS_WIDTH		4
+#define DSI_NUM_VIRTUAL_CHANNELS	4
+#define DSI_TX_FIFO_SIZE		2048
+#define DSI_RX_FIFO_SIZE		256
+#define DSI_XFER_TIMEOUT_MS		100
+#define DSI_RX_FIFO_EMPTY		0x30800002
+
+struct samsung_dsim_driver_data {
+	const unsigned int *reg_ofs;
+	unsigned int plltmr_reg;
+	unsigned int has_freqband:1;
+	unsigned int has_clklane_stop:1;
+	unsigned int has_broken_fifoctrl_emptyhdr:1;
+	unsigned int num_clks;
+	unsigned int min_freq;
+	unsigned int max_freq;
+	unsigned int wait_for_reset;
+	unsigned int num_bits_resol;
+	unsigned int pll_p_offset;
+	const unsigned int *reg_values;
+	unsigned int pll_fin_min;
+	unsigned int pll_fin_max;
+	u16 m_min;
+	u16 m_max;
+};
+
+enum reg_idx {
+	DSIM_STATUS_REG,	/* Status register */
+	DSIM_RGB_STATUS_REG,	/* RGB status register */
+	DSIM_SWRST_REG,		/* Software reset register */
+	DSIM_CLKCTRL_REG,	/* Clock control register */
+	DSIM_TIMEOUT_REG,	/* Time out register */
+	DSIM_CONFIG_REG,	/* Configuration register */
+	DSIM_ESCMODE_REG,	/* Escape mode register */
+	DSIM_MDRESOL_REG,
+	DSIM_MVPORCH_REG,	/* Main display Vporch register */
+	DSIM_MHPORCH_REG,	/* Main display Hporch register */
+	DSIM_MSYNC_REG,		/* Main display sync area register */
+	DSIM_INTSRC_REG,	/* Interrupt source register */
+	DSIM_INTMSK_REG,	/* Interrupt mask register */
+	DSIM_PKTHDR_REG,	/* Packet Header FIFO register */
+	DSIM_PAYLOAD_REG,	/* Payload FIFO register */
+	DSIM_RXFIFO_REG,	/* Read FIFO register */
+	DSIM_FIFOCTRL_REG,	/* FIFO status and control register */
+	DSIM_PLLCTRL_REG,	/* PLL control register */
+	DSIM_PHYCTRL_REG,
+	DSIM_PHYTIMING_REG,
+	DSIM_PHYTIMING1_REG,
+	DSIM_PHYTIMING2_REG,
+	NUM_REGS
+};
+
+static const unsigned int exynos_reg_ofs[] = {
+	[DSIM_STATUS_REG] =  0x00,
+	[DSIM_SWRST_REG] =  0x04,
+	[DSIM_CLKCTRL_REG] =  0x08,
+	[DSIM_TIMEOUT_REG] =  0x0c,
+	[DSIM_CONFIG_REG] =  0x10,
+	[DSIM_ESCMODE_REG] =  0x14,
+	[DSIM_MDRESOL_REG] =  0x18,
+	[DSIM_MVPORCH_REG] =  0x1c,
+	[DSIM_MHPORCH_REG] =  0x20,
+	[DSIM_MSYNC_REG] =  0x24,
+	[DSIM_INTSRC_REG] =  0x2c,
+	[DSIM_INTMSK_REG] =  0x30,
+	[DSIM_PKTHDR_REG] =  0x34,
+	[DSIM_PAYLOAD_REG] =  0x38,
+	[DSIM_RXFIFO_REG] =  0x3c,
+	[DSIM_FIFOCTRL_REG] =  0x44,
+	[DSIM_PLLCTRL_REG] =  0x4c,
+	[DSIM_PHYCTRL_REG] =  0x5c,
+	[DSIM_PHYTIMING_REG] =  0x64,
+	[DSIM_PHYTIMING1_REG] =  0x68,
+	[DSIM_PHYTIMING2_REG] =  0x6c,
+};
+
+static const unsigned int exynos5433_reg_ofs[] = {
+	[DSIM_STATUS_REG] = 0x04,
+	[DSIM_RGB_STATUS_REG] = 0x08,
+	[DSIM_SWRST_REG] = 0x0C,
+	[DSIM_CLKCTRL_REG] = 0x10,
+	[DSIM_TIMEOUT_REG] = 0x14,
+	[DSIM_CONFIG_REG] = 0x18,
+	[DSIM_ESCMODE_REG] = 0x1C,
+	[DSIM_MDRESOL_REG] = 0x20,
+	[DSIM_MVPORCH_REG] = 0x24,
+	[DSIM_MHPORCH_REG] = 0x28,
+	[DSIM_MSYNC_REG] = 0x2C,
+	[DSIM_INTSRC_REG] = 0x34,
+	[DSIM_INTMSK_REG] = 0x38,
+	[DSIM_PKTHDR_REG] = 0x3C,
+	[DSIM_PAYLOAD_REG] = 0x40,
+	[DSIM_RXFIFO_REG] = 0x44,
+	[DSIM_FIFOCTRL_REG] = 0x4C,
+	[DSIM_PLLCTRL_REG] = 0x94,
+	[DSIM_PHYCTRL_REG] = 0xA4,
+	[DSIM_PHYTIMING_REG] = 0xB4,
+	[DSIM_PHYTIMING1_REG] = 0xB8,
+	[DSIM_PHYTIMING2_REG] = 0xBC,
+};
+
+enum reg_value_idx {
+	RESET_TYPE,
+	PLL_TIMER,
+	STOP_STATE_CNT,
+	PHYCTRL_ULPS_EXIT,
+	PHYCTRL_VREG_LP,
+	PHYCTRL_SLEW_UP,
+	PHYTIMING_LPX,
+	PHYTIMING_HS_EXIT,
+	PHYTIMING_CLK_PREPARE,
+	PHYTIMING_CLK_ZERO,
+	PHYTIMING_CLK_POST,
+	PHYTIMING_CLK_TRAIL,
+	PHYTIMING_HS_PREPARE,
+	PHYTIMING_HS_ZERO,
+	PHYTIMING_HS_TRAIL
+};
+
+static const unsigned int reg_values[] = {
+	[RESET_TYPE] = DSIM_SWRST,
+	[PLL_TIMER] = 500,
+	[STOP_STATE_CNT] = 0xf,
+	[PHYCTRL_ULPS_EXIT] = DSIM_PHYCTRL_ULPS_EXIT(0x0af),
+	[PHYCTRL_VREG_LP] = 0,
+	[PHYCTRL_SLEW_UP] = 0,
+	[PHYTIMING_LPX] = DSIM_PHYTIMING_LPX(0x06),
+	[PHYTIMING_HS_EXIT] = DSIM_PHYTIMING_HS_EXIT(0x0b),
+	[PHYTIMING_CLK_PREPARE] = DSIM_PHYTIMING1_CLK_PREPARE(0x07),
+	[PHYTIMING_CLK_ZERO] = DSIM_PHYTIMING1_CLK_ZERO(0x27),
+	[PHYTIMING_CLK_POST] = DSIM_PHYTIMING1_CLK_POST(0x0d),
+	[PHYTIMING_CLK_TRAIL] = DSIM_PHYTIMING1_CLK_TRAIL(0x08),
+	[PHYTIMING_HS_PREPARE] = DSIM_PHYTIMING2_HS_PREPARE(0x09),
+	[PHYTIMING_HS_ZERO] = DSIM_PHYTIMING2_HS_ZERO(0x0d),
+	[PHYTIMING_HS_TRAIL] = DSIM_PHYTIMING2_HS_TRAIL(0x0b),
+};
+
+static const unsigned int exynos5422_reg_values[] = {
+	[RESET_TYPE] = DSIM_SWRST,
+	[PLL_TIMER] = 500,
+	[STOP_STATE_CNT] = 0xf,
+	[PHYCTRL_ULPS_EXIT] = DSIM_PHYCTRL_ULPS_EXIT(0xaf),
+	[PHYCTRL_VREG_LP] = 0,
+	[PHYCTRL_SLEW_UP] = 0,
+	[PHYTIMING_LPX] = DSIM_PHYTIMING_LPX(0x08),
+	[PHYTIMING_HS_EXIT] = DSIM_PHYTIMING_HS_EXIT(0x0d),
+	[PHYTIMING_CLK_PREPARE] = DSIM_PHYTIMING1_CLK_PREPARE(0x09),
+	[PHYTIMING_CLK_ZERO] = DSIM_PHYTIMING1_CLK_ZERO(0x30),
+	[PHYTIMING_CLK_POST] = DSIM_PHYTIMING1_CLK_POST(0x0e),
+	[PHYTIMING_CLK_TRAIL] = DSIM_PHYTIMING1_CLK_TRAIL(0x0a),
+	[PHYTIMING_HS_PREPARE] = DSIM_PHYTIMING2_HS_PREPARE(0x0c),
+	[PHYTIMING_HS_ZERO] = DSIM_PHYTIMING2_HS_ZERO(0x11),
+	[PHYTIMING_HS_TRAIL] = DSIM_PHYTIMING2_HS_TRAIL(0x0d),
+};
+
+static const unsigned int exynos5433_reg_values[] = {
+	[RESET_TYPE] = DSIM_FUNCRST,
+	[PLL_TIMER] = 22200,
+	[STOP_STATE_CNT] = 0xa,
+	[PHYCTRL_ULPS_EXIT] = DSIM_PHYCTRL_ULPS_EXIT(0x190),
+	[PHYCTRL_VREG_LP] = DSIM_PHYCTRL_B_DPHYCTL_VREG_LP,
+	[PHYCTRL_SLEW_UP] = DSIM_PHYCTRL_B_DPHYCTL_SLEW_UP,
+	[PHYTIMING_LPX] = DSIM_PHYTIMING_LPX(0x07),
+	[PHYTIMING_HS_EXIT] = DSIM_PHYTIMING_HS_EXIT(0x0c),
+	[PHYTIMING_CLK_PREPARE] = DSIM_PHYTIMING1_CLK_PREPARE(0x09),
+	[PHYTIMING_CLK_ZERO] = DSIM_PHYTIMING1_CLK_ZERO(0x2d),
+	[PHYTIMING_CLK_POST] = DSIM_PHYTIMING1_CLK_POST(0x0e),
+	[PHYTIMING_CLK_TRAIL] = DSIM_PHYTIMING1_CLK_TRAIL(0x09),
+	[PHYTIMING_HS_PREPARE] = DSIM_PHYTIMING2_HS_PREPARE(0x0b),
+	[PHYTIMING_HS_ZERO] = DSIM_PHYTIMING2_HS_ZERO(0x10),
+	[PHYTIMING_HS_TRAIL] = DSIM_PHYTIMING2_HS_TRAIL(0x0c),
+};
+
+static const unsigned int imx8mm_dsim_reg_values[] = {
+	[RESET_TYPE] = DSIM_SWRST,
+	[PLL_TIMER] = 500,
+	[STOP_STATE_CNT] = 0xf,
+	[PHYCTRL_ULPS_EXIT] = DSIM_PHYCTRL_ULPS_EXIT(0xaf),
+	[PHYCTRL_VREG_LP] = 0,
+	[PHYCTRL_SLEW_UP] = 0,
+	[PHYTIMING_LPX] = DSIM_PHYTIMING_LPX(0x06),
+	[PHYTIMING_HS_EXIT] = DSIM_PHYTIMING_HS_EXIT(0x0b),
+	[PHYTIMING_CLK_PREPARE] = DSIM_PHYTIMING1_CLK_PREPARE(0x07),
+	[PHYTIMING_CLK_ZERO] = DSIM_PHYTIMING1_CLK_ZERO(0x26),
+	[PHYTIMING_CLK_POST] = DSIM_PHYTIMING1_CLK_POST(0x0d),
+	[PHYTIMING_CLK_TRAIL] = DSIM_PHYTIMING1_CLK_TRAIL(0x08),
+	[PHYTIMING_HS_PREPARE] = DSIM_PHYTIMING2_HS_PREPARE(0x08),
+	[PHYTIMING_HS_ZERO] = DSIM_PHYTIMING2_HS_ZERO(0x0d),
+	[PHYTIMING_HS_TRAIL] = DSIM_PHYTIMING2_HS_TRAIL(0x0b),
+};
+
+static const struct samsung_dsim_driver_data exynos3_dsi_driver_data = {
+	.reg_ofs = exynos_reg_ofs,
+	.plltmr_reg = 0x50,
+	.has_freqband = 1,
+	.has_clklane_stop = 1,
+	.num_clks = 2,
+	.max_freq = 1000,
+	.wait_for_reset = 1,
+	.num_bits_resol = 11,
+	.pll_p_offset = 13,
+	.reg_values = reg_values,
+	.pll_fin_min = 6,
+	.pll_fin_max = 12,
+	.m_min = 41,
+	.m_max = 125,
+	.min_freq = 500,
+	.has_broken_fifoctrl_emptyhdr = 1,
+};
+
+static const struct samsung_dsim_driver_data exynos4_dsi_driver_data = {
+	.reg_ofs = exynos_reg_ofs,
+	.plltmr_reg = 0x50,
+	.has_freqband = 1,
+	.has_clklane_stop = 1,
+	.num_clks = 2,
+	.max_freq = 1000,
+	.wait_for_reset = 1,
+	.num_bits_resol = 11,
+	.pll_p_offset = 13,
+	.reg_values = reg_values,
+	.pll_fin_min = 6,
+	.pll_fin_max = 12,
+	.m_min = 41,
+	.m_max = 125,
+	.min_freq = 500,
+	.has_broken_fifoctrl_emptyhdr = 1,
+};
+
+static const struct samsung_dsim_driver_data exynos5_dsi_driver_data = {
+	.reg_ofs = exynos_reg_ofs,
+	.plltmr_reg = 0x58,
+	.num_clks = 2,
+	.max_freq = 1000,
+	.wait_for_reset = 1,
+	.num_bits_resol = 11,
+	.pll_p_offset = 13,
+	.reg_values = reg_values,
+	.pll_fin_min = 6,
+	.pll_fin_max = 12,
+	.m_min = 41,
+	.m_max = 125,
+	.min_freq = 500,
+};
+
+static const struct samsung_dsim_driver_data exynos5433_dsi_driver_data = {
+	.reg_ofs = exynos5433_reg_ofs,
+	.plltmr_reg = 0xa0,
+	.has_clklane_stop = 1,
+	.num_clks = 5,
+	.max_freq = 1500,
+	.wait_for_reset = 0,
+	.num_bits_resol = 12,
+	.pll_p_offset = 13,
+	.reg_values = exynos5433_reg_values,
+	.pll_fin_min = 6,
+	.pll_fin_max = 12,
+	.m_min = 41,
+	.m_max = 125,
+	.min_freq = 500,
+};
+
+static const struct samsung_dsim_driver_data exynos5422_dsi_driver_data = {
+	.reg_ofs = exynos5433_reg_ofs,
+	.plltmr_reg = 0xa0,
+	.has_clklane_stop = 1,
+	.num_clks = 2,
+	.max_freq = 1500,
+	.wait_for_reset = 1,
+	.num_bits_resol = 12,
+	.pll_p_offset = 13,
+	.reg_values = exynos5422_reg_values,
+	.pll_fin_min = 6,
+	.pll_fin_max = 12,
+	.m_min = 41,
+	.m_max = 125,
+	.min_freq = 500,
+};
+
+static const struct samsung_dsim_driver_data imx8mm_dsi_driver_data = {
+	.reg_ofs = exynos5433_reg_ofs,
+	.plltmr_reg = 0xa0,
+	.has_clklane_stop = 1,
+	.num_clks = 2,
+	.max_freq = 2100,
+	.wait_for_reset = 0,
+	.num_bits_resol = 12,
+	/*
+	 * Unlike Exynos, PLL_P(PMS_P) offset 14 is used in i.MX8M Mini/Nano/Plus
+	 * downstream driver - drivers/gpu/drm/bridge/sec-dsim.c
+	 */
+	.pll_p_offset = 14,
+	.reg_values = imx8mm_dsim_reg_values,
+	.pll_fin_min = 2,
+	.pll_fin_max = 30,
+	.m_min = 64,
+	.m_max = 1023,
+	.min_freq = 1050,
+};
+
+static const struct samsung_dsim_driver_data *
+samsung_dsim_types[DSIM_TYPE_COUNT] = {
+	[DSIM_TYPE_EXYNOS3250] = &exynos3_dsi_driver_data,
+	[DSIM_TYPE_EXYNOS4210] = &exynos4_dsi_driver_data,
+	[DSIM_TYPE_EXYNOS5410] = &exynos5_dsi_driver_data,
+	[DSIM_TYPE_EXYNOS5422] = &exynos5422_dsi_driver_data,
+	[DSIM_TYPE_EXYNOS5433] = &exynos5433_dsi_driver_data,
+	[DSIM_TYPE_IMX8MM] = &imx8mm_dsi_driver_data,
+	[DSIM_TYPE_IMX8MP] = &imx8mm_dsi_driver_data,
+};
+
+/* DSIM PLL configuration from spec:
+ *
+ * Fout(DDR) = (M * Fin) / (P * 2^S), so Fout / Fin = M / (P * 2^S)
+ * Fin_pll   = Fin / P     (6 ~ 12 MHz)
+ * S: [2:0], M: [12:3], P: [18:13], so
+ * TODO: 'S' is in [0 ~ 3], 'M' is in, 'P' is in [1 ~ 33]
+ *
+ */
+
+struct samsung_dsi {
+	void __iomem *reg_base;
+	struct clk sclk_mipi;
+	const struct samsung_dsim_driver_data *driver_data;
+
+	/* kHz clocks */
+	u64 pix_clk;
+	u64 bit_clk;
+	u64 hs_clock;
+
+	unsigned int lanes;
+	unsigned int channel;			/* virtual channel */
+	enum mipi_dsi_pixel_format format;
+	unsigned long mode_flags;
+	unsigned int pms;
+
+	struct mipi_dsi_device *device;
+	u32 max_data_lanes;
+
+	struct mipi_dsi_host dsi_host;
+	struct display_timing timings;
+};
+
+static inline void samsung_dsim_write(struct samsung_dsi *dsi,
+				      enum reg_idx idx, u32 val)
+{
+	writel(val, dsi->reg_base + dsi->driver_data->reg_ofs[idx]);
+}
+
+static inline u32 samsung_dsim_read(struct samsung_dsi *dsi, enum reg_idx idx)
+{
+	return readl(dsi->reg_base + dsi->driver_data->reg_ofs[idx]);
+}
+
+static int samsung_dsi_wait_for_pkt_done(struct samsung_dsi *dsim, unsigned long timeout)
+{
+	u32 intsrc;
+
+	do {
+		intsrc = samsung_dsim_read(dsim, DSIM_INTSRC_REG);
+		if (intsrc & INTSRC_SFRPLFIFOEMPTY) {
+			samsung_dsim_write(dsim, DSIM_INTSRC_REG, INTSRC_SFRPLFIFOEMPTY);
+			return 0;
+		}
+
+		udelay(1);
+	} while (--timeout);
+
+	return -ETIMEDOUT;
+}
+
+static int samsung_dsi_wait_for_hdr_done(struct samsung_dsi *dsim, unsigned long timeout)
+{
+	u32 intsrc;
+
+	do {
+		intsrc = samsung_dsim_read(dsim, DSIM_INTSRC_REG);
+		if (intsrc & INTSRC_SFRPHFIFOEMPTY) {
+			samsung_dsim_write(dsim, DSIM_INTSRC_REG, INTSRC_SFRPHFIFOEMPTY);
+			return 0;
+		}
+
+		udelay(1);
+	} while (--timeout);
+
+	return -ETIMEDOUT;
+}
+
+static int samsung_dsi_wait_for_rx_done(struct samsung_dsi *dsim,
+					unsigned long timeout)
+{
+	u32 intsrc;
+
+	do {
+		intsrc = samsung_dsim_read(dsim, DSIM_INTSRC_REG);
+		if (intsrc & INTSRC_RXDATDONE) {
+			samsung_dsim_write(dsim, DSIM_INTSRC_REG, INTSRC_RXDATDONE);
+			return 0;
+		}
+
+		udelay(1);
+	} while (--timeout);
+
+	return -ETIMEDOUT;
+}
+
+static int samsung_dsi_wait_pll_stable(struct samsung_dsi *dsim)
+{
+	u32 status;
+	ulong start;
+
+	start = get_timer(0);	/* Get current timestamp */
+
+	do {
+		status = samsung_dsim_read(dsim, DSIM_STATUS_REG);
+		if (status & DSIM_PLL_STABLE)
+			return 0;
+	} while (get_timer(0) < (start + 100)); /* Wait 100ms */
+
+	return -ETIMEDOUT;
+}
+
+static unsigned long samsung_dsim_pll_find_pms(struct samsung_dsi *dsi,
+					       unsigned long fin,
+					       unsigned long fout,
+					       u8 *p, u16 *m, u8 *s)
+{
+	const struct samsung_dsim_driver_data *driver_data = dsi->driver_data;
+	unsigned long best_freq = 0;
+	u32 min_delta = 0xffffffff;
+	u8 p_min, p_max;
+	u8 _p, best_p;
+	u16 _m, best_m;
+	u8 _s, best_s;
+
+	p_min = DIV_ROUND_UP(fin, (MHZ(12)));
+	p_max = fin / (MHZ(6));
+
+	for (_p = p_min; _p <= p_max; ++_p) {
+		for (_s = 0; _s <= 5; ++_s) {
+			u64 tmp;
+			u32 delta;
+
+			tmp = (u64)fout * (_p << _s);
+			do_div(tmp, fin);
+			_m = tmp;
+			if (_m < driver_data->m_min || _m > driver_data->m_max)
+				continue;
+
+			tmp = (u64)_m * fin;
+			do_div(tmp, _p);
+			if (tmp < driver_data->min_freq  * MHZ(1) ||
+			    tmp > driver_data->max_freq * MHZ(1))
+				continue;
+
+			tmp = (u64)_m * fin;
+			do_div(tmp, _p << _s);
+
+			delta = abs(fout - tmp);
+			if (delta < min_delta) {
+				best_p = _p;
+				best_m = _m;
+				best_s = _s;
+				min_delta = delta;
+				best_freq = tmp;
+			}
+		}
+	}
+
+	if (best_freq) {
+		*p = best_p;
+		*m = best_m;
+		*s = best_s;
+	}
+
+	return best_freq;
+}
+
+static int samsung_dsi_config_pll(struct samsung_dsi *dsim)
+{
+	int ret;
+	u32 pllctrl = 0, status, data_lanes_en, stop;
+
+	writel(dsim->driver_data->reg_values[PLL_TIMER],
+	       dsim->reg_base + dsim->driver_data->plltmr_reg);
+
+	/* TODO: config dp/dn swap if requires */
+
+	pllctrl |= PLLCTRL_SET_PMS(dsim->pms) | PLLCTRL_PLLEN;
+	samsung_dsim_write(dsim, DSIM_PLLCTRL_REG, pllctrl);
+
+	ret = samsung_dsi_wait_pll_stable(dsim);
+	if (ret) {
+		log_err("wait for pll stable time out\n");
+		return ret;
+	}
+
+	/* wait for clk & data lanes to go to stop state */
+	mdelay(1);
+
+	data_lanes_en = (0x1 << dsim->lanes) - 1;
+	status = samsung_dsim_read(dsim, DSIM_STATUS_REG);
+	if (!(status & DSIM_STOP_STATE_CLK)) {
+		log_err("clock is not in stop state\n");
+		return -EBUSY;
+	}
+
+	stop = DSIM_STOP_STATE_DAT(status);
+	if ((stop & data_lanes_en) != data_lanes_en) {
+		log_err("one or more data lanes is not in stop state\n");
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
+static void samsung_dsi_set_main_mode(struct samsung_dsi *dsim)
+{
+	u32 bpp, hfp_wc, hbp_wc, hsa_wc, wc;
+	u32 mdresol = 0, mvporch = 0, mhporch = 0, msync = 0;
+	struct display_timing *timings = &dsim->timings;
+	unsigned int num_bits_resol = dsim->driver_data->num_bits_resol;
+
+	mdresol |= DSIM_MAIN_VRESOL(timings->vactive.typ, num_bits_resol) |
+		   DSIM_MAIN_HRESOL(timings->hactive.typ, num_bits_resol);
+	samsung_dsim_write(dsim, DSIM_MDRESOL_REG, mdresol);
+
+	mvporch |= MVPORCH_SET_MAINVBP(timings->vback_porch.typ)    |
+		   MVPORCH_SET_STABLEVFP(timings->vfront_porch.typ) |
+		   MVPORCH_SET_CMDALLOW(0x0);
+	samsung_dsim_write(dsim, DSIM_MVPORCH_REG, mvporch);
+
+	bpp = mipi_dsi_pixel_format_to_bpp(dsim->format);
+
+	wc = DIV_ROUND_UP(timings->hfront_porch.typ * (bpp >> 3), dsim->lanes);
+	hfp_wc = wc > MIPI_HFP_PKT_OVERHEAD ?
+		wc - MIPI_HFP_PKT_OVERHEAD : timings->hfront_porch.typ;
+	wc = DIV_ROUND_UP(timings->hback_porch.typ * (bpp >> 3), dsim->lanes);
+	hbp_wc = wc > MIPI_HBP_PKT_OVERHEAD ?
+		wc - MIPI_HBP_PKT_OVERHEAD : timings->hback_porch.typ;
+
+	mhporch |= MHPORCH_SET_MAINHFP(hfp_wc) |
+		   MHPORCH_SET_MAINHBP(hbp_wc);
+
+	samsung_dsim_write(dsim, DSIM_MHPORCH_REG, mhporch);
+
+	wc = DIV_ROUND_UP(timings->hsync_len.typ * (bpp >> 3), dsim->lanes);
+	hsa_wc = wc > MIPI_HSA_PKT_OVERHEAD ?
+		wc - MIPI_HSA_PKT_OVERHEAD : timings->hsync_len.typ;
+
+	msync |= MSYNC_SET_MAINVSA(timings->vsync_len.typ) |
+		 MSYNC_SET_MAINHSA(hsa_wc);
+
+	debug("hfp_wc %u hbp_wc %u hsa_wc %u\n", hfp_wc, hbp_wc, hsa_wc);
+
+	samsung_dsim_write(dsim, DSIM_MSYNC_REG, msync);
+}
+
+static void samsung_dsi_config_dpi(struct samsung_dsi *dsim)
+{
+	u32 config = 0, rgb_status = 0, data_lanes_en;
+
+	if (dsim->mode_flags & MIPI_DSI_MODE_VIDEO)
+		rgb_status &= ~RGB_STATUS_CMDMODE_INSEL;
+	else
+		rgb_status |= RGB_STATUS_CMDMODE_INSEL;
+
+	samsung_dsim_write(dsim, DSIM_RGB_STATUS_REG, rgb_status);
+
+	if (dsim->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) {
+		config |= DSIM_CLKLANE_STOP;
+		config |= DSIM_NON_CONTINUOUS_CLKLANE;
+	}
+
+	if (dsim->mode_flags & MIPI_DSI_MODE_VSYNC_FLUSH)
+		config |= DSIM_MFLUSH_VS;
+
+	/* disable EoT packets in HS mode */
+	if (dsim->mode_flags & MIPI_DSI_MODE_EOT_PACKET)
+		config |= DSIM_EOT_DISABLE;
+
+	if (dsim->mode_flags & MIPI_DSI_MODE_VIDEO) {
+		config |= DSIM_VIDEO_MODE;
+
+		if (dsim->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
+			config |= DSIM_BURST_MODE;
+
+		else if (dsim->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
+			config |= DSIM_SYNC_INFORM;
+
+		if (dsim->mode_flags & MIPI_DSI_MODE_VIDEO_AUTO_VERT)
+			config |= DSIM_AUTO_MODE;
+
+		if (dsim->mode_flags & MIPI_DSI_MODE_VIDEO_HSE)
+			config |= DSIM_HSE_DISABLE_MODE;
+
+		if (dsim->mode_flags & MIPI_DSI_MODE_VIDEO_HFP)
+			config |= DSIM_HFP_DISABLE_MODE;
+
+		if (dsim->mode_flags & MIPI_DSI_MODE_VIDEO_HBP)
+			config |= DSIM_HBP_DISABLE_MODE;
+
+		if (dsim->mode_flags & MIPI_DSI_MODE_VIDEO_HSA)
+			config |= DSIM_HSA_DISABLE_MODE;
+	}
+
+	config |= DSIM_MAIN_VC(dsim->channel);
+
+	if (dsim->mode_flags & MIPI_DSI_MODE_VIDEO) {
+		switch (dsim->format) {
+		case MIPI_DSI_FMT_RGB888:
+			config |= DSIM_MAIN_PIX_FORMAT_RGB888;
+			break;
+		case MIPI_DSI_FMT_RGB666:
+			config |= DSIM_MAIN_PIX_FORMAT_RGB666;
+			break;
+		case MIPI_DSI_FMT_RGB666_PACKED:
+			config |= DSIM_MAIN_PIX_FORMAT_RGB666_P;
+			break;
+		case MIPI_DSI_FMT_RGB565:
+			config |= DSIM_MAIN_PIX_FORMAT_RGB565;
+			break;
+		default:
+			log_err("invalid pixel format\n");
+			break;
+		}
+	}
+
+	/* config data lanes number and enable lanes */
+	data_lanes_en = BIT(dsim->lanes) - 1;
+	config |= (DSIM_NUM_OF_DATA_LANE(dsim->lanes - 1) | DSIM_LANE_EN_CLK |
+			DSIM_LANE_EN(data_lanes_en));
+
+	debug("DSIM config 0x%x\n", config);
+
+	samsung_dsim_write(dsim, DSIM_CONFIG_REG, config);
+}
+
+static void samsung_dsi_config_cmd_lpm(struct samsung_dsi *dsim, bool enable)
+{
+	u32 escmode;
+
+	escmode = samsung_dsim_read(dsim, DSIM_ESCMODE_REG);
+
+	if (enable)
+		escmode |= ESCMODE_CMDLPDT;
+	else
+		escmode &= ~ESCMODE_CMDLPDT;
+
+	samsung_dsim_write(dsim, DSIM_ESCMODE_REG, escmode);
+}
+
+static void samsung_dsi_config_dphy(struct samsung_dsi *dsim)
+{
+	const struct samsung_dsim_driver_data *driver_data = dsim->driver_data;
+	const unsigned int *reg_values = driver_data->reg_values;
+	u32 reg;
+	struct phy_configure_opts_mipi_dphy cfg;
+	int clk_prepare, lpx, clk_zero, clk_post, clk_trail;
+	int hs_exit, hs_prepare, hs_zero, hs_trail;
+	unsigned long long byte_clock = dsim->hs_clock / 8;
+
+	if (driver_data->has_freqband)
+		return;
+
+	phy_mipi_dphy_get_default_config_for_hsclk(dsim->hs_clock, dsim->lanes, &cfg);
+
+	/*
+	 * TODO:
+	 * The tech Applications Processor manuals for i.MX8M Mini, Nano,
+	 * and Plus don't state what the definition of the PHYTIMING
+	 * bits are beyond their address and bit position.
+	 * After reviewing NXP's downstream code, it appears
+	 * that the various PHYTIMING registers take the number
+	 * of cycles and use various dividers on them.  This
+	 * calculation does not result in an exact match to the
+	 * downstream code, but it is very close to the values
+	 * generated by their lookup table, and it appears
+	 * to sync at a variety of resolutions. If someone
+	 * can get a more accurate mathematical equation needed
+	 * for these registers, this should be updated.
+	 */
+
+	lpx = PS_TO_CYCLE(cfg.lpx, byte_clock);
+	hs_exit = PS_TO_CYCLE(cfg.hs_exit, byte_clock);
+	clk_prepare = PS_TO_CYCLE(cfg.clk_prepare, byte_clock);
+	clk_zero = PS_TO_CYCLE(cfg.clk_zero, byte_clock);
+	clk_post = PS_TO_CYCLE(cfg.clk_post, byte_clock);
+	clk_trail = PS_TO_CYCLE(cfg.clk_trail, byte_clock);
+	hs_prepare = PS_TO_CYCLE(cfg.hs_prepare, byte_clock);
+	hs_zero = PS_TO_CYCLE(cfg.hs_zero, byte_clock);
+	hs_trail = PS_TO_CYCLE(cfg.hs_trail, byte_clock);
+
+	/* B D-PHY: D-PHY Master & Slave Analog Block control */
+	reg = reg_values[PHYCTRL_ULPS_EXIT] | reg_values[PHYCTRL_VREG_LP] |
+		reg_values[PHYCTRL_SLEW_UP];
+
+	samsung_dsim_write(dsim, DSIM_PHYCTRL_REG, reg);
+
+	/*
+	 * T LPX: Transmitted length of any Low-Power state period
+	 * T HS-EXIT: Time that the transmitter drives LP-11 following a HS
+	 *	burst
+	 */
+
+	reg = DSIM_PHYTIMING_LPX(lpx) | DSIM_PHYTIMING_HS_EXIT(hs_exit);
+	samsung_dsim_write(dsim, DSIM_PHYTIMING_REG, reg);
+
+	/*
+	 * T CLK-PREPARE: Time that the transmitter drives the Clock Lane LP-00
+	 *	Line state immediately before the HS-0 Line state starting the
+	 *	HS transmission
+	 * T CLK-ZERO: Time that the transmitter drives the HS-0 state prior to
+	 *	transmitting the Clock.
+	 * T CLK_POST: Time that the transmitter continues to send HS clock
+	 *	after the last associated Data Lane has transitioned to LP Mode
+	 *	Interval is defined as the period from the end of T HS-TRAIL to
+	 *	the beginning of T CLK-TRAIL
+	 * T CLK-TRAIL: Time that the transmitter drives the HS-0 state after
+	 *	the last payload clock bit of a HS transmission burst
+	 */
+
+	reg = DSIM_PHYTIMING1_CLK_PREPARE(clk_prepare) |
+	      DSIM_PHYTIMING1_CLK_ZERO(clk_zero) |
+	      DSIM_PHYTIMING1_CLK_POST(clk_post) |
+	      DSIM_PHYTIMING1_CLK_TRAIL(clk_trail);
+
+	samsung_dsim_write(dsim, DSIM_PHYTIMING1_REG, reg);
+
+	/*
+	 * T HS-PREPARE: Time that the transmitter drives the Data Lane LP-00
+	 *	Line state immediately before the HS-0 Line state starting the
+	 *	HS transmission
+	 * T HS-ZERO: Time that the transmitter drives the HS-0 state prior to
+	 *	transmitting the Sync sequence.
+	 * T HS-TRAIL: Time that the transmitter drives the flipped differential
+	 *	state after last payload data bit of a HS transmission burst
+	 */
+
+	reg = DSIM_PHYTIMING2_HS_PREPARE(hs_prepare) |
+	      DSIM_PHYTIMING2_HS_ZERO(hs_zero) |
+	      DSIM_PHYTIMING2_HS_TRAIL(hs_trail);
+
+	samsung_dsim_write(dsim, DSIM_PHYTIMING2_REG, reg);
+
+	reg = DSIM_BTA_TIMEOUT(0xff) | DSIM_LPDR_TIMEOUT(0xffff);
+
+	samsung_dsim_write(dsim, DSIM_TIMEOUT_REG, reg);
+}
+
+static void samsung_dsim_write_pl_to_sfr_fifo(struct samsung_dsi *dsim,
+					      const void *payload,
+					      size_t length)
+{
+	u32 pl_data;
+
+	if (!length)
+		return;
+
+	while (length >= 4) {
+		pl_data = get_unaligned_le32(payload);
+		samsung_dsim_write(dsim, DSIM_PAYLOAD_REG, pl_data);
+		payload += 4;
+		length -= 4;
+	}
+
+	pl_data = 0;
+	switch (length) {
+	case 3:
+		pl_data |= ((u8 *)payload)[2] << 16;
+	case 2:
+		pl_data |= ((u8 *)payload)[1] << 8;
+	case 1:
+		pl_data |= ((u8 *)payload)[0];
+		samsung_dsim_write(dsim, DSIM_PAYLOAD_REG, pl_data);
+		break;
+	}
+}
+
+static void samsung_dsim_write_ph_to_sfr_fifo(struct samsung_dsi *dsim,
+					      void *header, bool use_lpm)
+{
+	u32 pkthdr;
+
+	pkthdr = PKTHDR_SET_DATA1(((u8 *)header)[2])	| /* WC MSB  */
+		 PKTHDR_SET_DATA0(((u8 *)header)[1])	| /* WC LSB  */
+		 PKTHDR_SET_DI(((u8 *)header)[0]);	  /* Data ID */
+
+	samsung_dsim_write(dsim, DSIM_PKTHDR_REG, pkthdr);
+}
+
+static int samsung_dsim_read_pl_from_sfr_fifo(struct samsung_dsi *dsim,
+					      void *payload, size_t length)
+{
+	u8 data_type;
+	u16 word_count = 0;
+	u32 fifoctrl, ph, pl;
+
+	fifoctrl = samsung_dsim_read(dsim, DSIM_FIFOCTRL_REG);
+
+	if (WARN_ON(fifoctrl & FIFOCTRL_EMPTYRX))
+		return -EINVAL;
+
+	ph = samsung_dsim_read(dsim, DSIM_RXFIFO_REG);
+	data_type = PKTHDR_GET_DT(ph);
+	switch (data_type) {
+	case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT:
+		dev_err(dsim->device->dev, "peripheral report error: (0-7)%x, (8-15)%x\n",
+			PKTHDR_GET_DATA0(ph), PKTHDR_GET_DATA1(ph));
+		return -EPROTO;
+	case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE:
+	case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE:
+		if (!WARN_ON(length < 2)) {
+			((u8 *)payload)[1] = PKTHDR_GET_DATA1(ph);
+			word_count++;
+		}
+		fallthrough;
+	case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE:
+	case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE:
+		((u8 *)payload)[0] = PKTHDR_GET_DATA0(ph);
+		word_count++;
+		length = word_count;
+		break;
+	case MIPI_DSI_RX_DCS_LONG_READ_RESPONSE:
+	case MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE:
+		word_count = PKTHDR_GET_WC(ph);
+		if (word_count > length) {
+			dev_err(dsim->device->dev, "invalid receive buffer length\n");
+			return -EINVAL;
+		}
+
+		length = word_count;
+
+		while (word_count >= 4) {
+			pl = samsung_dsim_read(dsim, DSIM_RXFIFO_REG);
+			((u8 *)payload)[0] = pl & 0xff;
+			((u8 *)payload)[1] = (pl >> 8)  & 0xff;
+			((u8 *)payload)[2] = (pl >> 16) & 0xff;
+			((u8 *)payload)[3] = (pl >> 24) & 0xff;
+			payload += 4;
+			word_count -= 4;
+		}
+
+		if (word_count > 0) {
+			pl = samsung_dsim_read(dsim, DSIM_RXFIFO_REG);
+
+			switch (word_count) {
+			case 3:
+				((u8 *)payload)[2] = (pl >> 16) & 0xff;
+			case 2:
+				((u8 *)payload)[1] = (pl >> 8) & 0xff;
+			case 1:
+				((u8 *)payload)[0] = pl & 0xff;
+				break;
+			}
+		}
+
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return length;
+}
+
+static void samsung_dsi_init_fifo_pointers(struct samsung_dsi *dsim)
+{
+	u32 fifoctrl, fifo_ptrs;
+
+	fifoctrl = samsung_dsim_read(dsim, DSIM_FIFOCTRL_REG);
+
+	fifo_ptrs = FIFOCTRL_NINITRX	|
+		    FIFOCTRL_NINITSFR	|
+		    FIFOCTRL_NINITI80	|
+		    FIFOCTRL_NINITSUB	|
+		    FIFOCTRL_NINITMAIN;
+
+	fifoctrl &= ~fifo_ptrs;
+	samsung_dsim_write(dsim, DSIM_FIFOCTRL_REG, fifoctrl);
+	udelay(500);
+
+	fifoctrl |= fifo_ptrs;
+	samsung_dsim_write(dsim, DSIM_FIFOCTRL_REG, fifoctrl);
+	udelay(500);
+}
+
+static void samsung_dsi_config_clkctrl(struct samsung_dsi *dsim)
+{
+	u32 clkctrl = 0, data_lanes_en;
+	u64 byte_clk, esc_prescaler;
+
+	clkctrl |= DSIM_TX_REQUEST_HSCLK;
+
+	/* using 1.5Gbps PHY */
+	clkctrl |= CLKCTRL_DPHY_SEL_1P5G;
+	clkctrl |= DSIM_ESC_CLKEN;
+	clkctrl &= ~CLKCTRL_PLLBYPASS;
+	clkctrl |= CLKCTRL_BYTECLKSRC_DPHY_PLL;
+	clkctrl |= DSIM_BYTE_CLKEN;
+
+	data_lanes_en = (0x1 << dsim->lanes) - 1;
+	clkctrl |= CLKCTRL_SET_LANEESCCLKEN(0x1 | data_lanes_en << 1);
+
+	/* calculate esc prescaler from byte clock:
+	 * EscClk = ByteClk / EscPrescaler;
+	 */
+	byte_clk = dsim->bit_clk >> 3;
+	esc_prescaler = DIV_ROUND_UP_ULL(byte_clk, MAX_ESC_CLK_FREQ);
+
+	clkctrl |= CLKCTRL_SET_ESCPRESCALER(esc_prescaler);
+
+	debug("DSIM clkctrl 0x%x\n", clkctrl);
+
+	samsung_dsim_write(dsim, DSIM_CLKCTRL_REG, clkctrl);
+}
+
+static void samsung_dsi_set_standby(struct samsung_dsi *dsim, bool standby)
+{
+	u32 mdresol = 0;
+
+	mdresol = samsung_dsim_read(dsim, DSIM_MDRESOL_REG);
+
+	if (standby)
+		mdresol |= DSIM_MAIN_STAND_BY;
+	else
+		mdresol &= ~DSIM_MAIN_STAND_BY;
+
+	samsung_dsim_write(dsim, DSIM_MDRESOL_REG, mdresol);
+}
+
+static void samsung_dsi_disable_clock(struct samsung_dsi *dsim)
+{
+	u32 reg;
+
+	reg = samsung_dsim_read(dsim, DSIM_CLKCTRL_REG);
+	reg &= ~(DSIM_LANE_ESC_CLK_EN_CLK | DSIM_LANE_ESC_CLK_EN_DATA_MASK |
+		 DSIM_ESC_CLKEN | DSIM_BYTE_CLKEN);
+	samsung_dsim_write(dsim, DSIM_CLKCTRL_REG, reg);
+
+	reg = samsung_dsim_read(dsim, DSIM_PLLCTRL_REG);
+	reg &= ~DSIM_PLL_EN;
+	samsung_dsim_write(dsim, DSIM_PLLCTRL_REG, reg);
+}
+
+static inline struct samsung_dsi *host_to_dsi(struct mipi_dsi_host *host)
+{
+	return container_of(host, struct samsung_dsi, dsi_host);
+}
+
+static int samsung_dsi_bridge_clk_set(struct samsung_dsi *dsim_host)
+{
+	int bpp;
+	unsigned long pix_clk, bit_clk;
+	unsigned long fin, fout;
+	u8 p, s;
+	u16 m;
+
+	bpp = mipi_dsi_pixel_format_to_bpp(dsim_host->format);
+	if (bpp < 0)
+		return -EINVAL;
+
+	pix_clk = dsim_host->timings.pixelclock.typ;
+	bit_clk = DIV_ROUND_UP_ULL(pix_clk * bpp, dsim_host->lanes);
+
+	dsim_host->pix_clk = DIV_ROUND_UP_ULL(pix_clk, 1000);
+	dsim_host->bit_clk = DIV_ROUND_UP_ULL(bit_clk, 1000);
+
+	fout = dsim_host->bit_clk;
+	fin  = clk_get_rate(&dsim_host->sclk_mipi);
+	if (fin == 0) {
+		log_err("Error: DSI PHY reference clock is disabled\n");
+		return -EINVAL;
+	}
+
+	fout = samsung_dsim_pll_find_pms(dsim_host, fin, bit_clk, &p, &m, &s);
+	if (!fout) {
+		log_err("failed to find PLL PMS for requested frequency\n");
+		return -EINVAL;
+	}
+	dsim_host->pms = PLLCTRL_SET_P(p) | PLLCTRL_SET_M(m) |
+			 PLLCTRL_SET_S(s);
+	dsim_host->hs_clock = fout;
+
+	debug("%s: bitclk %llu pixclk %llu pms 0x%x\n", __func__,
+	      dsim_host->bit_clk, dsim_host->pix_clk, dsim_host->pms);
+
+	return 0;
+}
+
+static int samsung_dsi_bridge_prepare(struct samsung_dsi *dsim_host)
+{
+	int ret;
+
+	/* At this moment, the dsim bridge's preceding encoder has
+	 * already been enabled. So the dsim can be configed here
+	 */
+
+	/* config main display mode */
+	samsung_dsi_set_main_mode(dsim_host);
+
+	/* config dsim dpi */
+	samsung_dsi_config_dpi(dsim_host);
+
+	/* config dsim pll */
+	ret = samsung_dsi_config_pll(dsim_host);
+	if (ret) {
+		log_err("dsim pll config failed: %d\n", ret);
+		return ret;
+	}
+
+	/* config dphy timings */
+	samsung_dsi_config_dphy(dsim_host);
+
+	samsung_dsi_init_fifo_pointers(dsim_host);
+
+	/* config esc clock, byte clock and etc */
+	samsung_dsi_config_clkctrl(dsim_host);
+
+	return 0;
+}
+
+static int samsung_dsi_host_attach(struct mipi_dsi_host *host,
+				   struct mipi_dsi_device *device)
+{
+	struct samsung_dsi *dsi = host_to_dsi(host);
+
+	if (!device->lanes || device->lanes > dsi->max_data_lanes) {
+		log_err("invalid data lanes number\n");
+		return -EINVAL;
+	}
+
+	if (!(device->mode_flags & MIPI_DSI_MODE_VIDEO)		||
+	    !((device->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)	||
+	      (device->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE))) {
+		log_err("unsupported dsi mode\n");
+		return -EINVAL;
+	}
+
+	if (device->format != MIPI_DSI_FMT_RGB888 &&
+	    device->format != MIPI_DSI_FMT_RGB565 &&
+	    device->format != MIPI_DSI_FMT_RGB666 &&
+	    device->format != MIPI_DSI_FMT_RGB666_PACKED) {
+		log_err("unsupported pixel format: %#x\n", device->format);
+		return -EINVAL;
+	}
+
+	dsi->lanes	 = device->lanes;
+	dsi->channel	 = device->channel;
+	dsi->format	 = device->format;
+	dsi->mode_flags = device->mode_flags;
+
+	debug("lanes %u, channel %u, format 0x%x, mode_flags 0x%lx\n", dsi->lanes,
+	      dsi->channel, dsi->format, dsi->mode_flags);
+
+	samsung_dsi_bridge_clk_set(dsi);
+	samsung_dsi_bridge_prepare(dsi);
+
+	return 0;
+}
+
+static ssize_t samsung_dsi_host_transfer(struct mipi_dsi_host *host,
+					 const struct mipi_dsi_msg *msg)
+{
+	struct samsung_dsi *dsim = host_to_dsi(host);
+	int ret, nb_bytes;
+	bool use_lpm;
+	struct mipi_dsi_packet packet;
+
+	ret = mipi_dsi_create_packet(&packet, msg);
+	if (ret) {
+		dev_err(dsim->device->dev, "failed to create dsi packet: %d\n", ret);
+		return ret;
+	}
+
+	/* config LPM for CMD TX */
+	use_lpm = msg->flags & MIPI_DSI_MSG_USE_LPM ? true : false;
+	samsung_dsi_config_cmd_lpm(dsim, use_lpm);
+
+	if (packet.payload_length) {		/* Long Packet case */
+		/* write packet payload */
+		samsung_dsim_write_pl_to_sfr_fifo(dsim, packet.payload,
+						  packet.payload_length);
+
+		/* write packet header */
+		samsung_dsim_write_ph_to_sfr_fifo(dsim, packet.header, use_lpm);
+
+		ret = samsung_dsi_wait_for_pkt_done(dsim, MIPI_FIFO_TIMEOUT);
+		if (ret) {
+			dev_err(dsim->device->dev, "wait tx done timeout!\n");
+			return -EBUSY;
+		}
+	} else {
+		/* write packet header */
+		samsung_dsim_write_ph_to_sfr_fifo(dsim, packet.header, use_lpm);
+
+		ret = samsung_dsi_wait_for_hdr_done(dsim, MIPI_FIFO_TIMEOUT);
+		if (ret) {
+			dev_err(dsim->device->dev, "wait pkthdr tx done time out\n");
+			return -EBUSY;
+		}
+	}
+
+	/* read packet payload */
+	if (unlikely(msg->rx_buf)) {
+		ret = samsung_dsi_wait_for_rx_done(dsim, MIPI_FIFO_TIMEOUT);
+		if (ret) {
+			dev_err(dsim->device->dev, "wait rx done time out\n");
+			return -EBUSY;
+		}
+
+		ret = samsung_dsim_read_pl_from_sfr_fifo(dsim, msg->rx_buf,
+							 msg->rx_len);
+		if (ret < 0)
+			return ret;
+		nb_bytes = msg->rx_len;
+	} else {
+		nb_bytes = packet.size;
+	}
+
+	return nb_bytes;
+}
+
+static const struct mipi_dsi_host_ops samsung_dsi_host_ops = {
+	.attach = samsung_dsi_host_attach,
+	.transfer = samsung_dsi_host_transfer,
+};
+
+static int samsung_dsi_init(struct udevice *dev,
+			    struct mipi_dsi_device *device,
+			    struct display_timing *timings,
+			    unsigned int max_data_lanes,
+			    const struct mipi_dsi_phy_ops *phy_ops)
+{
+	struct samsung_dsi *dsi = dev_get_priv(dev);
+	struct udevice *dsi_bridge = device->dev;
+	enum samsung_dsim_type hw_type = (enum samsung_dsim_type)dev_get_driver_data(dsi_bridge);
+
+	dsi->max_data_lanes = max_data_lanes;
+	dsi->device = device;
+	dsi->dsi_host.ops = &samsung_dsi_host_ops;
+	dsi->driver_data = samsung_dsim_types[hw_type];
+	device->host = &dsi->dsi_host;
+
+	dsi->reg_base = (void *)dev_read_addr(device->dev);
+	if ((fdt_addr_t)dsi->reg_base == FDT_ADDR_T_NONE) {
+		dev_err(device->dev, "dsi dt register address error\n");
+		return -EINVAL;
+	}
+
+	dsi->timings = *timings;
+
+	return 0;
+}
+
+static int samsung_dsi_enable(struct udevice *dev)
+{
+	struct samsung_dsi *dsim_host = dev_get_priv(dev);
+
+	/* enable data transfer of dsim */
+	samsung_dsi_set_standby(dsim_host, true);
+
+	return 0;
+}
+
+static int samsung_dsi_disable(struct udevice *dev)
+{
+	u32 intsrc;
+	struct samsung_dsi *dsim_host = dev_get_priv(dev);
+
+	/* disable data transfer of dsim */
+	samsung_dsi_set_standby(dsim_host, false);
+
+	/* disable esc clock & byte clock & dsim pll */
+	samsung_dsi_disable_clock(dsim_host);
+
+	/* Clear all intsrc */
+	intsrc = samsung_dsim_read(dsim_host, DSIM_INTSRC_REG);
+	samsung_dsim_write(dsim_host, DSIM_INTSRC_REG, intsrc);
+
+	return 0;
+}
+
+struct dsi_host_ops samsung_dsi_ops = {
+	.init = samsung_dsi_init,
+	.enable = samsung_dsi_enable,
+	.disable = samsung_dsi_disable,
+};
+
+static int samsung_dsi_probe(struct udevice *dev)
+{
+	struct samsung_dsi *dsim_host = dev_get_priv(dev);
+	int ret;
+
+	ret = clk_get_by_name(dev, "sclk_mipi", &dsim_host->sclk_mipi);
+	if (ret)
+		debug("Failed to get sclk_mipi clock\n");
+
+	return ret;
+}
+
+static const struct udevice_id samsung_dsi_ids[] = {
+	{ .compatible = "samsung,sec-mipi-dsi" },
+	{ }
+};
+
+U_BOOT_DRIVER(samsung_dsi) = {
+	.name			= "samsung_dsi",
+	.id			= UCLASS_DSI_HOST,
+	.of_match		= samsung_dsi_ids,
+	.probe			= samsung_dsi_probe,
+	.remove			= samsung_dsi_disable,
+	.ops			= &samsung_dsi_ops,
+	.priv_auto		= sizeof(struct samsung_dsi),
+};
diff --git a/drivers/video/bridge/samsung-dsim.c b/drivers/video/bridge/samsung-dsim.c
new file mode 100644
index 000000000000..986f1d830844
--- /dev/null
+++ b/drivers/video/bridge/samsung-dsim.c
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2024 Amarula Solutions
+ * Copyright 2019 NXP
+ *
+ */
+
+#include <clk.h>
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <dsi_host.h>
+#include <mipi_dsi.h>
+#include <panel.h>
+#include <video.h>
+#include <video_bridge.h>
+#include <video_link.h>
+#include <asm/io.h>
+#include <asm/arch/gpio.h>
+#include <dm/device-internal.h>
+#include <linux/iopoll.h>
+#include <linux/err.h>
+#include <power/regulator.h>
+#include "samsung-dsim.h"
+
+struct samsung_dsim_priv {
+	struct mipi_dsi_device device;
+	void __iomem *base;
+	struct udevice *panel;
+	struct udevice *dsi_host;
+};
+
+static int samsung_dsim_attach(struct udevice *dev)
+{
+	struct samsung_dsim_priv *priv = dev_get_priv(dev);
+	struct mipi_dsi_device *device = &priv->device;
+	struct mipi_dsi_panel_plat *mplat;
+	struct display_timing timings;
+	int ret;
+
+	priv->panel = video_link_get_next_device(dev);
+	if (!priv->panel || device_get_uclass_id(priv->panel) != UCLASS_PANEL) {
+		dev_err(dev, "get panel device error\n");
+		return -ENODEV;
+	}
+
+	mplat = dev_get_plat(priv->panel);
+	mplat->device = &priv->device;
+
+	ret = video_link_get_display_timings(&timings);
+	if (ret) {
+		dev_err(dev, "decode display timing error %d\n", ret);
+		return ret;
+	}
+
+	ret = uclass_get_device(UCLASS_DSI_HOST, 0, &priv->dsi_host);
+	if (ret) {
+		dev_err(dev, "No video dsi host detected %d\n", ret);
+		return ret;
+	}
+
+	/* allow to use the compatible */
+	device->dev = dev;
+	ret = dsi_host_init(priv->dsi_host, device, &timings, 4,
+			    NULL);
+	if (ret) {
+		dev_err(dev, "failed to initialize mipi dsi host\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int samsung_dsim_set_backlight(struct udevice *dev, int percent)
+{
+	struct samsung_dsim_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	ret = panel_enable_backlight(priv->panel);
+	if (ret) {
+		dev_err(dev, "panel %s enable backlight error %d\n",
+			priv->panel->name, ret);
+		return ret;
+	}
+
+	ret = dsi_host_enable(priv->dsi_host);
+	if (ret) {
+		dev_err(dev, "failed to enable mipi dsi host\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int samsung_dsim_probe(struct udevice *dev)
+{
+	struct samsung_dsim_priv *priv = dev_get_priv(dev);
+	struct mipi_dsi_device *device = &priv->device;
+
+	device->dev = dev;
+
+	return 0;
+}
+
+static int samsung_dsim_remove(struct udevice *dev)
+{
+	struct samsung_dsim_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	if (priv->panel)
+		device_remove(priv->panel, DM_REMOVE_NORMAL);
+
+	ret = dsi_host_disable(priv->dsi_host);
+	if (ret) {
+		dev_err(dev, "failed to enable mipi dsi host\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int samsung_dsim_check_timing(struct udevice *dev, struct display_timing *timings)
+{
+	timings->flags &= ~DISPLAY_FLAGS_DE_HIGH;
+	return 0;
+}
+
+struct video_bridge_ops samsung_dsim_ops = {
+	.attach = samsung_dsim_attach,
+	.set_backlight = samsung_dsim_set_backlight,
+	.check_timing = samsung_dsim_check_timing,
+};
+
+static const struct udevice_id samsung_dsim_ids[] = {
+	{ .compatible = "fsl,imx8mm-mipi-dsim", .data = DSIM_TYPE_IMX8MM },
+	{ .compatible = "fsl,imx8mn-mipi-dsim", .data = DSIM_TYPE_IMX8MM },
+	{ }
+};
+
+U_BOOT_DRIVER(samsung_dsim) = {
+	.name				= "samsung_dsim",
+	.id				= UCLASS_VIDEO_BRIDGE,
+	.of_match			= samsung_dsim_ids,
+	.bind				= dm_scan_fdt_dev,
+	.remove				= samsung_dsim_remove,
+	.probe				= samsung_dsim_probe,
+	.ops				= &samsung_dsim_ops,
+	.priv_auto		= sizeof(struct samsung_dsim_priv),
+};
diff --git a/drivers/video/bridge/samsung-dsim.h b/drivers/video/bridge/samsung-dsim.h
new file mode 100644
index 000000000000..9bb2a379589b
--- /dev/null
+++ b/drivers/video/bridge/samsung-dsim.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2024 Amarula Solutions
+ */
+
+#ifndef SAMSUNG_DSIM_H
+#define SAMSUNG_DSIM_H
+
+enum samsung_dsim_type {
+	DSIM_TYPE_EXYNOS3250,
+	DSIM_TYPE_EXYNOS4210,
+	DSIM_TYPE_EXYNOS5410,
+	DSIM_TYPE_EXYNOS5422,
+	DSIM_TYPE_EXYNOS5433,
+	DSIM_TYPE_IMX8MM,
+	DSIM_TYPE_IMX8MP,
+	DSIM_TYPE_COUNT,
+};
+
+#endif
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 19/26] video: Add Synaptics R63353 panel driver
  2024-09-13  9:55 [PATCH 00/26] Support display (and even more) on the BSH SMM S2/PRO boards Dario Binacchi
                   ` (17 preceding siblings ...)
  2024-09-13  9:56 ` [PATCH 18/26] video: bridge: Add Samsung DSIM bridge Dario Binacchi
@ 2024-09-13  9:56 ` Dario Binacchi
  2024-09-13  9:56 ` [PATCH 20/26] imx8mn_bsh_smm_s2/pro: Enable display on reference design Dario Binacchi
                   ` (7 subsequent siblings)
  26 siblings, 0 replies; 48+ messages in thread
From: Dario Binacchi @ 2024-09-13  9:56 UTC (permalink / raw)
  To: u-boot
  Cc: Fabio Estevam, linux-amarula, michael, Miquel Raynal,
	Dario Binacchi, Anatolij Gustschin, Anton Bambura,
	Jonas Schwöbel, Simon Glass, Svyatoslav Ryhel, Tom Rini,
	Ye Li

From: Michael Trimarchi <michael@amarulasolutions.com>

The LS068B3SX02 panel is based on the Synaptics R63353 Controller.
Add a driver for it.

Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---

 drivers/video/Kconfig            |   8 ++
 drivers/video/Makefile           |   1 +
 drivers/video/synaptics-r63353.c | 228 +++++++++++++++++++++++++++++++
 3 files changed, 237 insertions(+)
 create mode 100644 drivers/video/synaptics-r63353.c

diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index cafdc15f9fe2..520577976571 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -627,6 +627,14 @@ config VIDEO_LCD_SSD2828_RESET
 	The reset pin of SSD2828 chip. This takes a string in the format
 	understood by 'sunxi_name_to_gpio' function, e.g. PH1 for pin 1 of port H.
 
+config VIDEO_LCD_SYNAPTICS_R63353
+	tristate "Synaptics R63353-based DSI LCD panels support"
+	select VIDEO_MIPI_DSI
+	default n
+	help
+	  Say Y if you want to enable support for panels based on the
+	  Synaptics R63353 controller.
+
 config VIDEO_LCD_TDO_TL070WSH30
 	bool "TDO TL070WSH30 DSI LCD panel support"
 	select VIDEO_MIPI_DSI
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 9fd3645994f1..4d836efcfa41 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -66,6 +66,7 @@ obj-$(CONFIG_VIDEO_LCD_RENESAS_R61307) += renesas-r61307.o
 obj-$(CONFIG_VIDEO_LCD_RENESAS_R69328) += renesas-r69328.o
 obj-$(CONFIG_VIDEO_LCD_SAMSUNG_LTL106HL02) += samsung-ltl106hl02.o
 obj-$(CONFIG_VIDEO_LCD_SSD2828) += ssd2828.o
+obj-$(CONFIG_VIDEO_LCD_SYNAPTICS_R63353) += synaptics-r63353.o
 obj-$(CONFIG_VIDEO_LCD_TDO_TL070WSH30) += tdo-tl070wsh30.o
 obj-$(CONFIG_VIDEO_MCDE_SIMPLE) += mcde_simple.o
 obj-${CONFIG_VIDEO_MESON} += meson/
diff --git a/drivers/video/synaptics-r63353.c b/drivers/video/synaptics-r63353.c
new file mode 100644
index 000000000000..86d2aea346b2
--- /dev/null
+++ b/drivers/video/synaptics-r63353.c
@@ -0,0 +1,228 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Synaptics R63353 Controller driver
+ *
+ * Copyright (C) 2020 BSH Hausgerate GmbH
+ */
+
+#include <backlight.h>
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <mipi_dsi.h>
+#include <panel.h>
+#include <asm/gpio.h>
+#include <linux/delay.h>
+#include <power/regulator.h>
+
+#define R63353_INSTR(...) { \
+		.len = ARRAY_SIZE(((u8[]) {__VA_ARGS__})), \
+		.data = (const u8 *)&(const u8 []){__VA_ARGS__} \
+	}
+
+struct r63353_instr {
+	size_t len;
+	const u8 * const data;
+};
+
+static const struct r63353_instr init_sequence[] = {
+	R63353_INSTR(0x51, 0xff),
+	R63353_INSTR(0x53, 0x0c),
+	R63353_INSTR(0x55, 0x00),
+	R63353_INSTR(0x84, 0x00),
+	R63353_INSTR(0x29),
+	R63353_INSTR(0x11),
+};
+
+struct r63353_panel_priv {
+	struct udevice *dvdd;
+	struct udevice *avdd;
+	struct udevice *backlight;
+	struct gpio_desc reset_gpio;
+};
+
+static const struct display_timing default_timing = {
+	.pixelclock.typ		= 70000000,
+	.hactive.typ		= 640,
+	.hfront_porch.typ	= 35,
+	.hsync_len.typ		= 2,
+	.hback_porch.typ	= 150,
+	.vactive.typ		= 1280,
+	.vfront_porch.typ	= 2,
+	.vsync_len.typ		= 4,
+	.vback_porch.typ	= 1,
+	.flags = DISPLAY_FLAGS_DE_LOW,
+};
+
+static int r63353_panel_enable_backlight(struct udevice *dev)
+{
+	struct r63353_panel_priv *priv = dev_get_priv(dev);
+	struct mipi_dsi_panel_plat *plat = dev_get_plat(dev);
+	struct mipi_dsi_device *dsi = plat->device;
+	int i, ret;
+
+	ret = mipi_dsi_attach(dsi);
+	if (ret < 0)
+		return ret;
+
+	ret = mipi_dsi_dcs_soft_reset(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to do Software Reset (%d)\n", ret);
+		goto fail;
+	}
+
+	mdelay(20);
+
+	ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enter sleep mode (%d)\n", ret);
+		goto fail;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(init_sequence); i++) {
+		const struct r63353_instr *instr = &init_sequence[i];
+
+		ret = mipi_dsi_dcs_write_buffer(dsi, instr->data, instr->len);
+		if (ret < 0)
+			goto fail;
+	}
+
+	mdelay(120);
+
+	ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to exit sleep mode (%d)\n", ret);
+		goto fail;
+	}
+
+	mdelay(10);
+
+	/* This call starts sending the data on the display (LINUX LOGO) */
+	ret = mipi_dsi_dcs_set_display_on(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set display ON (%d)\n", ret);
+		goto fail;
+	}
+
+	ret = backlight_enable(priv->backlight);
+	if (ret)
+		return ret;
+
+	return 0;
+
+fail:
+	dm_gpio_set_value(&priv->reset_gpio, 0);
+
+	return ret;
+}
+
+static int r63353_panel_get_display_timing(struct udevice *dev,
+					   struct display_timing *timing)
+{
+	struct mipi_dsi_panel_plat *plat = dev_get_plat(dev);
+	struct mipi_dsi_device *device = plat->device;
+
+	memcpy(timing, &default_timing, sizeof(*timing));
+
+	/* fill characteristics of DSI data link */
+	if (device) {
+		device->lanes = plat->lanes;
+		device->format = plat->format;
+		device->mode_flags = plat->mode_flags;
+	}
+
+	return 0;
+}
+
+static int r63353_panel_of_to_plat(struct udevice *dev)
+{
+	struct r63353_panel_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	ret = device_get_supply_regulator(dev, "dvdd-supply", &priv->dvdd);
+	if (ret) {
+		dev_err(dev, "failed to get power dvdd supply\n");
+		return ret;
+	}
+
+	ret = device_get_supply_regulator(dev, "avdd-supply", &priv->avdd);
+	if (ret) {
+		dev_err(dev, "failed to get power avdd supply\n");
+		return ret;
+	}
+
+	ret = gpio_request_by_name(dev, "reset-gpios", 0, &priv->reset_gpio,
+				   GPIOD_IS_OUT);
+	if (ret) {
+		dev_err(dev, "failed to get RESET GPIO\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int r63353_panel_probe(struct udevice *dev)
+{
+	struct r63353_panel_priv *priv = dev_get_priv(dev);
+	struct mipi_dsi_panel_plat *plat = dev_get_plat(dev);
+	int ret;
+
+	ret = regulator_set_enable(priv->avdd, true);
+	if (ret) {
+		dev_err(dev, "Failed to enable avdd regulator (%d)\n", ret);
+		return ret;
+	}
+
+	mdelay(25);
+
+	ret = regulator_set_enable(priv->dvdd, true);
+	if (ret) {
+		dev_err(dev, "Failed to enable dvdd regulator (%d)\n", ret);
+		regulator_set_enable(priv->avdd, false);
+		return ret;
+	}
+
+	dm_gpio_set_value(&priv->reset_gpio, 0);
+	mdelay(10);
+	dm_gpio_set_value(&priv->reset_gpio, 1);
+	mdelay(120);
+
+	/* fill characteristics of DSI data link */
+	plat->lanes = 2;
+	plat->format = MIPI_DSI_FMT_RGB888;
+	plat->mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO |
+		MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM |
+		MIPI_DSI_MODE_VIDEO_SYNC_PULSE | MIPI_DSI_MODE_EOT_PACKET;
+
+	ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev,
+					   "backlight", &priv->backlight);
+	if (ret) {
+		dev_err(dev, "%s: Warning: cannot get backlight: ret=%d\n",
+			__func__, ret);
+		if (ret != -ENOENT)
+			return ret;
+	}
+
+	return 0;
+}
+
+static const struct panel_ops r63353_panel_ops = {
+	.enable_backlight = r63353_panel_enable_backlight,
+	.get_display_timing = r63353_panel_get_display_timing,
+};
+
+static const struct udevice_id r63353_panel_ids[] = {
+	{ .compatible = "syna,r63353" },
+	{ .compatible = "sharp,ls068b3sx02" },
+	{ } /* sentinel */
+};
+
+U_BOOT_DRIVER(r63353_panel) = {
+	.name = "r63353_panel",
+	.id = UCLASS_PANEL,
+	.of_match = r63353_panel_ids,
+	.ops = &r63353_panel_ops,
+	.of_to_plat = r63353_panel_of_to_plat,
+	.probe = r63353_panel_probe,
+	.plat_auto = sizeof(struct mipi_dsi_panel_plat),
+	.priv_auto = sizeof(struct r63353_panel_priv),
+};
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 20/26] imx8mn_bsh_smm_s2/pro: Enable display on reference design
  2024-09-13  9:55 [PATCH 00/26] Support display (and even more) on the BSH SMM S2/PRO boards Dario Binacchi
                   ` (18 preceding siblings ...)
  2024-09-13  9:56 ` [PATCH 19/26] video: Add Synaptics R63353 panel driver Dario Binacchi
@ 2024-09-13  9:56 ` Dario Binacchi
  2024-09-13  9:56 ` [PATCH 21/26] boot: fdt_simplefb: add a debug message Dario Binacchi
                   ` (6 subsequent siblings)
  26 siblings, 0 replies; 48+ messages in thread
From: Dario Binacchi @ 2024-09-13  9:56 UTC (permalink / raw)
  To: u-boot
  Cc: Fabio Estevam, linux-amarula, michael, Miquel Raynal,
	Dario Binacchi, Fabio Estevam, Marcel Ziswiler,
	NXP i.MX U-Boot Team, Patrick Barsanti, Sean Anderson,
	Simon Glass, Stefano Babic, Svyatoslav Ryhel, Tom Rini

From: Michael Trimarchi <michael@amarulasolutions.com>

Co-developed-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
---

 .../dts/imx8mn-bsh-smm-s2-u-boot-common.dtsi  | 23 +++++++++++++++++++
 configs/imx8mn_bsh_smm_s2_defconfig           | 15 ++++++++++++
 configs/imx8mn_bsh_smm_s2pro_defconfig        | 15 ++++++++++++
 3 files changed, 53 insertions(+)

diff --git a/arch/arm/dts/imx8mn-bsh-smm-s2-u-boot-common.dtsi b/arch/arm/dts/imx8mn-bsh-smm-s2-u-boot-common.dtsi
index 19b0d8977539..8cae580e2851 100644
--- a/arch/arm/dts/imx8mn-bsh-smm-s2-u-boot-common.dtsi
+++ b/arch/arm/dts/imx8mn-bsh-smm-s2-u-boot-common.dtsi
@@ -6,6 +6,19 @@
 
 #include "imx8mn-u-boot.dtsi"
 
+/ {
+	aliases {
+		display0 = &lcdif;
+	};
+
+	samsung_dsi_host: dsi-host {
+		compatible = "samsung,sec-mipi-dsi";
+		clocks = <&clk IMX8MN_CLK_DSI_PHY_REF>;
+		clock-names = "sclk_mipi";
+		status = "okay";
+	};
+};
+
 &{/soc@0/bus@30800000/i2c@30a20000/pmic@4b} {
 	bootph-pre-ram;
 };
@@ -30,6 +43,16 @@
 	bootph-pre-ram;
 };
 
+&lcdif {
+	display = <&display0>;
+
+	/* panel is r8g8b8 */
+	display0: display@0 {
+		bits-per-pixel = <24>;
+		bits-per-color = <8>;
+	};
+};
+
 &pinctrl_i2c1 {
 	bootph-pre-ram;
 };
diff --git a/configs/imx8mn_bsh_smm_s2_defconfig b/configs/imx8mn_bsh_smm_s2_defconfig
index b4351a392eff..2fa8bc22747e 100644
--- a/configs/imx8mn_bsh_smm_s2_defconfig
+++ b/configs/imx8mn_bsh_smm_s2_defconfig
@@ -56,6 +56,7 @@ CONFIG_SYS_PROMPT="> "
 CONFIG_CMD_FUSE=y
 CONFIG_CMD_USB=y
 CONFIG_CMD_USB_MASS_STORAGE=y
+CONFIG_CMD_BMP=y
 CONFIG_CMD_MTDPARTS=y
 CONFIG_MTDIDS_DEFAULT="nand0=gpmi-nand"
 CONFIG_MTDPARTS_DEFAULT="gpmi-nand:64m(nandboot),16m(nandfit),32m(nandkernel),1m(nanddtb),8m(nandtee),-(nandrootfs)"
@@ -74,6 +75,8 @@ CONFIG_FASTBOOT_BUF_ADDR=0x40480000
 CONFIG_FASTBOOT_BUF_SIZE=0x20000000
 CONFIG_FASTBOOT_FLASH=y
 CONFIG_FASTBOOT_UUU_SUPPORT=y
+CONFIG_DM_GPIO_LOOKUP_LABEL=y
+CONFIG_SPL_DM_GPIO_LOOKUP_LABEL=y
 CONFIG_MXC_GPIO=y
 CONFIG_DM_I2C=y
 # CONFIG_MMC is not set
@@ -94,12 +97,17 @@ CONFIG_MII=y
 CONFIG_PINCTRL=y
 CONFIG_SPL_PINCTRL=y
 CONFIG_PINCTRL_IMX8M=y
+CONFIG_POWER_DOMAIN=y
+CONFIG_IMX8M_POWER_DOMAIN=y
+CONFIG_IMX8M_BLK_CTRL=y
 CONFIG_DM_PMIC=y
 CONFIG_DM_PMIC_BD71837=y
 CONFIG_SPL_DM_PMIC_BD71837=y
 CONFIG_DM_REGULATOR=y
 CONFIG_DM_REGULATOR_FIXED=y
 CONFIG_DM_REGULATOR_GPIO=y
+CONFIG_DM_PWM=y
+CONFIG_PWM_IMX=y
 CONFIG_DM_SERIAL=y
 CONFIG_MXC_UART=y
 CONFIG_SYSRESET=y
@@ -112,5 +120,12 @@ CONFIG_USB_GADGET_MANUFACTURER="FSL"
 CONFIG_USB_GADGET_VENDOR_NUM=0x0525
 CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
 CONFIG_CI_UDC=y
+CONFIG_VIDEO=y
+CONFIG_VIDEO_LCD_SYNAPTICS_R63353=y
+CONFIG_VIDEO_BRIDGE_SAMSUNG_DSIM=y
+CONFIG_VIDEO_MXS=y
+CONFIG_BMP_16BPP=y
+CONFIG_BMP_24BPP=y
+CONFIG_BMP_32BPP=y
 CONFIG_IMX_WATCHDOG=y
 # CONFIG_FAT_WRITE is not set
diff --git a/configs/imx8mn_bsh_smm_s2pro_defconfig b/configs/imx8mn_bsh_smm_s2pro_defconfig
index 0faa3376fd3d..b6b62b9d53f9 100644
--- a/configs/imx8mn_bsh_smm_s2pro_defconfig
+++ b/configs/imx8mn_bsh_smm_s2pro_defconfig
@@ -53,6 +53,7 @@ CONFIG_CMD_FUSE=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_USB=y
 CONFIG_CMD_USB_MASS_STORAGE=y
+CONFIG_CMD_BMP=y
 CONFIG_OF_CONTROL=y
 CONFIG_SPL_OF_CONTROL=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
@@ -68,6 +69,8 @@ CONFIG_FASTBOOT_BUF_SIZE=0x20000000
 CONFIG_FASTBOOT_FLASH=y
 CONFIG_FASTBOOT_UUU_SUPPORT=y
 CONFIG_FASTBOOT_FLASH_MMC_DEV=0
+CONFIG_DM_GPIO_LOOKUP_LABEL=y
+CONFIG_SPL_DM_GPIO_LOOKUP_LABEL=y
 CONFIG_MXC_GPIO=y
 CONFIG_DM_I2C=y
 CONFIG_SUPPORT_EMMC_BOOT=y
@@ -83,12 +86,17 @@ CONFIG_MII=y
 CONFIG_PINCTRL=y
 CONFIG_SPL_PINCTRL=y
 CONFIG_PINCTRL_IMX8M=y
+CONFIG_POWER_DOMAIN=y
+CONFIG_IMX8M_POWER_DOMAIN=y
+CONFIG_IMX8M_BLK_CTRL=y
 CONFIG_DM_PMIC=y
 CONFIG_DM_PMIC_BD71837=y
 CONFIG_SPL_DM_PMIC_BD71837=y
 CONFIG_DM_REGULATOR=y
 CONFIG_DM_REGULATOR_FIXED=y
 CONFIG_DM_REGULATOR_GPIO=y
+CONFIG_DM_PWM=y
+CONFIG_PWM_IMX=y
 CONFIG_DM_SERIAL=y
 CONFIG_MXC_UART=y
 CONFIG_SYSRESET=y
@@ -101,5 +109,12 @@ CONFIG_USB_GADGET_MANUFACTURER="FSL"
 CONFIG_USB_GADGET_VENDOR_NUM=0x0525
 CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
 CONFIG_CI_UDC=y
+CONFIG_VIDEO=y
+CONFIG_VIDEO_LCD_SYNAPTICS_R63353=y
+CONFIG_VIDEO_BRIDGE_SAMSUNG_DSIM=y
+CONFIG_VIDEO_MXS=y
+CONFIG_BMP_16BPP=y
+CONFIG_BMP_24BPP=y
+CONFIG_BMP_32BPP=y
 CONFIG_IMX_WATCHDOG=y
 # CONFIG_FAT_WRITE is not set
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 21/26] boot: fdt_simplefb: add a debug message
  2024-09-13  9:55 [PATCH 00/26] Support display (and even more) on the BSH SMM S2/PRO boards Dario Binacchi
                   ` (19 preceding siblings ...)
  2024-09-13  9:56 ` [PATCH 20/26] imx8mn_bsh_smm_s2/pro: Enable display on reference design Dario Binacchi
@ 2024-09-13  9:56 ` Dario Binacchi
  2024-09-13  9:56 ` [PATCH 22/26] video: mxsfb: support simple frame-buffer Dario Binacchi
                   ` (5 subsequent siblings)
  26 siblings, 0 replies; 48+ messages in thread
From: Dario Binacchi @ 2024-09-13  9:56 UTC (permalink / raw)
  To: u-boot
  Cc: Fabio Estevam, linux-amarula, michael, Miquel Raynal,
	Dario Binacchi, Devarsh Thakkar, Nikhil M Jain, Simon Glass,
	Tom Rini

The printed information is useful when adding support for the simple
frame buffer to a board.

Co-developed-by: Michael Trimarchi <michael@amarulasolutions.com>
Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---

 boot/fdt_simplefb.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/boot/fdt_simplefb.c b/boot/fdt_simplefb.c
index 53415548459a..22aaad9d5c5b 100644
--- a/boot/fdt_simplefb.c
+++ b/boot/fdt_simplefb.c
@@ -61,6 +61,8 @@ static int fdt_simplefb_configure_node(void *blob, int off)
 		return -EINVAL;
 	}
 
+	debug("Simple frame buffer at 0x%lx, pixels %dx%d, format %s\n",
+	      fb_base, xsize, ysize, name);
 	return fdt_setup_simplefb_node(blob, off, fb_base, xsize, ysize,
 				       xsize * (1 << bpix) / 8, name);
 }
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 22/26] video: mxsfb: support simple frame-buffer
  2024-09-13  9:55 [PATCH 00/26] Support display (and even more) on the BSH SMM S2/PRO boards Dario Binacchi
                   ` (20 preceding siblings ...)
  2024-09-13  9:56 ` [PATCH 21/26] boot: fdt_simplefb: add a debug message Dario Binacchi
@ 2024-09-13  9:56 ` Dario Binacchi
  2024-09-13  9:56 ` [PATCH 23/26] video: bridge: samsung: " Dario Binacchi
                   ` (4 subsequent siblings)
  26 siblings, 0 replies; 48+ messages in thread
From: Dario Binacchi @ 2024-09-13  9:56 UTC (permalink / raw)
  To: u-boot
  Cc: Fabio Estevam, linux-amarula, michael, Miquel Raynal,
	Dario Binacchi, Anatolij Gustschin, Peter Robinson,
	Sébastien Szymanski, Tom Rini, Ye Li

If you want to pass the frame-buffer to the kernel, the video output is
initialized by U-Boot, and kept by the kernel. The patch does not turn
off the power domains or reset the peripheral if you want to support
such feature.

Co-developed-by: Michael Trimarchi <michael@amarulasolutions.com>
Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---

 drivers/video/mxsfb.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c
index 45431f0a1047..06b2a2461246 100644
--- a/drivers/video/mxsfb.c
+++ b/drivers/video/mxsfb.c
@@ -422,7 +422,8 @@ static int mxs_video_remove(struct udevice *dev)
 	if (priv->disp_dev)
 		device_remove(priv->disp_dev, DM_REMOVE_NORMAL);
 
-	mxs_remove_common(priv->reg_base, plat->base);
+	if (!IS_ENABLED(CONFIG_VIDEO_DT_SIMPLEFB))
+		mxs_remove_common(priv->reg_base, plat->base);
 
 	return 0;
 }
@@ -445,6 +446,10 @@ U_BOOT_DRIVER(mxs_video) = {
 	.bind	= mxs_video_bind,
 	.probe	= mxs_video_probe,
 	.remove = mxs_video_remove,
+#if !IS_ENABLED(CONFIG_VIDEO_DT_SIMPLEFB)
 	.flags	= DM_FLAG_PRE_RELOC | DM_FLAG_OS_PREPARE,
+#else
+	.flags	= DM_FLAG_PRE_RELOC | DM_FLAG_OS_PREPARE | DM_FLAG_LEAVE_PD_ON,
+#endif
 	.priv_auto   = sizeof(struct mxsfb_priv),
 };
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 23/26] video: bridge: samsung: support simple frame-buffer
  2024-09-13  9:55 [PATCH 00/26] Support display (and even more) on the BSH SMM S2/PRO boards Dario Binacchi
                   ` (21 preceding siblings ...)
  2024-09-13  9:56 ` [PATCH 22/26] video: mxsfb: support simple frame-buffer Dario Binacchi
@ 2024-09-13  9:56 ` Dario Binacchi
  2024-09-13  9:56 ` [PATCH 24/26] imx8mn_bsh_smm_s2/pro: " Dario Binacchi
                   ` (3 subsequent siblings)
  26 siblings, 0 replies; 48+ messages in thread
From: Dario Binacchi @ 2024-09-13  9:56 UTC (permalink / raw)
  To: u-boot
  Cc: Fabio Estevam, linux-amarula, michael, Miquel Raynal,
	Dario Binacchi, Anatolij Gustschin, Minkyu Kang, Tom Rini

If you want to pass the frame-buffer to the kernel, the video output is
initialized by U-Boot, and kept by the kernel. The patch does not turn
off the power domains or disable the peripheral if you want to support
such feature.

Co-developed-by: Michael Trimarchi <michael@amarulasolutions.com>
Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---

 drivers/video/bridge/samsung-dsi-host.c | 9 +++++++++
 drivers/video/bridge/samsung-dsim.c     | 3 +++
 2 files changed, 12 insertions(+)

diff --git a/drivers/video/bridge/samsung-dsi-host.c b/drivers/video/bridge/samsung-dsi-host.c
index dd3e33c4edc7..2d0e8f71a756 100644
--- a/drivers/video/bridge/samsung-dsi-host.c
+++ b/drivers/video/bridge/samsung-dsi-host.c
@@ -1281,6 +1281,7 @@ static void samsung_dsi_set_standby(struct samsung_dsi *dsim, bool standby)
 	samsung_dsim_write(dsim, DSIM_MDRESOL_REG, mdresol);
 }
 
+#if (!IS_ENABLED(CONFIG_VIDEO_DT_SIMPLEFB))
 static void samsung_dsi_disable_clock(struct samsung_dsi *dsim)
 {
 	u32 reg;
@@ -1294,6 +1295,7 @@ static void samsung_dsi_disable_clock(struct samsung_dsi *dsim)
 	reg &= ~DSIM_PLL_EN;
 	samsung_dsim_write(dsim, DSIM_PLLCTRL_REG, reg);
 }
+#endif
 
 static inline struct samsung_dsi *host_to_dsi(struct mipi_dsi_host *host)
 {
@@ -1515,6 +1517,12 @@ static int samsung_dsi_enable(struct udevice *dev)
 	return 0;
 }
 
+#if IS_ENABLED(CONFIG_VIDEO_DT_SIMPLEFB)
+static int samsung_dsi_disable(struct udevice *dev)
+{
+	return 0;
+}
+#else
 static int samsung_dsi_disable(struct udevice *dev)
 {
 	u32 intsrc;
@@ -1532,6 +1540,7 @@ static int samsung_dsi_disable(struct udevice *dev)
 
 	return 0;
 }
+#endif
 
 struct dsi_host_ops samsung_dsi_ops = {
 	.init = samsung_dsi_init,
diff --git a/drivers/video/bridge/samsung-dsim.c b/drivers/video/bridge/samsung-dsim.c
index 986f1d830844..36e45abb3009 100644
--- a/drivers/video/bridge/samsung-dsim.c
+++ b/drivers/video/bridge/samsung-dsim.c
@@ -144,5 +144,8 @@ U_BOOT_DRIVER(samsung_dsim) = {
 	.remove				= samsung_dsim_remove,
 	.probe				= samsung_dsim_probe,
 	.ops				= &samsung_dsim_ops,
+#if IS_ENABLED(CONFIG_VIDEO_DT_SIMPLEFB)
+	.flags				= DM_FLAG_LEAVE_PD_ON,
+#endif
 	.priv_auto		= sizeof(struct samsung_dsim_priv),
 };
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 24/26] imx8mn_bsh_smm_s2/pro: support simple frame-buffer
  2024-09-13  9:55 [PATCH 00/26] Support display (and even more) on the BSH SMM S2/PRO boards Dario Binacchi
                   ` (22 preceding siblings ...)
  2024-09-13  9:56 ` [PATCH 23/26] video: bridge: samsung: " Dario Binacchi
@ 2024-09-13  9:56 ` Dario Binacchi
  2024-09-13  9:56 ` [PATCH 25/26] imx8mn_bsh_smm_s2/pro: enable " Dario Binacchi
                   ` (2 subsequent siblings)
  26 siblings, 0 replies; 48+ messages in thread
From: Dario Binacchi @ 2024-09-13  9:56 UTC (permalink / raw)
  To: u-boot
  Cc: Fabio Estevam, linux-amarula, michael, Miquel Raynal,
	Dario Binacchi, Tom Rini

If you want to pass the frame-buffer to the kernel, the video output is
initialized by U-Boot, and kept by the kernel. The commit modifies the
device tree to be passed to the kernel just before launching it, to
prevent the kernel from reinitializing hardware that has already been
configured by the bootloader.

Co-developed-by: Michael Trimarchi <michael@amarulasolutions.com>
Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---

 board/bsh/imx8mn_smm_s2/imx8mn_smm_s2.c | 99 +++++++++++++++++++++++++
 1 file changed, 99 insertions(+)

diff --git a/board/bsh/imx8mn_smm_s2/imx8mn_smm_s2.c b/board/bsh/imx8mn_smm_s2/imx8mn_smm_s2.c
index c99896873991..87eb4e7ed63e 100644
--- a/board/bsh/imx8mn_smm_s2/imx8mn_smm_s2.c
+++ b/board/bsh/imx8mn_smm_s2/imx8mn_smm_s2.c
@@ -5,6 +5,8 @@
 
 #include <asm/arch/sys_proto.h>
 #include <env.h>
+#include <fdt_simplefb.h>
+#include <fdt_support.h>
 
 int board_init(void)
 {
@@ -20,3 +22,100 @@ int board_late_init(void)
 
 	return 0;
 }
+
+#if (IS_ENABLED(CONFIG_OF_LIBFDT) && IS_ENABLED(CONFIG_FDT_SIMPLEFB) && \
+	IS_ENABLED(CONFIG_VIDEO))
+static void smm_s2_setup_simplefb(void *blob)
+{
+#define DT_BLK_CTRL_NODE_PATH "/soc@0/bus@32c00000/blk-ctrl@32e28000"
+#define DT_GPC_NODE_PATH "/soc@0/bus@30000000/gpc@303a0000"
+#define DT_MIPI_DSI_NODE_PATH "/soc@0/bus@32c00000/dsi@32e10000"
+#define DT_LCDIF_NODE_PATH "/soc@0/bus@32c00000/lcdif@32e00000"
+
+	const char *dt_addnode[][2] = {
+		{ DT_BLK_CTRL_NODE_PATH, "lcdif" },
+		{ DT_BLK_CTRL_NODE_PATH, "mipi-dsi" },
+	};
+
+	const char *dt_addprop[][2] = {
+		{ "/regulator-3v3-O2", "regulator-boot-on" },
+		{ "/regulator-3v3-O3", "regulator-boot-on" },
+		{ DT_GPC_NODE_PATH "/pgc/power-domain@3", "fsl,boot-on" },
+		{ DT_GPC_NODE_PATH "/pgc/power-domain@4", "fsl,boot-on" },
+		{ DT_BLK_CTRL_NODE_PATH "/lcdif", "fsl,boot-on" },
+		{ DT_BLK_CTRL_NODE_PATH "/mipi-dsi", "fsl,boot-on" },
+		{ DT_MIPI_DSI_NODE_PATH, "samsung,boot-on" },
+		{ DT_MIPI_DSI_NODE_PATH "/panel@0", "syna,boot-on" },
+		{ DT_LCDIF_NODE_PATH, "fsl,boot-on" },
+	};
+	const char *dt_delprop[][2] = {
+		{ DT_BLK_CTRL_NODE_PATH, "assigned-clock-rates" },
+		{ DT_GPC_NODE_PATH "/pgc/power-domain@3", "assigned-clock-rates" }, // pgc_dispmix
+		{ DT_LCDIF_NODE_PATH, "assigned-clock-rates" },
+	};
+	int i, ret, offset;
+
+	ret = fdt_simplefb_enable_and_mem_rsv(blob);
+	if (ret) {
+		printf("Failed to enable framebuffer DTS node\n");
+		return;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(dt_addnode); i++) {
+		const char *path = dt_addnode[i][0];
+		const char *node = dt_addnode[i][1];
+
+		offset = fdt_path_offset(blob, path);
+		if (offset < 0) {
+			printf("Missing node %s, err=%s\n", path,
+			       fdt_strerror(offset));
+			continue;
+		}
+
+		offset = fdt_find_or_add_subnode(blob, offset, node);
+		if (offset < 0)
+			printf("Failed to create node %s, err=%s\n", path,
+			       fdt_strerror(offset));
+		else
+			debug("Add node %s:%s\n", path, node);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(dt_addprop); i++) {
+		const char *path = dt_addprop[i][0];
+		const char *prop = dt_addprop[i][1];
+
+		ret = fdt_find_and_setprop(blob, path, prop, NULL, 0, 1);
+		if (ret < 0)
+			printf("Failed to add property %s:%s, err=%s\n", path, prop,
+			       fdt_strerror(ret));
+		else
+			debug("Add property %s:%s\n", path, prop);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(dt_delprop); i++) {
+		const char *path = dt_delprop[i][0];
+		const char *prop = dt_delprop[i][1];
+
+		offset = fdt_path_offset(blob, path);
+		if (offset < 0) {
+			printf("Missing node %s\n", path);
+			continue;
+		}
+
+		ret = fdt_delprop(blob, offset, prop);
+		if (ret < 0)
+			printf("Failed to delete property %s:%s\n", path, prop);
+		else
+			debug("Delete property %s:%s\n", path, prop);
+	}
+}
+#endif
+
+int ft_board_setup(void *blob, struct bd_info *bd)
+{
+	if (IS_ENABLED(CONFIG_OF_LIBFDT) && IS_ENABLED(CONFIG_FDT_SIMPLEFB) &&
+	    IS_ENABLED(CONFIG_VIDEO))
+		smm_s2_setup_simplefb(blob);
+
+	return 0;
+}
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 25/26] imx8mn_bsh_smm_s2/pro: enable simple frame-buffer
  2024-09-13  9:55 [PATCH 00/26] Support display (and even more) on the BSH SMM S2/PRO boards Dario Binacchi
                   ` (23 preceding siblings ...)
  2024-09-13  9:56 ` [PATCH 24/26] imx8mn_bsh_smm_s2/pro: " Dario Binacchi
@ 2024-09-13  9:56 ` Dario Binacchi
  2024-09-13  9:56 ` [PATCH 26/26] imx8mn_bsh_smm_s2/pro: add splash screen with BSH logo Dario Binacchi
  2024-09-30  9:43 ` [PATCH 00/26] Support display (and even more) on the BSH SMM S2/PRO boards Miquel Raynal
  26 siblings, 0 replies; 48+ messages in thread
From: Dario Binacchi @ 2024-09-13  9:56 UTC (permalink / raw)
  To: u-boot
  Cc: Fabio Estevam, linux-amarula, michael, Miquel Raynal,
	Dario Binacchi, Marcel Ziswiler, Patrick Barsanti, Peng Fan,
	Sean Anderson, Simon Glass, Tom Rini

Co-developed-by: Michael Trimarchi <michael@amarulasolutions.com>
Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---

 configs/imx8mn_bsh_smm_s2_defconfig    | 3 +++
 configs/imx8mn_bsh_smm_s2pro_defconfig | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/configs/imx8mn_bsh_smm_s2_defconfig b/configs/imx8mn_bsh_smm_s2_defconfig
index 2fa8bc22747e..4982b58407c6 100644
--- a/configs/imx8mn_bsh_smm_s2_defconfig
+++ b/configs/imx8mn_bsh_smm_s2_defconfig
@@ -28,7 +28,9 @@ CONFIG_FIT_EXTERNAL_OFFSET=0x3000
 CONFIG_SPL_LOAD_FIT=y
 CONFIG_SYS_BOOTM_LEN=0x2000000
 CONFIG_DISTRO_DEFAULTS=y
+CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_SYSTEM_SETUP=y
+CONFIG_FDT_SIMPLEFB=y
 CONFIG_DEFAULT_FDT_FILE="freescale/imx8mn-bsh-smm-s2.dtb"
 CONFIG_SYS_CBSIZE=2048
 CONFIG_SYS_PBSIZE=2067
@@ -124,6 +126,7 @@ CONFIG_VIDEO=y
 CONFIG_VIDEO_LCD_SYNAPTICS_R63353=y
 CONFIG_VIDEO_BRIDGE_SAMSUNG_DSIM=y
 CONFIG_VIDEO_MXS=y
+CONFIG_VIDEO_DT_SIMPLEFB=y
 CONFIG_BMP_16BPP=y
 CONFIG_BMP_24BPP=y
 CONFIG_BMP_32BPP=y
diff --git a/configs/imx8mn_bsh_smm_s2pro_defconfig b/configs/imx8mn_bsh_smm_s2pro_defconfig
index b6b62b9d53f9..7ae99adf7fad 100644
--- a/configs/imx8mn_bsh_smm_s2pro_defconfig
+++ b/configs/imx8mn_bsh_smm_s2pro_defconfig
@@ -29,7 +29,9 @@ CONFIG_FIT_EXTERNAL_OFFSET=0x3000
 CONFIG_SPL_LOAD_FIT=y
 CONFIG_SYS_BOOTM_LEN=0x2000000
 CONFIG_DISTRO_DEFAULTS=y
+CONFIG_OF_BOARD_SETUP=y
 CONFIG_OF_SYSTEM_SETUP=y
+CONFIG_FDT_SIMPLEFB=y
 CONFIG_DEFAULT_FDT_FILE="freescale/imx8mn-bsh-smm-s2pro.dtb"
 CONFIG_SYS_CBSIZE=2048
 CONFIG_SYS_PBSIZE=2067
@@ -113,6 +115,7 @@ CONFIG_VIDEO=y
 CONFIG_VIDEO_LCD_SYNAPTICS_R63353=y
 CONFIG_VIDEO_BRIDGE_SAMSUNG_DSIM=y
 CONFIG_VIDEO_MXS=y
+CONFIG_VIDEO_DT_SIMPLEFB=y
 CONFIG_BMP_16BPP=y
 CONFIG_BMP_24BPP=y
 CONFIG_BMP_32BPP=y
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH 26/26] imx8mn_bsh_smm_s2/pro: add splash screen with BSH logo
  2024-09-13  9:55 [PATCH 00/26] Support display (and even more) on the BSH SMM S2/PRO boards Dario Binacchi
                   ` (24 preceding siblings ...)
  2024-09-13  9:56 ` [PATCH 25/26] imx8mn_bsh_smm_s2/pro: enable " Dario Binacchi
@ 2024-09-13  9:56 ` Dario Binacchi
  2024-09-30  9:43 ` [PATCH 00/26] Support display (and even more) on the BSH SMM S2/PRO boards Miquel Raynal
  26 siblings, 0 replies; 48+ messages in thread
From: Dario Binacchi @ 2024-09-13  9:56 UTC (permalink / raw)
  To: u-boot
  Cc: Fabio Estevam, linux-amarula, michael, Miquel Raynal,
	Dario Binacchi, Marcel Ziswiler, Martyn Welch, Patrick Barsanti,
	Peng Fan, Sean Anderson, Simon Glass, Svyatoslav Ryhel, Tom Rini

Display the BSH logo with features VIDEO_LOGO and SPLASH_SCREEN on
imx8mn_bsh_smm_s2/pro boards.

With CONFIG_SYS_VENDOR = "bsh", the logo bsh.bmp is selected, loaded at
the address indicated by splashimage and centered with "splashpos=m,m".

Co-developed-by: Michael Trimarchi <michael@amarulasolutions.com>
Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>

---

 configs/imx8mn_bsh_smm_s2_defconfig        |   3 +++
 configs/imx8mn_bsh_smm_s2pro_defconfig     |   3 +++
 include/configs/imx8mn_bsh_smm_s2.h        |   1 +
 include/configs/imx8mn_bsh_smm_s2_common.h |   4 ++++
 include/configs/imx8mn_bsh_smm_s2pro.h     |   1 +
 tools/logos/bsh.bmp                        | Bin 0 -> 10644 bytes
 6 files changed, 12 insertions(+)
 create mode 100644 tools/logos/bsh.bmp

diff --git a/configs/imx8mn_bsh_smm_s2_defconfig b/configs/imx8mn_bsh_smm_s2_defconfig
index 4982b58407c6..b3190945c59c 100644
--- a/configs/imx8mn_bsh_smm_s2_defconfig
+++ b/configs/imx8mn_bsh_smm_s2_defconfig
@@ -123,10 +123,13 @@ CONFIG_USB_GADGET_VENDOR_NUM=0x0525
 CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
 CONFIG_CI_UDC=y
 CONFIG_VIDEO=y
+CONFIG_VIDEO_LOGO=y
 CONFIG_VIDEO_LCD_SYNAPTICS_R63353=y
 CONFIG_VIDEO_BRIDGE_SAMSUNG_DSIM=y
 CONFIG_VIDEO_MXS=y
 CONFIG_VIDEO_DT_SIMPLEFB=y
+CONFIG_SPLASH_SCREEN=y
+CONFIG_SPLASH_SCREEN_ALIGN=y
 CONFIG_BMP_16BPP=y
 CONFIG_BMP_24BPP=y
 CONFIG_BMP_32BPP=y
diff --git a/configs/imx8mn_bsh_smm_s2pro_defconfig b/configs/imx8mn_bsh_smm_s2pro_defconfig
index 7ae99adf7fad..db83a326c053 100644
--- a/configs/imx8mn_bsh_smm_s2pro_defconfig
+++ b/configs/imx8mn_bsh_smm_s2pro_defconfig
@@ -112,10 +112,13 @@ CONFIG_USB_GADGET_VENDOR_NUM=0x0525
 CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
 CONFIG_CI_UDC=y
 CONFIG_VIDEO=y
+CONFIG_VIDEO_LOGO=y
 CONFIG_VIDEO_LCD_SYNAPTICS_R63353=y
 CONFIG_VIDEO_BRIDGE_SAMSUNG_DSIM=y
 CONFIG_VIDEO_MXS=y
 CONFIG_VIDEO_DT_SIMPLEFB=y
+CONFIG_SPLASH_SCREEN=y
+CONFIG_SPLASH_SCREEN_ALIGN=y
 CONFIG_BMP_16BPP=y
 CONFIG_BMP_24BPP=y
 CONFIG_BMP_32BPP=y
diff --git a/include/configs/imx8mn_bsh_smm_s2.h b/include/configs/imx8mn_bsh_smm_s2.h
index deeed9c2f582..c8bd55fd3744 100644
--- a/include/configs/imx8mn_bsh_smm_s2.h
+++ b/include/configs/imx8mn_bsh_smm_s2.h
@@ -38,6 +38,7 @@
 #define CFG_EXTRA_ENV_SETTINGS \
 	MEM_LAYOUT_ENV_SETTINGS \
 	NANDARGS \
+	SPLASH_ENV_SETTINGS \
 	BOOTENV
 
 #define PHYS_SDRAM_SIZE			SZ_256M
diff --git a/include/configs/imx8mn_bsh_smm_s2_common.h b/include/configs/imx8mn_bsh_smm_s2_common.h
index 204fc4b31647..5d6b22e04139 100644
--- a/include/configs/imx8mn_bsh_smm_s2_common.h
+++ b/include/configs/imx8mn_bsh_smm_s2_common.h
@@ -21,6 +21,10 @@
 	"fdtfile=" CONFIG_DEFAULT_FDT_FILE "\0" \
 	"bootcmd_mfg=echo Running fastboot mode; fastboot usb 0\0" \
 
+#define SPLASH_ENV_SETTINGS \
+	"splashimage=0x5bb00000\0" \
+	"splashpos=m,m\0" \
+
 /* Link Definitions */
 
 #define CFG_SYS_INIT_RAM_ADDR	0x40000000
diff --git a/include/configs/imx8mn_bsh_smm_s2pro.h b/include/configs/imx8mn_bsh_smm_s2pro.h
index 8619fdde7fdb..dd26e0b885d2 100644
--- a/include/configs/imx8mn_bsh_smm_s2pro.h
+++ b/include/configs/imx8mn_bsh_smm_s2pro.h
@@ -25,6 +25,7 @@
 #define CFG_EXTRA_ENV_SETTINGS \
 	MEM_LAYOUT_ENV_SETTINGS \
 	EMMCARGS \
+	SPLASH_ENV_SETTINGS \
 	BOOTENV
 
 #define PHYS_SDRAM_SIZE			SZ_512M
diff --git a/tools/logos/bsh.bmp b/tools/logos/bsh.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..5b6fb1ebd50d70c7f5ce4a51042271e9634d8d81
GIT binary patch
literal 10644
zcmeI2eOy%4)_~XQUh}nk@sis0dX-ZAhBT2#Ny(20Qj*A^GBYuaRLsZ-%1<&s((=``
zt{GWmp;?v|R#;eMWQ9c*Rv1NP)bu?~Uz643efB<w!I|d&_x(eD&JWJsXFY4Jeb!!k
ztuu}ucSnD*KP&$#GM~Q&9VfCzMO6NWkH`tVMP6+0eC&W3lp`(w?8WHx@z<5?`Ke!S
z<;f>?U;34fOib)pl9$(KWM1C!Wg9lM8-BvOf9ZAE>cQsbmLJrG{B%F1r}XIFOJaNU
zmY%VFq-W1Q(yM1*>D{ZJ^y%GS`u2&FetqMmf4@^Du0Nl+0TLfKP)?0MO$MAgNCpl_
zkkbYZmO-Z_O2QyM38%~8gd|BEe1@E!I7E_8A1Y@gCCiXAl4a<SGiB(|VUj#_xSW}s
zBE!x+ONI{{At}R0$XO{PWyD#dWW<QkGIGS(GHPV1j2?B4oIN^CQqNA4b5heK?VNKZ
zEp3dXr;n9$(=%kux#!8)G3QCf*l}`RMy8BA?|d0IE=w{qFOc&y$4l1v<K=>^3uXKT
z*>d6d9Lc`$BFWCaSaNbMk&F0Te9;8C<l;+Z!X*>s(g~Nz#7ig1#EF;7WtUBsNqjD!
zlq-`jpCY-FuaGIZQ{{>&)8vXPu9T@$uas%i^5n{CS4rNL)8(qX88ZE<nKEN~zRZ}B
zFEeM(lKlLuWmf)dxq8+$GW+TRxn}mYQgF>2DJYmD*Is*_%$ZXt*Uh<J3a=}Y>kEse
z==vL^xQI{jjdH^cbLGYx=gHg~=gYjg3uOMhg|cA&LRq+Akt|$TB8wK?Bqb$_<))i%
zmc=(Mk((DUktH`Tm8DCT$<n3EW!bV@Wcl(Ha?33%WyLMG%E}eD%B?GJliO}xCAZ!7
zzp`r8YFWMdc3H#c_BCr|?d|Ji-P${3-MTyFjywJ%ciy>P*8k@&xoiCf*>Kn0a`%Q(
zx%=*Wq_lLS+;h*pvT@_Ra_`3b<i2~$r0l-?<^Hlwa{v7g$fivX$^#EPC=WhZF6HH$
zWpnu!*|PZ|d1%X4dFY{sW$V_5<>7}Pkw+fcCfl|>Dvxe^Odfl5yKH}Khiu=zLw4+V
zTpoY?33=j)3aO~rDLX5klqYvSB~Ly1v^@3H)AIDwl~P%`OLpygMxJ@*S$X!EDye#Q
zx9qOsv->%D?z!jX`RA*py7~oq;e|c2XU~iBBA=QUYow;;C3)$ky|Q=j%kuKeugEK}
zyehB0S}V1D_SNo_efwUM*Is*FUVpt#>gwK*H{RGU`}gmcH}}6OZ@u}Jy!BSS)Yl)7
z0|(xgx8Ht8-g)O8dH3CSrQzKMIoNPe4jz0@-g~c68XMo2_uqeCKKS4RX=-Yc51T%e
zk3RfJKKkfm`S{~Qa_G<}^2sNkNON<ueER99^4VvfiRUwqcs!rW=bwKeUwrX}eEH><
z^3_*g$=6?hE#G|ejePsfxAN_`Uh#Up^4)jeiO=Vg@4x?Ee)!=B`SHge<)<HilAnJ1
zS$_WcXYu>}^2;y3$l=3><=0<-mEV5*jnD7$`|rO?AP|s0{`f<V93hXmKSu&b0)qpj
zm1Dn;t;4Z6IJOV|kMqET0rekWs}1=9_3^uLK|nqH_S{BnmIpMpjc7;p&*U!c#NWM{
zuRC5e*PUO?-&>KL#qVn761XQyeYZN&hg7*9!~8zxr!v2q-=$`Db3oIXQ*C0_m70%k
zZOiB|_l_;xy@Yuyg>(+r4J#dK$DUYb9hu?GS2AC0=C`;OF>7U*i-Frk53g`$tq;uZ
zG!o3t<9CIbdnllTxid<=DFJQPI^Crey7jnn-Ksluj~-NCY(Tpi7E%YTe_5{FS{NIK
z1higDwNTTvo9f?1WB6;H?o?k)K<64Q$fY3PRz0_%Z(5*Bq9*?(RWmh5C+I9K(RJvm
z*5;F2JWEbAmaNlk?etG0m!W0q`*(}>?7;zDc|wjZ?-|hYzvZa!9|0{x&nk!BN3<&v
zi?p_DKrd$ez-flNR#Q~FiAHOI9_kXbD1r4lK{ONAg1?D+VEME?*2X)uIO9*D*8R&_
z>!JYxt<_v@*TdK~TRoj!-Qk?*fKEks?Q-k!sph$7YAtuWPbDtEIuFOz4!Z82MrRZ{
z2S%XOK$+oCP7_wda}t&^w!L3Kt27z=Qni^et8Gx2Hzx+PFWhMLEwgqEG7(YPDWHw^
zIcD}Te`O62?W7fq8eRDj7|R(icL)i_la<^%3T_*1?iJ82+7`=H*E8y9^Rwb1tBM`X
zR%5C|NhHcU26PkL6%d-VU1t-4(b^sRqEB*Wt=4c-hk$0FS+#Mg_2_g6jQKR0(YW5k
zb+jRk)H%e=9?1UV&Fn!UY%X!x<{!if_dC|4MWAoPrbP~$c*r<0hc!>tB<-(VI~cuH
zNKfaU8tnFI7veoui+B=#eDvsY?Gk0~+7Yy~X<*n|Fyrjx?m;b0M1U8@3gWhHd(qC?
z3~eu3^6+RwI}>Y@bT`rC)#-MRMQH<f7+Xui`K;?4#;cat^}&ZGc8*t<X(uepM0-3d
z)n0v&2XbE&QQX8%sn)Lek_^?cu15rJJ@-#&<#sb3PlQ^H)Jo>cU{?Os_&>?+=0h3}
za}~1%#v=AkNK_CnN!Zd(y*CGKB?l}+W(YDKZNuzHVl?A8(FCpOVaEF6QM7v5U&fkA
z5t!>4U*AeRC7^{6s~~2<BXY3v04usc{p|V%je=OhtZU1uf40)A?T}0gVfr-zxyi`w
zK;HtaZ056`u@36PI%`EZi+wtgyXzMR{q4?*A;SrR%wg?<o|sIY3}fYtIGTq<;8ekx
z)5>9O;*r^kJw?n^jtgih*I8UoFdE~-ydvVdqpOqpZwlH1V;(Yv$TT361H-3n$&PKU
zbw*=h1kNJHw}nu4LK#M+4MPK2A5JPGHE@m2&gv)og+v0@G}-)+5yJ7RqCE;yDLU4`
zDTK2I&O)OzoWlM{g|FIN67-3)s|zwdWSktE0A(E`QyFoyU<6J%{N*7O6L(EmlFLlp
zdE_pxv$%FO_7C$2Tl_XB^$npUBUOh~HI!LU%D7J9+UQ#m&fv_M!FbK0qrFK(;sATR
zH=cG-e?~x8Fp>zv$$|YNP->w}4WSH0rU}XtW;Vl^ZS3IMW;RZikf+0GX>tZJy6|XA
zdh={l{YW`gPZ}H(x0#F>jd>9`s~9h9r4Vt4H407)J7cVUc1>e!c7{_xesFVD-#=UA
z)IcdAtXiZ}A#FuV37mQCdvhvTt>Fx^;&`j^;DVr6*s~hOLKtqfb*{-dQE>LdaWYa$
z1X2YW=Y?>Fz^NjxZRSf4Xf}+FT)R1lToJOySmW&eZmkq@!+t1KqsW>1ZBiOfjC?zV
zYopO*oe&CnyqNLI`9Y6hjE6CuSTgyIDle5>tqP?QikopFa2o7>%xNW&M|VL|TMMm2
z%lgq~m1c2X#X`4Phs+vc4=0411Lg%SBEvUpH%OVpm7Cv2aoXuX&gM0cZ0?CbvN@oY
zLv`uZB*!9F&t|!^%%09ug%qQH_{sQ82I8y^x6922tvqZ!sBt`{Vpee%{uK_Vil;)=
z6UoJBF#6Yqld!^Ogt<ZgxYJJ^5Dh6o{ZQRJJJj$OYg|XF3N*O-Bk*i)XyuVfJX%Se
zY$}Ux+Jr`%{gRAz3pIgiDMmf$nT&mPoM<7Qvf6H@xUt2;P0_n_n{K8eF43tvTsu)Q
zb=ErWbn;<Fg7KhI^EJj+WwmHDHqDN}Hu+<VLmn*JR~v~pHzN)(K5o`aG`fp<29?B*
z+gp*7jg6^28#SNj=RvcRLDC%(H70c~d(mcLva?sqHA~xdHSt@82BUSWp`3{{+%a|^
zH{D=8q!#U>W!UQE!@gvpN~GJy(93BZROh5gKT6)@i^Y!g03*HJR!27X@_fAPm)<9v
z$j?<TT(^sZ)S}<b6%HZJ<mF4W0=+ixqQ^%!5_O8`P^}`ajkYB%(s(nQ>*``_dq49e
zwsYFM`IgxVjX`phR*`l5+7VA<kCHW6VX`CJ->mXv-OqZNe7BKRJxmp>_#LfNw1#op
zv%<7?Lvj1QBC9*zcsNNt*zM+4p1WVO=$YIO47-fJ+@lD#19aqBxoF*hbhdpO4MgPF
zf14+k&C~M^3iiA_uNM7|o@7U!NT_b#NM%;5HS`oK@ue@hC0G4qCzI{WzMS<hlMi!s
zyZRCXYP6TO@K|Tl?KNEA66Z~1@kVx>scVze1EnjLb!C5Ur>l%%M^)+JGg`b&HXNcd
zspnRkF+K21cU{!VV<(y?*#=9K)XS4Jxwe9g<<-vY>dsWsdxt?WR<QaZ`;fSCJHNu9
zedMRz+6meySWdpphE`0zQ96Ojvs?=zuuKQIqm_hDd$ld3Wsuxno9yn@C^DhaGc=3}
z>gTD3TjuQhtX3W?eHXO0T2K6MMAs^4D`2H+{n<|cSrN|R&XKHd8}(cl^pF@ZRdP0S
zZifpefjrhm*PhdoZ?Yng%FwwogtHwEwL2u+>2ex3!HLq{oUO)V^r9`qGpp71@*yO4
zE36`B_n;*o(k3EAb=$daFCWffP4l?3c23YQES?1;ff={IrsgStQb5(=zCVaSG5z)Q
z5K4vh%8M<_m@9{p!AO*P#=3s;Btm>5isSH>j{e%Ct!YAcB^0;IhBFvWE)|*88G*6_
zeValUJ{X(uC<8t#O+{&H-g2tc{*FeXEZml6+oPraiL(lh?WCc^LaB#hG@5fXgh5uz
zbo3P*?N1}Nl)!K@Yj-H7vh+Z4J&eFH`WA*zYM`uU#cV%Jy>F^-FZI9cA^R`f7Qc4J
znwSvEDk$Yp>fuj>k`1L1iq#j+ApaF|->z$p_9hF0$=_~=NnbY?Ml}rAzX%kgZ9*%B
zXlk}QT-6K7beHSkm@cH0e$jeJ?g;URPGBhB&|l9ES_5YR)+Avk*@4+4C{0i%La{m{
zP^`9A2GP`@ZJ`vSVG@??hY?Heq(gw>dP%knx5m}jO5!Q{bO<EXdRV5zEPz#nJ?4b;
z@UG6sxn=c-^BA|fuMYagD*7~?tS~0tsWs?sd7oDgElL~7?;AKf*!f7h9eo6*wV{>C
zY8=!A&Y>!pCD^wW`%)k#sgJd+<4vZ?J@qhcXHR|$@w(NLSwTCw$HP0Lc2Ki9Q=NKb
zEZizqB2|6((ah;&-XxENYb}bvHP$@RN@dSC@E(>oNaX2G>Y@HhgFrV7ISq2G?uOEg
z<|zILz$VB&m}iYRC&O)ayYV1>#@~yn2lMn|`!+0I+u3(v+Xe=7Ggd4?L!<4Il!~&R
z-C9N6+=htgqF$b>v2<Iw7Cd+D%eN~-)wh=SaenQ9RlV6~Yw;sR@8bEHHQK}})|nNX
z4bQbM0?|~A%N!o>Iu}vN+L{MiE~jb~)ou=66!9*w$a<5c9jqsHP~Ezf^B`n3u+#12
z9qvGLF0LQ!yy2e$*{^BTK5exOhSeWV;7R0T*PfZyPwwradrlA5LzXZm-uT+UGjVlA
zVAyKXVQ{w+A>JhSn*vtcuQR9~yJ{)gOy#<VcnI->XXSqDFvHqGy{MY5bwgSzpke4N
z)%Ly2IxSWo_gjq-IJUlYD1FUYRG<xKq7AJLFq$-jx8t3(L_Ms(TghT!xHWE->2P|Q
zU6jQ42D{Zi+^KttiPmaOp?*!$^|s!#dc#S?j9YO|w|;eqMQ0*1sqBRu;&Fx+>k{Ip
zTAN0@-(=`vc781p5JiU*$NYgaT2{fljR~<7zNtRv8v3j5_a-*eR6y>pN=z!9&jh}&
zXk-<F?-ZPB)0J{7Eb0ayc9c>@PQkVeY)o^%1zARwT%%rUKC5kkQ(f-73azzHg~Lvs
z+0wChW!~-3-8*c>l<)Tc%noN4(fQ^%@=h-l&%7(e9j2dMZRYp6^$oLbw?5z4X-<cD
zcivVJ%v%{`O%1m1N@QOP)+5;F$}nHe{496gRvO6WGFHc&shD_kHO-NBD+uPT4D+VD
z+iYfE57q|Ex>8u?Q~>Gj9nI#uJLVht?L)f0O|90Mxnuv|;Mo7WIQIWej_rg0FL^-p
EzX&OIXaE2J

literal 0
HcmV?d00001

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* Re: [PATCH 05/26] clk: imx8mm: Mark IMX8MM_SYS_PLL2 and IMX8MM_SYS_PLL3 as enabled
  2024-09-13  9:55 ` [PATCH 05/26] clk: imx8mm: Mark IMX8MM_SYS_PLL2 and IMX8MM_SYS_PLL3 as enabled Dario Binacchi
@ 2024-09-13 10:07   ` Marek Vasut
  0 siblings, 0 replies; 48+ messages in thread
From: Marek Vasut @ 2024-09-13 10:07 UTC (permalink / raw)
  To: Dario Binacchi, u-boot
  Cc: Fabio Estevam, linux-amarula, michael, Miquel Raynal,
	Hou Zhiqiang, Lukasz Majewski, Sean Anderson, Tim Harvey,
	Tom Rini

On 9/13/24 11:55 AM, Dario Binacchi wrote:
> From: Michael Trimarchi <michael@amarulasolutions.com>
> 
> Both clock are enabled by the bootloader and we need to increase their
> reference count to avoid disable during reparent operation.
> 
> Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
> Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
> ---
> 
>   drivers/clk/imx/clk-imx8mm.c | 9 +++++++++
>   1 file changed, 9 insertions(+)
> 
> diff --git a/drivers/clk/imx/clk-imx8mm.c b/drivers/clk/imx/clk-imx8mm.c
> index 432348a15cad..0e71ceefe96c 100644
> --- a/drivers/clk/imx/clk-imx8mm.c
> +++ b/drivers/clk/imx/clk-imx8mm.c
> @@ -176,6 +176,8 @@ static const char * const imx8mm_ecspi3_sels[] = {"clock-osc-24m", "sys_pll2_200
>   static int imx8mm_clk_probe(struct udevice *dev)
>   {
>   	void __iomem *base;
> +	struct clk *clk;
> +	int ret;
>   
>   	base = (void *)ANATOP_BASE_ADDR;
>   
> @@ -458,6 +460,13 @@ static int imx8mm_clk_probe(struct udevice *dev)
>   	clk_dm(IMX8MM_CLK_QSPI_ROOT,
>   	       imx_clk_gate4("qspi_root_clk", "qspi", base + 0x42f0, 0));
>   #endif
> +	ret = clk_get_by_id(IMX8MM_SYS_PLL2, &clk);
> +	if (!ret)
> +		clk_enable(clk);
> +
> +	ret = clk_get_by_id(IMX8MM_SYS_PLL3, &clk);
> +	if (!ret)
> +		clk_enable(clk);
This enables these PLLs for all boards, even the ones which do not need 
those are use those for other purposes like drive the CLKOUT outputs 
from them. Please describe DT consumers, do not hack board-specific 
changes into generic drivers.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 03/26] clk: imx8mm: Prevent clock critical path from disabling during reparent and set_rate
  2024-09-13  9:55 ` [PATCH 03/26] clk: imx8mm: " Dario Binacchi
@ 2024-09-13 10:09   ` Marek Vasut
  0 siblings, 0 replies; 48+ messages in thread
From: Marek Vasut @ 2024-09-13 10:09 UTC (permalink / raw)
  To: Dario Binacchi, u-boot
  Cc: Fabio Estevam, linux-amarula, michael, Miquel Raynal,
	Hou Zhiqiang, Lukasz Majewski, Sean Anderson, Tim Harvey,
	Tom Rini

On 9/13/24 11:55 AM, Dario Binacchi wrote:
> From: Michael Trimarchi <michael@amarulasolutions.com>
> 
> This commit ensures that critical clock paths are not disabled during
> reparent and set_rate operations within the clock framework, paving the
> way for the inclusion of new features.
> 
> Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
> Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
> ---
> 
>   drivers/clk/imx/clk-imx8mm.c | 64 +++++++++++++++++++++++++++++-------
>   1 file changed, 52 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/clk/imx/clk-imx8mm.c b/drivers/clk/imx/clk-imx8mm.c
> index a91c6767fac5..432348a15cad 100644
> --- a/drivers/clk/imx/clk-imx8mm.c
> +++ b/drivers/clk/imx/clk-imx8mm.c
> @@ -27,11 +27,25 @@ static const char * const imx8mm_a53_sels[] = {"clock-osc-24m", "arm_pll_out", "
>   					       "sys_pll2_1000m", "sys_pll1_800m", "sys_pll1_400m",
>   					       "audio_pll1_out", "sys_pll3_out", };
>   
> +#ifndef CONFIG_SPL_BUILD
> +static const char * const imx8mm_noc_sels[] = {"clock-osc-24m", "sys_pll1_800m", "sys_pll3_out",
> +					       "sys_pll2_1000m", "sys_pll2_500m", "audio_pll1_out",
> +					       "video_pll1_out", "audio_pll2_out", };
> +
This seems to be adding a lot of new clock, such a change is not 
described in the commit message.

What problem is this patch solving ? The commit message needs to be 
updated, it does not seem to match the patch at all.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 08/26] power: Add iMX8M block ctrl driver for dispmix
  2024-09-13  9:55 ` [PATCH 08/26] power: Add iMX8M block ctrl driver for dispmix Dario Binacchi
@ 2024-09-24  9:05   ` Heiko Schocher
  2024-09-30 13:20     ` Dario Binacchi
  0 siblings, 1 reply; 48+ messages in thread
From: Heiko Schocher @ 2024-09-24  9:05 UTC (permalink / raw)
  To: Dario Binacchi, u-boot
  Cc: Fabio Estevam, linux-amarula, michael, Miquel Raynal, Ye Li,
	AKASHI Takahiro, Jaehoon Chung, Tom Rini

Hello Dario,

On 13.09.24 11:55, Dario Binacchi wrote:
> From: Michael Trimarchi <michael@amarulasolutions.com>
> 
> Add iMX8 block ctrl driver for displaymix on iMX8MM/iMX8MN and
> mediamix on iMX8MP.
> 
> To support blk ctrl driver, the power domain driver on iMX8M needs
> update to add relevant PGC domains
> 
> Signed-off-by: Ye Li <ye.li@nxp.com>
> Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
> Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
> ---
> 
>   drivers/power/domain/Kconfig              |   6 +
>   drivers/power/domain/Makefile             |   1 +
>   drivers/power/domain/imx8m-blk-ctrl.c     | 438 ++++++++++++++++++++++
>   drivers/power/domain/imx8m-power-domain.c | 213 ++++++++++-
>   4 files changed, 656 insertions(+), 2 deletions(-)
>   create mode 100644 drivers/power/domain/imx8m-blk-ctrl.c
> 
> diff --git a/drivers/power/domain/Kconfig b/drivers/power/domain/Kconfig
> index bd82d2f7044b..fb006b6e8e28 100644
> --- a/drivers/power/domain/Kconfig
> +++ b/drivers/power/domain/Kconfig
> @@ -40,6 +40,12 @@ config IMX8M_POWER_DOMAIN
>   	  Enable support for manipulating NXP i.MX8M on-SoC power domains via
>   	  requests to the ATF.
>   
> +config IMX8M_BLK_CTRL
> +	bool "Enable i.MX8M block control driver"
> +	depends on POWER_DOMAIN && ARCH_IMX8M
> +	help
> +	  Enable support for manipulating NXP i.MX8M on-SoC block control driver
> +
>   config IMX8MP_HSIOMIX_BLKCTRL
>   	bool "Enable i.MX8MP HSIOMIX domain driver"
>   	depends on POWER_DOMAIN && IMX8MP
> diff --git a/drivers/power/domain/Makefile b/drivers/power/domain/Makefile
> index 2daab73eb758..46849fd2a4db 100644
> --- a/drivers/power/domain/Makefile
> +++ b/drivers/power/domain/Makefile
> @@ -8,6 +8,7 @@ obj-$(CONFIG_APPLE_PMGR_POWER_DOMAIN) += apple-pmgr.o
>   obj-$(CONFIG_BCM6328_POWER_DOMAIN) += bcm6328-power-domain.o
>   obj-$(CONFIG_IMX8_POWER_DOMAIN) += imx8-power-domain-legacy.o imx8-power-domain.o
>   obj-$(CONFIG_IMX8M_POWER_DOMAIN) += imx8m-power-domain.o
> +obj-$(CONFIG_IMX8M_BLK_CTRL) += imx8m-blk-ctrl.o
>   obj-$(CONFIG_IMX8MP_HSIOMIX_BLKCTRL) += imx8mp-hsiomix.o
>   obj-$(CONFIG_MTK_POWER_DOMAIN) += mtk-power-domain.o
>   obj-$(CONFIG_MESON_GX_VPU_POWER_DOMAIN) += meson-gx-pwrc-vpu.o
> diff --git a/drivers/power/domain/imx8m-blk-ctrl.c b/drivers/power/domain/imx8m-blk-ctrl.c
> new file mode 100644
> index 000000000000..4c89078b991b
> --- /dev/null
> +++ b/drivers/power/domain/imx8m-blk-ctrl.c
> @@ -0,0 +1,438 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2023 NXP
> + */
> +
> +#include <dm.h>
> +#include <malloc.h>
> +#include <power-domain-uclass.h>
> +#include <asm/io.h>
> +#include <dm/device-internal.h>
> +#include <dm/device.h>
> +#include <dt-bindings/power/imx8mm-power.h>
> +#include <dt-bindings/power/imx8mn-power.h>
> +#include <dt-bindings/power/imx8mp-power.h>
> +#include <clk.h>
> +#include <linux/delay.h>
> +
> +#define BLK_SFT_RSTN	0x0
> +#define BLK_CLK_EN	0x4
> +#define BLK_MIPI_RESET_DIV	0x8 /* Mini/Nano/Plus DISPLAY_BLK_CTRL only */
> +
> +#define DOMAIN_MAX_CLKS 4
> +
> +struct imx8m_blk_ctrl_domain {
> +	struct clk clks[DOMAIN_MAX_CLKS];
> +	struct power_domain power_dev;
> +};
> +
> +struct imx8m_blk_ctrl {
> +	void __iomem *base;
> +	struct power_domain bus_power_dev;
> +	struct imx8m_blk_ctrl_domain *domains;
> +};
> +
> +struct imx8m_blk_ctrl_domain_data {
> +	const char *name;
> +	const char * const *clk_names;
> +	const char *gpc_name;
> +	int num_clks;
> +	u32 rst_mask;
> +	u32 clk_mask;
> +	u32 mipi_phy_rst_mask;
> +};
> +
> +struct imx8m_blk_ctrl_data {
> +	int max_reg;
> +	const struct imx8m_blk_ctrl_domain_data *domains;
> +	int num_domains;
> +	u32 bus_rst_mask;
> +	u32 bus_clk_mask;
> +};
> +
> +static int imx8m_blk_ctrl_request(struct power_domain *power_domain)
> +{
> +	return 0;
> +}
> +
> +static int imx8m_blk_ctrl_free(struct power_domain *power_domain)
> +{
> +	return 0;
> +}
> +
> +static int imx8m_blk_ctrl_enable_domain_clk(struct udevice *dev, ulong domain_id, bool enable)
> +{
> +	int ret, i;
> +	struct imx8m_blk_ctrl *priv = (struct imx8m_blk_ctrl *)dev_get_priv(dev);
> +	struct imx8m_blk_ctrl_data *drv_data =
> +		(struct imx8m_blk_ctrl_data *)dev_get_driver_data(dev);
> +
> +	debug("%s num_clk %u\n", __func__, drv_data->domains[domain_id].num_clks);
> +
> +	for (i = 0; i < drv_data->domains[domain_id].num_clks; i++) {
> +		debug("%s clk %s\n", __func__, drv_data->domains[domain_id].clk_names[i]);
> +		if (enable)
> +			ret = clk_enable(&priv->domains[domain_id].clks[i]);
> +		else
> +			ret = clk_disable(&priv->domains[domain_id].clks[i]);
> +		if (ret && ret != -ENOENT) {
> +			printf("Failed to %s domain clk %s\n", enable ? "enable" : "disable",
> +			       drv_data->domains[domain_id].clk_names[i]);
> +			return ret;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static int imx8m_blk_ctrl_power_on(struct power_domain *power_domain)
> +{
> +	struct udevice *dev = power_domain->dev;
> +	struct imx8m_blk_ctrl *priv = (struct imx8m_blk_ctrl *)dev_get_priv(dev);
> +	struct imx8m_blk_ctrl_data *drv_data =
> +		(struct imx8m_blk_ctrl_data *)dev_get_driver_data(dev);
> +	int ret;
> +
> +	debug("%s, id %lu\n", __func__, power_domain->id);
> +
> +	if (!priv->domains[power_domain->id].power_dev.dev)
> +		return -ENODEV;
> +
> +	ret = power_domain_on(&priv->bus_power_dev);
> +	if (ret < 0) {
> +		printf("Failed to power up bus domain %d\n", ret);
> +		return ret;
> +	}
> +
> +	/* Enable bus clock and deassert bus reset */
> +	setbits_le32(priv->base + BLK_CLK_EN, drv_data->bus_clk_mask);
> +	setbits_le32(priv->base + BLK_SFT_RSTN, drv_data->bus_rst_mask);
> +
> +	/* wait for reset to propagate */
> +	udelay(5);
> +
> +	/* put devices into reset */
> +	clrbits_le32(priv->base + BLK_SFT_RSTN, drv_data->domains[power_domain->id].rst_mask);
> +	if (drv_data->domains[power_domain->id].mipi_phy_rst_mask)
> +		clrbits_le32(priv->base + BLK_MIPI_RESET_DIV, d
> +			     rv_data->domains[power_domain->id].mipi_phy_rst_mask);

Does this build for you?

I needed the following fix:

diff --git a/drivers/power/domain/imx8m-blk-ctrl.c b/drivers/power/domain/imx8m-blk-ctrl.c
index 4c89078b99..b772d50480 100644
--- a/drivers/power/domain/imx8m-blk-ctrl.c
+++ b/drivers/power/domain/imx8m-blk-ctrl.c
@@ -114,8 +114,8 @@ static int imx8m_blk_ctrl_power_on(struct power_domain *power_domain)
         /* put devices into reset */
         clrbits_le32(priv->base + BLK_SFT_RSTN, drv_data->domains[power_domain->id].rst_mask);
         if (drv_data->domains[power_domain->id].mipi_phy_rst_mask)
-               clrbits_le32(priv->base + BLK_MIPI_RESET_DIV, d
-                            rv_data->domains[power_domain->id].mipi_phy_rst_mask);
+               clrbits_le32(priv->base + BLK_MIPI_RESET_DIV,
+                            drv_data->domains[power_domain->id].mipi_phy_rst_mask);

         /* enable upstream and blk-ctrl clocks to allow reset to propagate */
         ret = imx8m_blk_ctrl_enable_domain_clk(dev, power_domain->id, true);

to get it building.

BTW: Just also working on bootlogo support for an imx8mp based board!

I now applied your patches:

clk: Propagate clk_set_rate() if CLK_SET_PARENT_RATE present for gate and mux
clk: clk-uclass: Implement CLK_OPS_PARENT_ENABLE

And added in my adapted /drivers/clk/imx/clk-imx8mp.c (imported from linux)

clk_dm(IMX8MP_CLK_MEDIA_AXI, imx8m_clk_composite_flags("media_axi", imx8mp_media_axi_sels, 
ARRAY_SIZE(imx8mp_media_axi_sels), base + 0x8a00, CLK_IS_CRITICAL));

instead of using imx8m_clk_composite, and dropped my approach to
get clocks up and working.

Also dropped my similiar approach for mediablock and used your

power: Add iMX8M block ctrl driver for dispmix

And with this 3 patches, bootlogo works also/still fine for me!

I did not applied/need your patches:

clk: imx8mn: Prevent clock critical path from disabling during reparent and set_rate
clk: imx8mm: Prevent clock critical path from disabling during reparent and set_rate
clk: imx8mm: Mark IMX8MM_SYS_PLL2 and IMX8MM_SYS_PLL3 as enabled
clk: imx8mn: Mark IMX8MN_SYS_PLL2 and IMX8MN_SYS_PLL3 as enabled

Of course, they are for imx8mm, but I mean I do not need similiar patches
for imx8mp!

Also not applied (as for imx8mm)
clk: imx8mn: add video clocks support

but as said, have similiar patch for clk-imx8mp.c

May you check if using imx8m_clk_composite_flags() is working for you?

I did not applied your patches 09/26 and the following patches from
your series, as I made a video bridge driver based on

linux driver drivers/gpu/drm/bridge/fsl-ldb.c

and a lcdif driver based on linux:/drivers/gpu/drm/mxsfb/lcdif_drv.c

bye,
Heiko
-- 
DENX Software Engineering GmbH,      Managing Director: Erika Unter
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-52   Fax: +49-8142-66989-80   Email: hs@denx.de

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* Re: [PATCH 00/26] Support display (and even more) on the BSH SMM S2/PRO boards
  2024-09-13  9:55 [PATCH 00/26] Support display (and even more) on the BSH SMM S2/PRO boards Dario Binacchi
                   ` (25 preceding siblings ...)
  2024-09-13  9:56 ` [PATCH 26/26] imx8mn_bsh_smm_s2/pro: add splash screen with BSH logo Dario Binacchi
@ 2024-09-30  9:43 ` Miquel Raynal
  2024-09-30 13:07   ` Dario Binacchi
  26 siblings, 1 reply; 48+ messages in thread
From: Miquel Raynal @ 2024-09-30  9:43 UTC (permalink / raw)
  To: Dario Binacchi
  Cc: u-boot, Fabio Estevam, linux-amarula, michael, AKASHI Takahiro,
	Alexander Dahl, Anatolij Gustschin, Andrzej Hajda, Anton Bambura,
	Ashok Reddy Soma, Devarsh Thakkar, Eugen Hristev, Fabio Estevam,
	Heinrich Schuchardt, Hou Zhiqiang, Igor Prusov, Igor Prusov,
	Jaehoon Chung, Jan Kiszka, Joe Hershberger, Jonas Schwöbel,
	Julien Masson, Liu Ying, Lukasz Majewski, Maksim Kiselev,
	Marcel Ziswiler, Marco Felsch, Marek Vasut, Marek Vasut,
	Martyn Welch, Mattijs Korpershoek, Minkyu Kang,
	NXP i.MX U-Boot Team, Neil Armstrong, Nicolas Heemeryck,
	Nikhil M Jain, Patrick Barsanti, Peng Fan, Peter Robinson,
	Sakari Ailus, Sam Protsenko, Sean Anderson, Simon Glass,
	Stefan Bosch, Stefano Babic, Svyatoslav Ryhel,
	Sébastien Szymanski, Tim Harvey, Tom Rini, Vinod Koul,
	Yang Xiwen, Ye Li, u-boot-amlogic

Hi Dario,

dario.binacchi@amarulasolutions.com wrote on Fri, 13 Sep 2024 11:55:42
+0200:

> This series was created out of the need to supportsimple-framebuffer for
> BSH boards SMM_S2 and SMM_S2PRO. To achieve this goal, it was necessary
> to develop additional code and/or drivers for all the required components
> (i. e. clock, power domain, video, etc.). This series has a Linux
> counterpart that will also be submitted upstream as soon as possible.
> Furthermore, given the overlap in topics with the recent series [1], we
> are open to collaborate on the common parts to ensure proper development.
> 
> [1] https://lore.kernel.org/all/20240910101344.110633-1-miquel.raynal@bootlin.com/T/#mb7cd440abc6fcc0de205f577eb3225e1c1c76823

I received a bit of feedback on this U-Boot series, I can take the
feedback into account and send a v2. Then, if you are still okay, you
can stack your patches on top of mine and do the required adaptations
(on both sides).

Thanks,
Miquèl

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 00/26] Support display (and even more) on the BSH SMM S2/PRO boards
  2024-09-30  9:43 ` [PATCH 00/26] Support display (and even more) on the BSH SMM S2/PRO boards Miquel Raynal
@ 2024-09-30 13:07   ` Dario Binacchi
  0 siblings, 0 replies; 48+ messages in thread
From: Dario Binacchi @ 2024-09-30 13:07 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: u-boot, Fabio Estevam, linux-amarula, michael, AKASHI Takahiro,
	Alexander Dahl, Anatolij Gustschin, Andrzej Hajda, Anton Bambura,
	Ashok Reddy Soma, Devarsh Thakkar, Eugen Hristev, Fabio Estevam,
	Heinrich Schuchardt, Hou Zhiqiang, Igor Prusov, Igor Prusov,
	Jaehoon Chung, Jan Kiszka, Joe Hershberger, Jonas Schwöbel,
	Julien Masson, Liu Ying, Lukasz Majewski, Maksim Kiselev,
	Marcel Ziswiler, Marco Felsch, Marek Vasut, Marek Vasut,
	Martyn Welch, Mattijs Korpershoek, Minkyu Kang,
	NXP i.MX U-Boot Team, Neil Armstrong, Nicolas Heemeryck,
	Nikhil M Jain, Patrick Barsanti, Peng Fan, Peter Robinson,
	Sakari Ailus, Sam Protsenko, Sean Anderson, Simon Glass,
	Stefan Bosch, Stefano Babic, Svyatoslav Ryhel,
	Sébastien Szymanski, Tim Harvey, Tom Rini, Vinod Koul,
	Yang Xiwen, Ye Li, u-boot-amlogic

Hi Miquel,

On Mon, Sep 30, 2024 at 11:43 AM Miquel Raynal
<miquel.raynal@bootlin.com> wrote:
>
> Hi Dario,
>
> dario.binacchi@amarulasolutions.com wrote on Fri, 13 Sep 2024 11:55:42
> +0200:
>
> > This series was created out of the need to supportsimple-framebuffer for
> > BSH boards SMM_S2 and SMM_S2PRO. To achieve this goal, it was necessary
> > to develop additional code and/or drivers for all the required components
> > (i. e. clock, power domain, video, etc.). This series has a Linux
> > counterpart that will also be submitted upstream as soon as possible.
> > Furthermore, given the overlap in topics with the recent series [1], we
> > are open to collaborate on the common parts to ensure proper development.
> >
> > [1] https://lore.kernel.org/all/20240910101344.110633-1-miquel.raynal@bootlin.com/T/#mb7cd440abc6fcc0de205f577eb3225e1c1c76823
>
> I received a bit of feedback on this U-Boot series, I can take the
> feedback into account and send a v2. Then, if you are still okay, you
> can stack your patches on top of mine and do the required adaptations
> (on both sides).

Sure, go ahead with version 2.

Thanks and regards,
Dario
>
> Thanks,
> Miquèl



-- 

Dario Binacchi

Senior Embedded Linux Developer

dario.binacchi@amarulasolutions.com

__________________________________


Amarula Solutions SRL

Via Le Canevare 30, 31100 Treviso, Veneto, IT

T. +39 042 243 5310
info@amarulasolutions.com

www.amarulasolutions.com

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 08/26] power: Add iMX8M block ctrl driver for dispmix
  2024-09-24  9:05   ` Heiko Schocher
@ 2024-09-30 13:20     ` Dario Binacchi
  2024-10-01  4:21       ` Heiko Schocher
  0 siblings, 1 reply; 48+ messages in thread
From: Dario Binacchi @ 2024-09-30 13:20 UTC (permalink / raw)
  To: hs
  Cc: u-boot, Fabio Estevam, linux-amarula, michael, Miquel Raynal,
	Ye Li, AKASHI Takahiro, Jaehoon Chung, Tom Rini

Hello Heiko,

On Tue, Sep 24, 2024 at 11:07 AM Heiko Schocher <hs@denx.de> wrote:
>
> Hello Dario,
>
> On 13.09.24 11:55, Dario Binacchi wrote:
> > From: Michael Trimarchi <michael@amarulasolutions.com>
> >
> > Add iMX8 block ctrl driver for displaymix on iMX8MM/iMX8MN and
> > mediamix on iMX8MP.
> >
> > To support blk ctrl driver, the power domain driver on iMX8M needs
> > update to add relevant PGC domains
> >
> > Signed-off-by: Ye Li <ye.li@nxp.com>
> > Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
> > Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
> > ---
> >
> >   drivers/power/domain/Kconfig              |   6 +
> >   drivers/power/domain/Makefile             |   1 +
> >   drivers/power/domain/imx8m-blk-ctrl.c     | 438 ++++++++++++++++++++++
> >   drivers/power/domain/imx8m-power-domain.c | 213 ++++++++++-
> >   4 files changed, 656 insertions(+), 2 deletions(-)
> >   create mode 100644 drivers/power/domain/imx8m-blk-ctrl.c
> >
> > diff --git a/drivers/power/domain/Kconfig b/drivers/power/domain/Kconfig
> > index bd82d2f7044b..fb006b6e8e28 100644
> > --- a/drivers/power/domain/Kconfig
> > +++ b/drivers/power/domain/Kconfig
> > @@ -40,6 +40,12 @@ config IMX8M_POWER_DOMAIN
> >         Enable support for manipulating NXP i.MX8M on-SoC power domains via
> >         requests to the ATF.
> >
> > +config IMX8M_BLK_CTRL
> > +     bool "Enable i.MX8M block control driver"
> > +     depends on POWER_DOMAIN && ARCH_IMX8M
> > +     help
> > +       Enable support for manipulating NXP i.MX8M on-SoC block control driver
> > +
> >   config IMX8MP_HSIOMIX_BLKCTRL
> >       bool "Enable i.MX8MP HSIOMIX domain driver"
> >       depends on POWER_DOMAIN && IMX8MP
> > diff --git a/drivers/power/domain/Makefile b/drivers/power/domain/Makefile
> > index 2daab73eb758..46849fd2a4db 100644
> > --- a/drivers/power/domain/Makefile
> > +++ b/drivers/power/domain/Makefile
> > @@ -8,6 +8,7 @@ obj-$(CONFIG_APPLE_PMGR_POWER_DOMAIN) += apple-pmgr.o
> >   obj-$(CONFIG_BCM6328_POWER_DOMAIN) += bcm6328-power-domain.o
> >   obj-$(CONFIG_IMX8_POWER_DOMAIN) += imx8-power-domain-legacy.o imx8-power-domain.o
> >   obj-$(CONFIG_IMX8M_POWER_DOMAIN) += imx8m-power-domain.o
> > +obj-$(CONFIG_IMX8M_BLK_CTRL) += imx8m-blk-ctrl.o
> >   obj-$(CONFIG_IMX8MP_HSIOMIX_BLKCTRL) += imx8mp-hsiomix.o
> >   obj-$(CONFIG_MTK_POWER_DOMAIN) += mtk-power-domain.o
> >   obj-$(CONFIG_MESON_GX_VPU_POWER_DOMAIN) += meson-gx-pwrc-vpu.o
> > diff --git a/drivers/power/domain/imx8m-blk-ctrl.c b/drivers/power/domain/imx8m-blk-ctrl.c
> > new file mode 100644
> > index 000000000000..4c89078b991b
> > --- /dev/null
> > +++ b/drivers/power/domain/imx8m-blk-ctrl.c
> > @@ -0,0 +1,438 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright 2023 NXP
> > + */
> > +
> > +#include <dm.h>
> > +#include <malloc.h>
> > +#include <power-domain-uclass.h>
> > +#include <asm/io.h>
> > +#include <dm/device-internal.h>
> > +#include <dm/device.h>
> > +#include <dt-bindings/power/imx8mm-power.h>
> > +#include <dt-bindings/power/imx8mn-power.h>
> > +#include <dt-bindings/power/imx8mp-power.h>
> > +#include <clk.h>
> > +#include <linux/delay.h>
> > +
> > +#define BLK_SFT_RSTN 0x0
> > +#define BLK_CLK_EN   0x4
> > +#define BLK_MIPI_RESET_DIV   0x8 /* Mini/Nano/Plus DISPLAY_BLK_CTRL only */
> > +
> > +#define DOMAIN_MAX_CLKS 4
> > +
> > +struct imx8m_blk_ctrl_domain {
> > +     struct clk clks[DOMAIN_MAX_CLKS];
> > +     struct power_domain power_dev;
> > +};
> > +
> > +struct imx8m_blk_ctrl {
> > +     void __iomem *base;
> > +     struct power_domain bus_power_dev;
> > +     struct imx8m_blk_ctrl_domain *domains;
> > +};
> > +
> > +struct imx8m_blk_ctrl_domain_data {
> > +     const char *name;
> > +     const char * const *clk_names;
> > +     const char *gpc_name;
> > +     int num_clks;
> > +     u32 rst_mask;
> > +     u32 clk_mask;
> > +     u32 mipi_phy_rst_mask;
> > +};
> > +
> > +struct imx8m_blk_ctrl_data {
> > +     int max_reg;
> > +     const struct imx8m_blk_ctrl_domain_data *domains;
> > +     int num_domains;
> > +     u32 bus_rst_mask;
> > +     u32 bus_clk_mask;
> > +};
> > +
> > +static int imx8m_blk_ctrl_request(struct power_domain *power_domain)
> > +{
> > +     return 0;
> > +}
> > +
> > +static int imx8m_blk_ctrl_free(struct power_domain *power_domain)
> > +{
> > +     return 0;
> > +}
> > +
> > +static int imx8m_blk_ctrl_enable_domain_clk(struct udevice *dev, ulong domain_id, bool enable)
> > +{
> > +     int ret, i;
> > +     struct imx8m_blk_ctrl *priv = (struct imx8m_blk_ctrl *)dev_get_priv(dev);
> > +     struct imx8m_blk_ctrl_data *drv_data =
> > +             (struct imx8m_blk_ctrl_data *)dev_get_driver_data(dev);
> > +
> > +     debug("%s num_clk %u\n", __func__, drv_data->domains[domain_id].num_clks);
> > +
> > +     for (i = 0; i < drv_data->domains[domain_id].num_clks; i++) {
> > +             debug("%s clk %s\n", __func__, drv_data->domains[domain_id].clk_names[i]);
> > +             if (enable)
> > +                     ret = clk_enable(&priv->domains[domain_id].clks[i]);
> > +             else
> > +                     ret = clk_disable(&priv->domains[domain_id].clks[i]);
> > +             if (ret && ret != -ENOENT) {
> > +                     printf("Failed to %s domain clk %s\n", enable ? "enable" : "disable",
> > +                            drv_data->domains[domain_id].clk_names[i]);
> > +                     return ret;
> > +             }
> > +     }
> > +
> > +     return 0;
> > +}
> > +
> > +static int imx8m_blk_ctrl_power_on(struct power_domain *power_domain)
> > +{
> > +     struct udevice *dev = power_domain->dev;
> > +     struct imx8m_blk_ctrl *priv = (struct imx8m_blk_ctrl *)dev_get_priv(dev);
> > +     struct imx8m_blk_ctrl_data *drv_data =
> > +             (struct imx8m_blk_ctrl_data *)dev_get_driver_data(dev);
> > +     int ret;
> > +
> > +     debug("%s, id %lu\n", __func__, power_domain->id);
> > +
> > +     if (!priv->domains[power_domain->id].power_dev.dev)
> > +             return -ENODEV;
> > +
> > +     ret = power_domain_on(&priv->bus_power_dev);
> > +     if (ret < 0) {
> > +             printf("Failed to power up bus domain %d\n", ret);
> > +             return ret;
> > +     }
> > +
> > +     /* Enable bus clock and deassert bus reset */
> > +     setbits_le32(priv->base + BLK_CLK_EN, drv_data->bus_clk_mask);
> > +     setbits_le32(priv->base + BLK_SFT_RSTN, drv_data->bus_rst_mask);
> > +
> > +     /* wait for reset to propagate */
> > +     udelay(5);
> > +
> > +     /* put devices into reset */
> > +     clrbits_le32(priv->base + BLK_SFT_RSTN, drv_data->domains[power_domain->id].rst_mask);
> > +     if (drv_data->domains[power_domain->id].mipi_phy_rst_mask)
> > +             clrbits_le32(priv->base + BLK_MIPI_RESET_DIV, d
> > +                          rv_data->domains[power_domain->id].mipi_phy_rst_mask);
>
> Does this build for you?
>
> I needed the following fix:
>
> diff --git a/drivers/power/domain/imx8m-blk-ctrl.c b/drivers/power/domain/imx8m-blk-ctrl.c
> index 4c89078b99..b772d50480 100644
> --- a/drivers/power/domain/imx8m-blk-ctrl.c
> +++ b/drivers/power/domain/imx8m-blk-ctrl.c
> @@ -114,8 +114,8 @@ static int imx8m_blk_ctrl_power_on(struct power_domain *power_domain)
>          /* put devices into reset */
>          clrbits_le32(priv->base + BLK_SFT_RSTN, drv_data->domains[power_domain->id].rst_mask);
>          if (drv_data->domains[power_domain->id].mipi_phy_rst_mask)
> -               clrbits_le32(priv->base + BLK_MIPI_RESET_DIV, d
> -                            rv_data->domains[power_domain->id].mipi_phy_rst_mask);
> +               clrbits_le32(priv->base + BLK_MIPI_RESET_DIV,
> +                            drv_data->domains[power_domain->id].mipi_phy_rst_mask);
>
>          /* enable upstream and blk-ctrl clocks to allow reset to propagate */
>          ret = imx8m_blk_ctrl_enable_domain_clk(dev, power_domain->id, true);
>
> to get it building.

Yes, you're right. I made some changes suggested by patman, and before
applying the
 patch, I didn't recompile, so I didn't notice.

>
> BTW: Just also working on bootlogo support for an imx8mp based board!
>
> I now applied your patches:
>
> clk: Propagate clk_set_rate() if CLK_SET_PARENT_RATE present for gate and mux
> clk: clk-uclass: Implement CLK_OPS_PARENT_ENABLE
>
> And added in my adapted /drivers/clk/imx/clk-imx8mp.c (imported from linux)
>
> clk_dm(IMX8MP_CLK_MEDIA_AXI, imx8m_clk_composite_flags("media_axi", imx8mp_media_axi_sels,
> ARRAY_SIZE(imx8mp_media_axi_sels), base + 0x8a00, CLK_IS_CRITICAL));
>
> instead of using imx8m_clk_composite, and dropped my approach to
> get clocks up and working.
>
> Also dropped my similiar approach for mediablock and used your
>
> power: Add iMX8M block ctrl driver for dispmix
>
> And with this 3 patches, bootlogo works also/still fine for me!
>
> I did not applied/need your patches:
>
> clk: imx8mn: Prevent clock critical path from disabling during reparent and set_rate
> clk: imx8mm: Prevent clock critical path from disabling during reparent and set_rate
> clk: imx8mm: Mark IMX8MM_SYS_PLL2 and IMX8MM_SYS_PLL3 as enabled
> clk: imx8mn: Mark IMX8MN_SYS_PLL2 and IMX8MN_SYS_PLL3 as enabled
>
> Of course, they are for imx8mm, but I mean I do not need similiar patches
> for imx8mp!
>
> Also not applied (as for imx8mm)
> clk: imx8mn: add video clocks support
>
> but as said, have similiar patch for clk-imx8mp.c
>
> May you check if using imx8m_clk_composite_flags() is working for you?

I will do it

>
> I did not applied your patches 09/26 and the following patches from
> your series, as I made a video bridge driver based on
>
> linux driver drivers/gpu/drm/bridge/fsl-ldb.c
>
> and a lcdif driver based on linux:/drivers/gpu/drm/mxsfb/lcdif_drv.c
>

Thank you for you feedback Heiko

Regards,
Dario

> bye,
> Heiko
> --
> DENX Software Engineering GmbH,      Managing Director: Erika Unter
> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
> Phone: +49-8142-66989-52   Fax: +49-8142-66989-80   Email: hs@denx.de



-- 

Dario Binacchi

Senior Embedded Linux Developer

dario.binacchi@amarulasolutions.com

__________________________________


Amarula Solutions SRL

Via Le Canevare 30, 31100 Treviso, Veneto, IT

T. +39 042 243 5310
info@amarulasolutions.com

www.amarulasolutions.com

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 08/26] power: Add iMX8M block ctrl driver for dispmix
  2024-09-30 13:20     ` Dario Binacchi
@ 2024-10-01  4:21       ` Heiko Schocher
  2024-10-01  5:01         ` Michael Nazzareno Trimarchi
  0 siblings, 1 reply; 48+ messages in thread
From: Heiko Schocher @ 2024-10-01  4:21 UTC (permalink / raw)
  To: Dario Binacchi
  Cc: u-boot, Fabio Estevam, linux-amarula, michael, Miquel Raynal,
	Ye Li, AKASHI Takahiro, Jaehoon Chung, Tom Rini

Hi Dario,

On 30.09.24 15:20, Dario Binacchi wrote:
> Hello Heiko,
> 
> On Tue, Sep 24, 2024 at 11:07 AM Heiko Schocher <hs@denx.de> wrote:
>>
>> Hello Dario,
>>
>> On 13.09.24 11:55, Dario Binacchi wrote:
>>> From: Michael Trimarchi <michael@amarulasolutions.com>
>>>
>>> Add iMX8 block ctrl driver for displaymix on iMX8MM/iMX8MN and
>>> mediamix on iMX8MP.
>>>
>>> To support blk ctrl driver, the power domain driver on iMX8M needs
>>> update to add relevant PGC domains
>>>
>>> Signed-off-by: Ye Li <ye.li@nxp.com>
>>> Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
>>> Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
>>> ---
>>>
>>>    drivers/power/domain/Kconfig              |   6 +
>>>    drivers/power/domain/Makefile             |   1 +
>>>    drivers/power/domain/imx8m-blk-ctrl.c     | 438 ++++++++++++++++++++++
>>>    drivers/power/domain/imx8m-power-domain.c | 213 ++++++++++-
>>>    4 files changed, 656 insertions(+), 2 deletions(-)
>>>    create mode 100644 drivers/power/domain/imx8m-blk-ctrl.c
>>>
>>> diff --git a/drivers/power/domain/Kconfig b/drivers/power/domain/Kconfig
>>> index bd82d2f7044b..fb006b6e8e28 100644
>>> --- a/drivers/power/domain/Kconfig
>>> +++ b/drivers/power/domain/Kconfig
>>> @@ -40,6 +40,12 @@ config IMX8M_POWER_DOMAIN
>>>          Enable support for manipulating NXP i.MX8M on-SoC power domains via
>>>          requests to the ATF.
>>>
>>> +config IMX8M_BLK_CTRL
>>> +     bool "Enable i.MX8M block control driver"
>>> +     depends on POWER_DOMAIN && ARCH_IMX8M
>>> +     help
>>> +       Enable support for manipulating NXP i.MX8M on-SoC block control driver
>>> +
>>>    config IMX8MP_HSIOMIX_BLKCTRL
>>>        bool "Enable i.MX8MP HSIOMIX domain driver"
>>>        depends on POWER_DOMAIN && IMX8MP
>>> diff --git a/drivers/power/domain/Makefile b/drivers/power/domain/Makefile
>>> index 2daab73eb758..46849fd2a4db 100644
>>> --- a/drivers/power/domain/Makefile
>>> +++ b/drivers/power/domain/Makefile
>>> @@ -8,6 +8,7 @@ obj-$(CONFIG_APPLE_PMGR_POWER_DOMAIN) += apple-pmgr.o
>>>    obj-$(CONFIG_BCM6328_POWER_DOMAIN) += bcm6328-power-domain.o
>>>    obj-$(CONFIG_IMX8_POWER_DOMAIN) += imx8-power-domain-legacy.o imx8-power-domain.o
>>>    obj-$(CONFIG_IMX8M_POWER_DOMAIN) += imx8m-power-domain.o
>>> +obj-$(CONFIG_IMX8M_BLK_CTRL) += imx8m-blk-ctrl.o
>>>    obj-$(CONFIG_IMX8MP_HSIOMIX_BLKCTRL) += imx8mp-hsiomix.o
>>>    obj-$(CONFIG_MTK_POWER_DOMAIN) += mtk-power-domain.o
>>>    obj-$(CONFIG_MESON_GX_VPU_POWER_DOMAIN) += meson-gx-pwrc-vpu.o
>>> diff --git a/drivers/power/domain/imx8m-blk-ctrl.c b/drivers/power/domain/imx8m-blk-ctrl.c
>>> new file mode 100644
>>> index 000000000000..4c89078b991b
>>> --- /dev/null
>>> +++ b/drivers/power/domain/imx8m-blk-ctrl.c
>>> @@ -0,0 +1,438 @@
>>> +// SPDX-License-Identifier: GPL-2.0
>>> +/*
>>> + * Copyright 2023 NXP
>>> + */
>>> +
>>> +#include <dm.h>
>>> +#include <malloc.h>
>>> +#include <power-domain-uclass.h>
>>> +#include <asm/io.h>
>>> +#include <dm/device-internal.h>
>>> +#include <dm/device.h>
>>> +#include <dt-bindings/power/imx8mm-power.h>
>>> +#include <dt-bindings/power/imx8mn-power.h>
>>> +#include <dt-bindings/power/imx8mp-power.h>
>>> +#include <clk.h>
>>> +#include <linux/delay.h>
>>> +
>>> +#define BLK_SFT_RSTN 0x0
>>> +#define BLK_CLK_EN   0x4
>>> +#define BLK_MIPI_RESET_DIV   0x8 /* Mini/Nano/Plus DISPLAY_BLK_CTRL only */
>>> +
>>> +#define DOMAIN_MAX_CLKS 4
>>> +
>>> +struct imx8m_blk_ctrl_domain {
>>> +     struct clk clks[DOMAIN_MAX_CLKS];
>>> +     struct power_domain power_dev;
>>> +};
>>> +
>>> +struct imx8m_blk_ctrl {
>>> +     void __iomem *base;
>>> +     struct power_domain bus_power_dev;
>>> +     struct imx8m_blk_ctrl_domain *domains;
>>> +};
>>> +
>>> +struct imx8m_blk_ctrl_domain_data {
>>> +     const char *name;
>>> +     const char * const *clk_names;
>>> +     const char *gpc_name;
>>> +     int num_clks;
>>> +     u32 rst_mask;
>>> +     u32 clk_mask;
>>> +     u32 mipi_phy_rst_mask;
>>> +};
>>> +
>>> +struct imx8m_blk_ctrl_data {
>>> +     int max_reg;
>>> +     const struct imx8m_blk_ctrl_domain_data *domains;
>>> +     int num_domains;
>>> +     u32 bus_rst_mask;
>>> +     u32 bus_clk_mask;
>>> +};
>>> +
>>> +static int imx8m_blk_ctrl_request(struct power_domain *power_domain)
>>> +{
>>> +     return 0;
>>> +}
>>> +
>>> +static int imx8m_blk_ctrl_free(struct power_domain *power_domain)
>>> +{
>>> +     return 0;
>>> +}
>>> +
>>> +static int imx8m_blk_ctrl_enable_domain_clk(struct udevice *dev, ulong domain_id, bool enable)
>>> +{
>>> +     int ret, i;
>>> +     struct imx8m_blk_ctrl *priv = (struct imx8m_blk_ctrl *)dev_get_priv(dev);
>>> +     struct imx8m_blk_ctrl_data *drv_data =
>>> +             (struct imx8m_blk_ctrl_data *)dev_get_driver_data(dev);
>>> +
>>> +     debug("%s num_clk %u\n", __func__, drv_data->domains[domain_id].num_clks);
>>> +
>>> +     for (i = 0; i < drv_data->domains[domain_id].num_clks; i++) {
>>> +             debug("%s clk %s\n", __func__, drv_data->domains[domain_id].clk_names[i]);
>>> +             if (enable)
>>> +                     ret = clk_enable(&priv->domains[domain_id].clks[i]);
>>> +             else
>>> +                     ret = clk_disable(&priv->domains[domain_id].clks[i]);
>>> +             if (ret && ret != -ENOENT) {
>>> +                     printf("Failed to %s domain clk %s\n", enable ? "enable" : "disable",
>>> +                            drv_data->domains[domain_id].clk_names[i]);
>>> +                     return ret;
>>> +             }
>>> +     }
>>> +
>>> +     return 0;
>>> +}
>>> +
>>> +static int imx8m_blk_ctrl_power_on(struct power_domain *power_domain)
>>> +{
>>> +     struct udevice *dev = power_domain->dev;
>>> +     struct imx8m_blk_ctrl *priv = (struct imx8m_blk_ctrl *)dev_get_priv(dev);
>>> +     struct imx8m_blk_ctrl_data *drv_data =
>>> +             (struct imx8m_blk_ctrl_data *)dev_get_driver_data(dev);
>>> +     int ret;
>>> +
>>> +     debug("%s, id %lu\n", __func__, power_domain->id);
>>> +
>>> +     if (!priv->domains[power_domain->id].power_dev.dev)
>>> +             return -ENODEV;
>>> +
>>> +     ret = power_domain_on(&priv->bus_power_dev);
>>> +     if (ret < 0) {
>>> +             printf("Failed to power up bus domain %d\n", ret);
>>> +             return ret;
>>> +     }
>>> +
>>> +     /* Enable bus clock and deassert bus reset */
>>> +     setbits_le32(priv->base + BLK_CLK_EN, drv_data->bus_clk_mask);
>>> +     setbits_le32(priv->base + BLK_SFT_RSTN, drv_data->bus_rst_mask);
>>> +
>>> +     /* wait for reset to propagate */
>>> +     udelay(5);
>>> +
>>> +     /* put devices into reset */
>>> +     clrbits_le32(priv->base + BLK_SFT_RSTN, drv_data->domains[power_domain->id].rst_mask);
>>> +     if (drv_data->domains[power_domain->id].mipi_phy_rst_mask)
>>> +             clrbits_le32(priv->base + BLK_MIPI_RESET_DIV, d
>>> +                          rv_data->domains[power_domain->id].mipi_phy_rst_mask);
>>
>> Does this build for you?
>>
>> I needed the following fix:
>>
>> diff --git a/drivers/power/domain/imx8m-blk-ctrl.c b/drivers/power/domain/imx8m-blk-ctrl.c
>> index 4c89078b99..b772d50480 100644
>> --- a/drivers/power/domain/imx8m-blk-ctrl.c
>> +++ b/drivers/power/domain/imx8m-blk-ctrl.c
>> @@ -114,8 +114,8 @@ static int imx8m_blk_ctrl_power_on(struct power_domain *power_domain)
>>           /* put devices into reset */
>>           clrbits_le32(priv->base + BLK_SFT_RSTN, drv_data->domains[power_domain->id].rst_mask);
>>           if (drv_data->domains[power_domain->id].mipi_phy_rst_mask)
>> -               clrbits_le32(priv->base + BLK_MIPI_RESET_DIV, d
>> -                            rv_data->domains[power_domain->id].mipi_phy_rst_mask);
>> +               clrbits_le32(priv->base + BLK_MIPI_RESET_DIV,
>> +                            drv_data->domains[power_domain->id].mipi_phy_rst_mask);
>>
>>           /* enable upstream and blk-ctrl clocks to allow reset to propagate */
>>           ret = imx8m_blk_ctrl_enable_domain_clk(dev, power_domain->id, true);
>>
>> to get it building.
> 
> Yes, you're right. I made some changes suggested by patman, and before
> applying the
>   patch, I didn't recompile, so I didn't notice.
> 
>>
>> BTW: Just also working on bootlogo support for an imx8mp based board!
>>
>> I now applied your patches:
>>
>> clk: Propagate clk_set_rate() if CLK_SET_PARENT_RATE present for gate and mux
>> clk: clk-uclass: Implement CLK_OPS_PARENT_ENABLE
>>
>> And added in my adapted /drivers/clk/imx/clk-imx8mp.c (imported from linux)
>>
>> clk_dm(IMX8MP_CLK_MEDIA_AXI, imx8m_clk_composite_flags("media_axi", imx8mp_media_axi_sels,
>> ARRAY_SIZE(imx8mp_media_axi_sels), base + 0x8a00, CLK_IS_CRITICAL));
>>
>> instead of using imx8m_clk_composite, and dropped my approach to
>> get clocks up and working.
>>
>> Also dropped my similiar approach for mediablock and used your
>>
>> power: Add iMX8M block ctrl driver for dispmix
>>
>> And with this 3 patches, bootlogo works also/still fine for me!
>>
>> I did not applied/need your patches:
>>
>> clk: imx8mn: Prevent clock critical path from disabling during reparent and set_rate
>> clk: imx8mm: Prevent clock critical path from disabling during reparent and set_rate
>> clk: imx8mm: Mark IMX8MM_SYS_PLL2 and IMX8MM_SYS_PLL3 as enabled
>> clk: imx8mn: Mark IMX8MN_SYS_PLL2 and IMX8MN_SYS_PLL3 as enabled
>>
>> Of course, they are for imx8mm, but I mean I do not need similiar patches
>> for imx8mp!
>>
>> Also not applied (as for imx8mm)
>> clk: imx8mn: add video clocks support
>>
>> but as said, have similiar patch for clk-imx8mp.c
>>
>> May you check if using imx8m_clk_composite_flags() is working for you?
> 
> I will do it
> 
>>
>> I did not applied your patches 09/26 and the following patches from
>> your series, as I made a video bridge driver based on
>>
>> linux driver drivers/gpu/drm/bridge/fsl-ldb.c
>>
>> and a lcdif driver based on linux:/drivers/gpu/drm/mxsfb/lcdif_drv.c
>>
> 
> Thank you for you feedback Heiko

You are welcome!

Hmm.. unfortunately ... I had applied your 2 clock patches, which
fixed a problem with enabling parent clocks ... but they broke booting
on a carrier which has fec ethernet! After "Net: " output the board hang...

I reverted your 2 clock patches and it bootet again ... so there is
a problem ... try to get some more time to look into...

Do you have fec ethernet on your board?

Thanks!

bye,
Heiko
> 
> Regards,
> Dario
> 
>> bye,
>> Heiko
>> --
>> DENX Software Engineering GmbH,      Managing Director: Erika Unter
>> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
>> Phone: +49-8142-66989-52   Fax: +49-8142-66989-80   Email: hs@denx.de
> 
> 
> 

-- 
DENX Software Engineering GmbH,      Managing Director: Erika Unter
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-52   Fax: +49-8142-66989-80   Email: hs@denx.de

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 08/26] power: Add iMX8M block ctrl driver for dispmix
  2024-10-01  4:21       ` Heiko Schocher
@ 2024-10-01  5:01         ` Michael Nazzareno Trimarchi
  2024-10-01  5:14           ` Heiko Schocher
  0 siblings, 1 reply; 48+ messages in thread
From: Michael Nazzareno Trimarchi @ 2024-10-01  5:01 UTC (permalink / raw)
  To: hs
  Cc: Dario Binacchi, u-boot, Fabio Estevam, linux-amarula,
	Miquel Raynal, Ye Li, AKASHI Takahiro, Jaehoon Chung, Tom Rini

Hi Heko

On Tue, Oct 1, 2024 at 6:23 AM Heiko Schocher <hs@denx.de> wrote:
>
> Hi Dario,
>
> On 30.09.24 15:20, Dario Binacchi wrote:
> > Hello Heiko,
> >
> > On Tue, Sep 24, 2024 at 11:07 AM Heiko Schocher <hs@denx.de> wrote:
> >>
> >> Hello Dario,
> >>
> >> On 13.09.24 11:55, Dario Binacchi wrote:
> >>> From: Michael Trimarchi <michael@amarulasolutions.com>
> >>>
> >>> Add iMX8 block ctrl driver for displaymix on iMX8MM/iMX8MN and
> >>> mediamix on iMX8MP.
> >>>
> >>> To support blk ctrl driver, the power domain driver on iMX8M needs
> >>> update to add relevant PGC domains
> >>>
> >>> Signed-off-by: Ye Li <ye.li@nxp.com>
> >>> Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
> >>> Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
> >>> ---
> >>>
> >>>    drivers/power/domain/Kconfig              |   6 +
> >>>    drivers/power/domain/Makefile             |   1 +
> >>>    drivers/power/domain/imx8m-blk-ctrl.c     | 438 ++++++++++++++++++++++
> >>>    drivers/power/domain/imx8m-power-domain.c | 213 ++++++++++-
> >>>    4 files changed, 656 insertions(+), 2 deletions(-)
> >>>    create mode 100644 drivers/power/domain/imx8m-blk-ctrl.c
> >>>
> >>> diff --git a/drivers/power/domain/Kconfig b/drivers/power/domain/Kconfig
> >>> index bd82d2f7044b..fb006b6e8e28 100644
> >>> --- a/drivers/power/domain/Kconfig
> >>> +++ b/drivers/power/domain/Kconfig
> >>> @@ -40,6 +40,12 @@ config IMX8M_POWER_DOMAIN
> >>>          Enable support for manipulating NXP i.MX8M on-SoC power domains via
> >>>          requests to the ATF.
> >>>
> >>> +config IMX8M_BLK_CTRL
> >>> +     bool "Enable i.MX8M block control driver"
> >>> +     depends on POWER_DOMAIN && ARCH_IMX8M
> >>> +     help
> >>> +       Enable support for manipulating NXP i.MX8M on-SoC block control driver
> >>> +
> >>>    config IMX8MP_HSIOMIX_BLKCTRL
> >>>        bool "Enable i.MX8MP HSIOMIX domain driver"
> >>>        depends on POWER_DOMAIN && IMX8MP
> >>> diff --git a/drivers/power/domain/Makefile b/drivers/power/domain/Makefile
> >>> index 2daab73eb758..46849fd2a4db 100644
> >>> --- a/drivers/power/domain/Makefile
> >>> +++ b/drivers/power/domain/Makefile
> >>> @@ -8,6 +8,7 @@ obj-$(CONFIG_APPLE_PMGR_POWER_DOMAIN) += apple-pmgr.o
> >>>    obj-$(CONFIG_BCM6328_POWER_DOMAIN) += bcm6328-power-domain.o
> >>>    obj-$(CONFIG_IMX8_POWER_DOMAIN) += imx8-power-domain-legacy.o imx8-power-domain.o
> >>>    obj-$(CONFIG_IMX8M_POWER_DOMAIN) += imx8m-power-domain.o
> >>> +obj-$(CONFIG_IMX8M_BLK_CTRL) += imx8m-blk-ctrl.o
> >>>    obj-$(CONFIG_IMX8MP_HSIOMIX_BLKCTRL) += imx8mp-hsiomix.o
> >>>    obj-$(CONFIG_MTK_POWER_DOMAIN) += mtk-power-domain.o
> >>>    obj-$(CONFIG_MESON_GX_VPU_POWER_DOMAIN) += meson-gx-pwrc-vpu.o
> >>> diff --git a/drivers/power/domain/imx8m-blk-ctrl.c b/drivers/power/domain/imx8m-blk-ctrl.c
> >>> new file mode 100644
> >>> index 000000000000..4c89078b991b
> >>> --- /dev/null
> >>> +++ b/drivers/power/domain/imx8m-blk-ctrl.c
> >>> @@ -0,0 +1,438 @@
> >>> +// SPDX-License-Identifier: GPL-2.0
> >>> +/*
> >>> + * Copyright 2023 NXP
> >>> + */
> >>> +
> >>> +#include <dm.h>
> >>> +#include <malloc.h>
> >>> +#include <power-domain-uclass.h>
> >>> +#include <asm/io.h>
> >>> +#include <dm/device-internal.h>
> >>> +#include <dm/device.h>
> >>> +#include <dt-bindings/power/imx8mm-power.h>
> >>> +#include <dt-bindings/power/imx8mn-power.h>
> >>> +#include <dt-bindings/power/imx8mp-power.h>
> >>> +#include <clk.h>
> >>> +#include <linux/delay.h>
> >>> +
> >>> +#define BLK_SFT_RSTN 0x0
> >>> +#define BLK_CLK_EN   0x4
> >>> +#define BLK_MIPI_RESET_DIV   0x8 /* Mini/Nano/Plus DISPLAY_BLK_CTRL only */
> >>> +
> >>> +#define DOMAIN_MAX_CLKS 4
> >>> +
> >>> +struct imx8m_blk_ctrl_domain {
> >>> +     struct clk clks[DOMAIN_MAX_CLKS];
> >>> +     struct power_domain power_dev;
> >>> +};
> >>> +
> >>> +struct imx8m_blk_ctrl {
> >>> +     void __iomem *base;
> >>> +     struct power_domain bus_power_dev;
> >>> +     struct imx8m_blk_ctrl_domain *domains;
> >>> +};
> >>> +
> >>> +struct imx8m_blk_ctrl_domain_data {
> >>> +     const char *name;
> >>> +     const char * const *clk_names;
> >>> +     const char *gpc_name;
> >>> +     int num_clks;
> >>> +     u32 rst_mask;
> >>> +     u32 clk_mask;
> >>> +     u32 mipi_phy_rst_mask;
> >>> +};
> >>> +
> >>> +struct imx8m_blk_ctrl_data {
> >>> +     int max_reg;
> >>> +     const struct imx8m_blk_ctrl_domain_data *domains;
> >>> +     int num_domains;
> >>> +     u32 bus_rst_mask;
> >>> +     u32 bus_clk_mask;
> >>> +};
> >>> +
> >>> +static int imx8m_blk_ctrl_request(struct power_domain *power_domain)
> >>> +{
> >>> +     return 0;
> >>> +}
> >>> +
> >>> +static int imx8m_blk_ctrl_free(struct power_domain *power_domain)
> >>> +{
> >>> +     return 0;
> >>> +}
> >>> +
> >>> +static int imx8m_blk_ctrl_enable_domain_clk(struct udevice *dev, ulong domain_id, bool enable)
> >>> +{
> >>> +     int ret, i;
> >>> +     struct imx8m_blk_ctrl *priv = (struct imx8m_blk_ctrl *)dev_get_priv(dev);
> >>> +     struct imx8m_blk_ctrl_data *drv_data =
> >>> +             (struct imx8m_blk_ctrl_data *)dev_get_driver_data(dev);
> >>> +
> >>> +     debug("%s num_clk %u\n", __func__, drv_data->domains[domain_id].num_clks);
> >>> +
> >>> +     for (i = 0; i < drv_data->domains[domain_id].num_clks; i++) {
> >>> +             debug("%s clk %s\n", __func__, drv_data->domains[domain_id].clk_names[i]);
> >>> +             if (enable)
> >>> +                     ret = clk_enable(&priv->domains[domain_id].clks[i]);
> >>> +             else
> >>> +                     ret = clk_disable(&priv->domains[domain_id].clks[i]);
> >>> +             if (ret && ret != -ENOENT) {
> >>> +                     printf("Failed to %s domain clk %s\n", enable ? "enable" : "disable",
> >>> +                            drv_data->domains[domain_id].clk_names[i]);
> >>> +                     return ret;
> >>> +             }
> >>> +     }
> >>> +
> >>> +     return 0;
> >>> +}
> >>> +
> >>> +static int imx8m_blk_ctrl_power_on(struct power_domain *power_domain)
> >>> +{
> >>> +     struct udevice *dev = power_domain->dev;
> >>> +     struct imx8m_blk_ctrl *priv = (struct imx8m_blk_ctrl *)dev_get_priv(dev);
> >>> +     struct imx8m_blk_ctrl_data *drv_data =
> >>> +             (struct imx8m_blk_ctrl_data *)dev_get_driver_data(dev);
> >>> +     int ret;
> >>> +
> >>> +     debug("%s, id %lu\n", __func__, power_domain->id);
> >>> +
> >>> +     if (!priv->domains[power_domain->id].power_dev.dev)
> >>> +             return -ENODEV;
> >>> +
> >>> +     ret = power_domain_on(&priv->bus_power_dev);
> >>> +     if (ret < 0) {
> >>> +             printf("Failed to power up bus domain %d\n", ret);
> >>> +             return ret;
> >>> +     }
> >>> +
> >>> +     /* Enable bus clock and deassert bus reset */
> >>> +     setbits_le32(priv->base + BLK_CLK_EN, drv_data->bus_clk_mask);
> >>> +     setbits_le32(priv->base + BLK_SFT_RSTN, drv_data->bus_rst_mask);
> >>> +
> >>> +     /* wait for reset to propagate */
> >>> +     udelay(5);
> >>> +
> >>> +     /* put devices into reset */
> >>> +     clrbits_le32(priv->base + BLK_SFT_RSTN, drv_data->domains[power_domain->id].rst_mask);
> >>> +     if (drv_data->domains[power_domain->id].mipi_phy_rst_mask)
> >>> +             clrbits_le32(priv->base + BLK_MIPI_RESET_DIV, d
> >>> +                          rv_data->domains[power_domain->id].mipi_phy_rst_mask);
> >>
> >> Does this build for you?
> >>
> >> I needed the following fix:
> >>
> >> diff --git a/drivers/power/domain/imx8m-blk-ctrl.c b/drivers/power/domain/imx8m-blk-ctrl.c
> >> index 4c89078b99..b772d50480 100644
> >> --- a/drivers/power/domain/imx8m-blk-ctrl.c
> >> +++ b/drivers/power/domain/imx8m-blk-ctrl.c
> >> @@ -114,8 +114,8 @@ static int imx8m_blk_ctrl_power_on(struct power_domain *power_domain)
> >>           /* put devices into reset */
> >>           clrbits_le32(priv->base + BLK_SFT_RSTN, drv_data->domains[power_domain->id].rst_mask);
> >>           if (drv_data->domains[power_domain->id].mipi_phy_rst_mask)
> >> -               clrbits_le32(priv->base + BLK_MIPI_RESET_DIV, d
> >> -                            rv_data->domains[power_domain->id].mipi_phy_rst_mask);
> >> +               clrbits_le32(priv->base + BLK_MIPI_RESET_DIV,
> >> +                            drv_data->domains[power_domain->id].mipi_phy_rst_mask);
> >>
> >>           /* enable upstream and blk-ctrl clocks to allow reset to propagate */
> >>           ret = imx8m_blk_ctrl_enable_domain_clk(dev, power_domain->id, true);
> >>
> >> to get it building.
> >
> > Yes, you're right. I made some changes suggested by patman, and before
> > applying the
> >   patch, I didn't recompile, so I didn't notice.
> >
> >>
> >> BTW: Just also working on bootlogo support for an imx8mp based board!
> >>
> >> I now applied your patches:
> >>
> >> clk: Propagate clk_set_rate() if CLK_SET_PARENT_RATE present for gate and mux
> >> clk: clk-uclass: Implement CLK_OPS_PARENT_ENABLE
> >>
> >> And added in my adapted /drivers/clk/imx/clk-imx8mp.c (imported from linux)
> >>
> >> clk_dm(IMX8MP_CLK_MEDIA_AXI, imx8m_clk_composite_flags("media_axi", imx8mp_media_axi_sels,
> >> ARRAY_SIZE(imx8mp_media_axi_sels), base + 0x8a00, CLK_IS_CRITICAL));
> >>
> >> instead of using imx8m_clk_composite, and dropped my approach to
> >> get clocks up and working.
> >>
> >> Also dropped my similiar approach for mediablock and used your
> >>
> >> power: Add iMX8M block ctrl driver for dispmix
> >>
> >> And with this 3 patches, bootlogo works also/still fine for me!
> >>
> >> I did not applied/need your patches:
> >>
> >> clk: imx8mn: Prevent clock critical path from disabling during reparent and set_rate
> >> clk: imx8mm: Prevent clock critical path from disabling during reparent and set_rate
> >> clk: imx8mm: Mark IMX8MM_SYS_PLL2 and IMX8MM_SYS_PLL3 as enabled
> >> clk: imx8mn: Mark IMX8MN_SYS_PLL2 and IMX8MN_SYS_PLL3 as enabled
> >>
> >> Of course, they are for imx8mm, but I mean I do not need similiar patches
> >> for imx8mp!
> >>
> >> Also not applied (as for imx8mm)
> >> clk: imx8mn: add video clocks support
> >>
> >> but as said, have similiar patch for clk-imx8mp.c
> >>
> >> May you check if using imx8m_clk_composite_flags() is working for you?
> >
> > I will do it
> >
> >>
> >> I did not applied your patches 09/26 and the following patches from
> >> your series, as I made a video bridge driver based on
> >>
> >> linux driver drivers/gpu/drm/bridge/fsl-ldb.c
> >>
> >> and a lcdif driver based on linux:/drivers/gpu/drm/mxsfb/lcdif_drv.c
> >>
> >
> > Thank you for you feedback Heiko
>
> You are welcome!
>
> Hmm.. unfortunately ... I had applied your 2 clock patches, which
> fixed a problem with enabling parent clocks ... but they broke booting
> on a carrier which has fec ethernet! After "Net: " output the board hang...
>
> I reverted your 2 clock patches and it bootet again ... so there is
> a problem ... try to get some more time to look into...
>

We have a fec, but we had I think two patches more on it. I forget to
answer Marek
about them because I don't have my board now and because he is
partially right (or maybe right).
Anyway when we boot we could have and we have clocks that are enabled
by bootrom or SPL that
we need to declare as enable like PLL2/PLL3 those clocks are parts or
could be part of reparent so,
you need to have a reference counter on them that allow to not disable
during the down chain disable
and up chain enable. I think that what happens to your ethernet it's
that you disable some clock that is
critical to the board to survive. I had a patch merged by Tom that
prints the clock name so if you enable
the debug of the clock you will find that your board stops working
during one of this reparinting.

Can you check it?

Michael


> Do you have fec ethernet on your board?
>
> Thanks!
>
> bye,
> Heiko
> >
> > Regards,
> > Dario
> >
> >> bye,
> >> Heiko
> >> --
> >> DENX Software Engineering GmbH,      Managing Director: Erika Unter
> >> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
> >> Phone: +49-8142-66989-52   Fax: +49-8142-66989-80   Email: hs@denx.de
> >
> >
> >
>
> --
> DENX Software Engineering GmbH,      Managing Director: Erika Unter
> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
> Phone: +49-8142-66989-52   Fax: +49-8142-66989-80   Email: hs@denx.de



-- 
Michael Nazzareno Trimarchi
Co-Founder & Chief Executive Officer
M. +39 347 913 2170
michael@amarulasolutions.com
__________________________________

Amarula Solutions BV
Joop Geesinkweg 125, 1114 AB, Amsterdam, NL
T. +31 (0)85 111 9172
info@amarulasolutions.com
www.amarulasolutions.com

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 08/26] power: Add iMX8M block ctrl driver for dispmix
  2024-10-01  5:01         ` Michael Nazzareno Trimarchi
@ 2024-10-01  5:14           ` Heiko Schocher
  2024-10-01  5:51             ` Heiko Schocher
  0 siblings, 1 reply; 48+ messages in thread
From: Heiko Schocher @ 2024-10-01  5:14 UTC (permalink / raw)
  To: Michael Nazzareno Trimarchi
  Cc: Dario Binacchi, u-boot, Fabio Estevam, linux-amarula,
	Miquel Raynal, Ye Li, AKASHI Takahiro, Jaehoon Chung, Tom Rini

Hi Micahel,

On 01.10.24 07:01, Michael Nazzareno Trimarchi wrote:
> Hi Heko
> 
> On Tue, Oct 1, 2024 at 6:23 AM Heiko Schocher <hs@denx.de> wrote:
>>
>> Hi Dario,
>>
>> On 30.09.24 15:20, Dario Binacchi wrote:
>>> Hello Heiko,
>>>
>>> On Tue, Sep 24, 2024 at 11:07 AM Heiko Schocher <hs@denx.de> wrote:
>>>>
>>>> Hello Dario,
>>>>
>>>> On 13.09.24 11:55, Dario Binacchi wrote:
>>>>> From: Michael Trimarchi <michael@amarulasolutions.com>
>>>>>
>>>>> Add iMX8 block ctrl driver for displaymix on iMX8MM/iMX8MN and
>>>>> mediamix on iMX8MP.
>>>>>
>>>>> To support blk ctrl driver, the power domain driver on iMX8M needs
>>>>> update to add relevant PGC domains
>>>>>
>>>>> Signed-off-by: Ye Li <ye.li@nxp.com>
>>>>> Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
>>>>> Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
>>>>> ---
>>>>>
>>>>>     drivers/power/domain/Kconfig              |   6 +
>>>>>     drivers/power/domain/Makefile             |   1 +
>>>>>     drivers/power/domain/imx8m-blk-ctrl.c     | 438 ++++++++++++++++++++++
>>>>>     drivers/power/domain/imx8m-power-domain.c | 213 ++++++++++-
>>>>>     4 files changed, 656 insertions(+), 2 deletions(-)
>>>>>     create mode 100644 drivers/power/domain/imx8m-blk-ctrl.c
>>>>>
>>>>> diff --git a/drivers/power/domain/Kconfig b/drivers/power/domain/Kconfig
>>>>> index bd82d2f7044b..fb006b6e8e28 100644
>>>>> --- a/drivers/power/domain/Kconfig
>>>>> +++ b/drivers/power/domain/Kconfig
>>>>> @@ -40,6 +40,12 @@ config IMX8M_POWER_DOMAIN
>>>>>           Enable support for manipulating NXP i.MX8M on-SoC power domains via
>>>>>           requests to the ATF.
>>>>>
>>>>> +config IMX8M_BLK_CTRL
>>>>> +     bool "Enable i.MX8M block control driver"
>>>>> +     depends on POWER_DOMAIN && ARCH_IMX8M
>>>>> +     help
>>>>> +       Enable support for manipulating NXP i.MX8M on-SoC block control driver
>>>>> +
>>>>>     config IMX8MP_HSIOMIX_BLKCTRL
>>>>>         bool "Enable i.MX8MP HSIOMIX domain driver"
>>>>>         depends on POWER_DOMAIN && IMX8MP
>>>>> diff --git a/drivers/power/domain/Makefile b/drivers/power/domain/Makefile
>>>>> index 2daab73eb758..46849fd2a4db 100644
>>>>> --- a/drivers/power/domain/Makefile
>>>>> +++ b/drivers/power/domain/Makefile
>>>>> @@ -8,6 +8,7 @@ obj-$(CONFIG_APPLE_PMGR_POWER_DOMAIN) += apple-pmgr.o
>>>>>     obj-$(CONFIG_BCM6328_POWER_DOMAIN) += bcm6328-power-domain.o
>>>>>     obj-$(CONFIG_IMX8_POWER_DOMAIN) += imx8-power-domain-legacy.o imx8-power-domain.o
>>>>>     obj-$(CONFIG_IMX8M_POWER_DOMAIN) += imx8m-power-domain.o
>>>>> +obj-$(CONFIG_IMX8M_BLK_CTRL) += imx8m-blk-ctrl.o
>>>>>     obj-$(CONFIG_IMX8MP_HSIOMIX_BLKCTRL) += imx8mp-hsiomix.o
>>>>>     obj-$(CONFIG_MTK_POWER_DOMAIN) += mtk-power-domain.o
>>>>>     obj-$(CONFIG_MESON_GX_VPU_POWER_DOMAIN) += meson-gx-pwrc-vpu.o
>>>>> diff --git a/drivers/power/domain/imx8m-blk-ctrl.c b/drivers/power/domain/imx8m-blk-ctrl.c
>>>>> new file mode 100644
>>>>> index 000000000000..4c89078b991b
>>>>> --- /dev/null
>>>>> +++ b/drivers/power/domain/imx8m-blk-ctrl.c
>>>>> @@ -0,0 +1,438 @@
>>>>> +// SPDX-License-Identifier: GPL-2.0
>>>>> +/*
>>>>> + * Copyright 2023 NXP
>>>>> + */
>>>>> +
>>>>> +#include <dm.h>
>>>>> +#include <malloc.h>
>>>>> +#include <power-domain-uclass.h>
>>>>> +#include <asm/io.h>
>>>>> +#include <dm/device-internal.h>
>>>>> +#include <dm/device.h>
>>>>> +#include <dt-bindings/power/imx8mm-power.h>
>>>>> +#include <dt-bindings/power/imx8mn-power.h>
>>>>> +#include <dt-bindings/power/imx8mp-power.h>
>>>>> +#include <clk.h>
>>>>> +#include <linux/delay.h>
>>>>> +
>>>>> +#define BLK_SFT_RSTN 0x0
>>>>> +#define BLK_CLK_EN   0x4
>>>>> +#define BLK_MIPI_RESET_DIV   0x8 /* Mini/Nano/Plus DISPLAY_BLK_CTRL only */
>>>>> +
>>>>> +#define DOMAIN_MAX_CLKS 4
>>>>> +
>>>>> +struct imx8m_blk_ctrl_domain {
>>>>> +     struct clk clks[DOMAIN_MAX_CLKS];
>>>>> +     struct power_domain power_dev;
>>>>> +};
>>>>> +
>>>>> +struct imx8m_blk_ctrl {
>>>>> +     void __iomem *base;
>>>>> +     struct power_domain bus_power_dev;
>>>>> +     struct imx8m_blk_ctrl_domain *domains;
>>>>> +};
>>>>> +
>>>>> +struct imx8m_blk_ctrl_domain_data {
>>>>> +     const char *name;
>>>>> +     const char * const *clk_names;
>>>>> +     const char *gpc_name;
>>>>> +     int num_clks;
>>>>> +     u32 rst_mask;
>>>>> +     u32 clk_mask;
>>>>> +     u32 mipi_phy_rst_mask;
>>>>> +};
>>>>> +
>>>>> +struct imx8m_blk_ctrl_data {
>>>>> +     int max_reg;
>>>>> +     const struct imx8m_blk_ctrl_domain_data *domains;
>>>>> +     int num_domains;
>>>>> +     u32 bus_rst_mask;
>>>>> +     u32 bus_clk_mask;
>>>>> +};
>>>>> +
>>>>> +static int imx8m_blk_ctrl_request(struct power_domain *power_domain)
>>>>> +{
>>>>> +     return 0;
>>>>> +}
>>>>> +
>>>>> +static int imx8m_blk_ctrl_free(struct power_domain *power_domain)
>>>>> +{
>>>>> +     return 0;
>>>>> +}
>>>>> +
>>>>> +static int imx8m_blk_ctrl_enable_domain_clk(struct udevice *dev, ulong domain_id, bool enable)
>>>>> +{
>>>>> +     int ret, i;
>>>>> +     struct imx8m_blk_ctrl *priv = (struct imx8m_blk_ctrl *)dev_get_priv(dev);
>>>>> +     struct imx8m_blk_ctrl_data *drv_data =
>>>>> +             (struct imx8m_blk_ctrl_data *)dev_get_driver_data(dev);
>>>>> +
>>>>> +     debug("%s num_clk %u\n", __func__, drv_data->domains[domain_id].num_clks);
>>>>> +
>>>>> +     for (i = 0; i < drv_data->domains[domain_id].num_clks; i++) {
>>>>> +             debug("%s clk %s\n", __func__, drv_data->domains[domain_id].clk_names[i]);
>>>>> +             if (enable)
>>>>> +                     ret = clk_enable(&priv->domains[domain_id].clks[i]);
>>>>> +             else
>>>>> +                     ret = clk_disable(&priv->domains[domain_id].clks[i]);
>>>>> +             if (ret && ret != -ENOENT) {
>>>>> +                     printf("Failed to %s domain clk %s\n", enable ? "enable" : "disable",
>>>>> +                            drv_data->domains[domain_id].clk_names[i]);
>>>>> +                     return ret;
>>>>> +             }
>>>>> +     }
>>>>> +
>>>>> +     return 0;
>>>>> +}
>>>>> +
>>>>> +static int imx8m_blk_ctrl_power_on(struct power_domain *power_domain)
>>>>> +{
>>>>> +     struct udevice *dev = power_domain->dev;
>>>>> +     struct imx8m_blk_ctrl *priv = (struct imx8m_blk_ctrl *)dev_get_priv(dev);
>>>>> +     struct imx8m_blk_ctrl_data *drv_data =
>>>>> +             (struct imx8m_blk_ctrl_data *)dev_get_driver_data(dev);
>>>>> +     int ret;
>>>>> +
>>>>> +     debug("%s, id %lu\n", __func__, power_domain->id);
>>>>> +
>>>>> +     if (!priv->domains[power_domain->id].power_dev.dev)
>>>>> +             return -ENODEV;
>>>>> +
>>>>> +     ret = power_domain_on(&priv->bus_power_dev);
>>>>> +     if (ret < 0) {
>>>>> +             printf("Failed to power up bus domain %d\n", ret);
>>>>> +             return ret;
>>>>> +     }
>>>>> +
>>>>> +     /* Enable bus clock and deassert bus reset */
>>>>> +     setbits_le32(priv->base + BLK_CLK_EN, drv_data->bus_clk_mask);
>>>>> +     setbits_le32(priv->base + BLK_SFT_RSTN, drv_data->bus_rst_mask);
>>>>> +
>>>>> +     /* wait for reset to propagate */
>>>>> +     udelay(5);
>>>>> +
>>>>> +     /* put devices into reset */
>>>>> +     clrbits_le32(priv->base + BLK_SFT_RSTN, drv_data->domains[power_domain->id].rst_mask);
>>>>> +     if (drv_data->domains[power_domain->id].mipi_phy_rst_mask)
>>>>> +             clrbits_le32(priv->base + BLK_MIPI_RESET_DIV, d
>>>>> +                          rv_data->domains[power_domain->id].mipi_phy_rst_mask);
>>>>
>>>> Does this build for you?
>>>>
>>>> I needed the following fix:
>>>>
>>>> diff --git a/drivers/power/domain/imx8m-blk-ctrl.c b/drivers/power/domain/imx8m-blk-ctrl.c
>>>> index 4c89078b99..b772d50480 100644
>>>> --- a/drivers/power/domain/imx8m-blk-ctrl.c
>>>> +++ b/drivers/power/domain/imx8m-blk-ctrl.c
>>>> @@ -114,8 +114,8 @@ static int imx8m_blk_ctrl_power_on(struct power_domain *power_domain)
>>>>            /* put devices into reset */
>>>>            clrbits_le32(priv->base + BLK_SFT_RSTN, drv_data->domains[power_domain->id].rst_mask);
>>>>            if (drv_data->domains[power_domain->id].mipi_phy_rst_mask)
>>>> -               clrbits_le32(priv->base + BLK_MIPI_RESET_DIV, d
>>>> -                            rv_data->domains[power_domain->id].mipi_phy_rst_mask);
>>>> +               clrbits_le32(priv->base + BLK_MIPI_RESET_DIV,
>>>> +                            drv_data->domains[power_domain->id].mipi_phy_rst_mask);
>>>>
>>>>            /* enable upstream and blk-ctrl clocks to allow reset to propagate */
>>>>            ret = imx8m_blk_ctrl_enable_domain_clk(dev, power_domain->id, true);
>>>>
>>>> to get it building.
>>>
>>> Yes, you're right. I made some changes suggested by patman, and before
>>> applying the
>>>    patch, I didn't recompile, so I didn't notice.
>>>
>>>>
>>>> BTW: Just also working on bootlogo support for an imx8mp based board!
>>>>
>>>> I now applied your patches:
>>>>
>>>> clk: Propagate clk_set_rate() if CLK_SET_PARENT_RATE present for gate and mux
>>>> clk: clk-uclass: Implement CLK_OPS_PARENT_ENABLE
>>>>
>>>> And added in my adapted /drivers/clk/imx/clk-imx8mp.c (imported from linux)
>>>>
>>>> clk_dm(IMX8MP_CLK_MEDIA_AXI, imx8m_clk_composite_flags("media_axi", imx8mp_media_axi_sels,
>>>> ARRAY_SIZE(imx8mp_media_axi_sels), base + 0x8a00, CLK_IS_CRITICAL));
>>>>
>>>> instead of using imx8m_clk_composite, and dropped my approach to
>>>> get clocks up and working.
>>>>
>>>> Also dropped my similiar approach for mediablock and used your
>>>>
>>>> power: Add iMX8M block ctrl driver for dispmix
>>>>
>>>> And with this 3 patches, bootlogo works also/still fine for me!
>>>>
>>>> I did not applied/need your patches:
>>>>
>>>> clk: imx8mn: Prevent clock critical path from disabling during reparent and set_rate
>>>> clk: imx8mm: Prevent clock critical path from disabling during reparent and set_rate
>>>> clk: imx8mm: Mark IMX8MM_SYS_PLL2 and IMX8MM_SYS_PLL3 as enabled
>>>> clk: imx8mn: Mark IMX8MN_SYS_PLL2 and IMX8MN_SYS_PLL3 as enabled
>>>>
>>>> Of course, they are for imx8mm, but I mean I do not need similiar patches
>>>> for imx8mp!
>>>>
>>>> Also not applied (as for imx8mm)
>>>> clk: imx8mn: add video clocks support
>>>>
>>>> but as said, have similiar patch for clk-imx8mp.c
>>>>
>>>> May you check if using imx8m_clk_composite_flags() is working for you?
>>>
>>> I will do it
>>>
>>>>
>>>> I did not applied your patches 09/26 and the following patches from
>>>> your series, as I made a video bridge driver based on
>>>>
>>>> linux driver drivers/gpu/drm/bridge/fsl-ldb.c
>>>>
>>>> and a lcdif driver based on linux:/drivers/gpu/drm/mxsfb/lcdif_drv.c
>>>>
>>>
>>> Thank you for you feedback Heiko
>>
>> You are welcome!
>>
>> Hmm.. unfortunately ... I had applied your 2 clock patches, which
>> fixed a problem with enabling parent clocks ... but they broke booting
>> on a carrier which has fec ethernet! After "Net: " output the board hang...
>>
>> I reverted your 2 clock patches and it bootet again ... so there is
>> a problem ... try to get some more time to look into...
>>
> 
> We have a fec, but we had I think two patches more on it. I forget to
> answer Marek
> about them because I don't have my board now and because he is
> partially right (or maybe right).
> Anyway when we boot we could have and we have clocks that are enabled
> by bootrom or SPL that
> we need to declare as enable like PLL2/PLL3 those clocks are parts or
> could be part of reparent so,
> you need to have a reference counter on them that allow to not disable
> during the down chain disable
> and up chain enable. I think that what happens to your ethernet it's
> that you disable some clock that is
> critical to the board to survive. I had a patch merged by Tom that

Yep, thats what I think too! If you access registers in a block for
which the clock is not enabled ... it just hang...

> prints the clock name so if you enable
> the debug of the clock you will find that your board stops working
> during one of this reparinting.

I currently work on 2024.07... will rebase if 2024.10 is out...

Ah, you mean:

commit a70d991212c9684e09ed80ece69ce1ff7bfd9f08
Author: Michael Trimarchi <michael@amarulasolutions.com>
Date:   Tue Jul 9 08:28:13 2024 +0200

     clk: clk-uclass: Print clk name in clk_enable/clk_disable

     Print clk name in clk_enable and clk_disable. Make sense to know
     what clock get disabled/enabled before a system crash or system
     hang.

     Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>

I have the same change when I debug :-P

IIRC I did not see the clock names ... but I will recheck!

Thanks!

> Can you check it?

Yep, will do.

bye,
Heiko
> 
> Michael
> 
> 
>> Do you have fec ethernet on your board?
>>
>> Thanks!
>>
>> bye,
>> Heiko
>>>
>>> Regards,
>>> Dario
>>>
>>>> bye,
>>>> Heiko
>>>> --
>>>> DENX Software Engineering GmbH,      Managing Director: Erika Unter
>>>> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
>>>> Phone: +49-8142-66989-52   Fax: +49-8142-66989-80   Email: hs@denx.de
>>>
>>>
>>>
>>
>> --
>> DENX Software Engineering GmbH,      Managing Director: Erika Unter
>> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
>> Phone: +49-8142-66989-52   Fax: +49-8142-66989-80   Email: hs@denx.de
> 
> 
> 

-- 
DENX Software Engineering GmbH,      Managing Director: Erika Unter
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-52   Fax: +49-8142-66989-80   Email: hs@denx.de

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 08/26] power: Add iMX8M block ctrl driver for dispmix
  2024-10-01  5:14           ` Heiko Schocher
@ 2024-10-01  5:51             ` Heiko Schocher
  2024-10-01  8:29               ` Miquel Raynal
  0 siblings, 1 reply; 48+ messages in thread
From: Heiko Schocher @ 2024-10-01  5:51 UTC (permalink / raw)
  To: Michael Nazzareno Trimarchi
  Cc: Dario Binacchi, u-boot, Fabio Estevam, linux-amarula,
	Miquel Raynal, Ye Li, AKASHI Takahiro, Jaehoon Chung, Tom Rini

Hello Michael,

On 01.10.24 07:14, Heiko Schocher wrote:
> Hi Micahel,
> 
> On 01.10.24 07:01, Michael Nazzareno Trimarchi wrote:
>> Hi Heko
>>
>> On Tue, Oct 1, 2024 at 6:23 AM Heiko Schocher <hs@denx.de> wrote:
>>>
>>> Hi Dario,
>>>
>>> On 30.09.24 15:20, Dario Binacchi wrote:
>>>> Hello Heiko,
>>>>
>>>> On Tue, Sep 24, 2024 at 11:07 AM Heiko Schocher <hs@denx.de> wrote:
>>>>>
>>>>> Hello Dario,
>>>>>
>>>>> On 13.09.24 11:55, Dario Binacchi wrote:
>>>>>> From: Michael Trimarchi <michael@amarulasolutions.com>
>>>>>>
>>>>>> Add iMX8 block ctrl driver for displaymix on iMX8MM/iMX8MN and
>>>>>> mediamix on iMX8MP.
>>>>>>
>>>>>> To support blk ctrl driver, the power domain driver on iMX8M needs
>>>>>> update to add relevant PGC domains
>>>>>>
>>>>>> Signed-off-by: Ye Li <ye.li@nxp.com>
>>>>>> Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
>>>>>> Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
>>>>>> ---
>>>>>>
>>>>>>     drivers/power/domain/Kconfig              |   6 +
>>>>>>     drivers/power/domain/Makefile             |   1 +
>>>>>>     drivers/power/domain/imx8m-blk-ctrl.c     | 438 ++++++++++++++++++++++
>>>>>>     drivers/power/domain/imx8m-power-domain.c | 213 ++++++++++-
>>>>>>     4 files changed, 656 insertions(+), 2 deletions(-)
>>>>>>     create mode 100644 drivers/power/domain/imx8m-blk-ctrl.c
>>>>>>
>>>>>> diff --git a/drivers/power/domain/Kconfig b/drivers/power/domain/Kconfig
>>>>>> index bd82d2f7044b..fb006b6e8e28 100644
>>>>>> --- a/drivers/power/domain/Kconfig
>>>>>> +++ b/drivers/power/domain/Kconfig
>>>>>> @@ -40,6 +40,12 @@ config IMX8M_POWER_DOMAIN
>>>>>>           Enable support for manipulating NXP i.MX8M on-SoC power domains via
>>>>>>           requests to the ATF.
>>>>>>
>>>>>> +config IMX8M_BLK_CTRL
>>>>>> +     bool "Enable i.MX8M block control driver"
>>>>>> +     depends on POWER_DOMAIN && ARCH_IMX8M
>>>>>> +     help
>>>>>> +       Enable support for manipulating NXP i.MX8M on-SoC block control driver
>>>>>> +
>>>>>>     config IMX8MP_HSIOMIX_BLKCTRL
>>>>>>         bool "Enable i.MX8MP HSIOMIX domain driver"
>>>>>>         depends on POWER_DOMAIN && IMX8MP
>>>>>> diff --git a/drivers/power/domain/Makefile b/drivers/power/domain/Makefile
>>>>>> index 2daab73eb758..46849fd2a4db 100644
>>>>>> --- a/drivers/power/domain/Makefile
>>>>>> +++ b/drivers/power/domain/Makefile
>>>>>> @@ -8,6 +8,7 @@ obj-$(CONFIG_APPLE_PMGR_POWER_DOMAIN) += apple-pmgr.o
>>>>>>     obj-$(CONFIG_BCM6328_POWER_DOMAIN) += bcm6328-power-domain.o
>>>>>>     obj-$(CONFIG_IMX8_POWER_DOMAIN) += imx8-power-domain-legacy.o imx8-power-domain.o
>>>>>>     obj-$(CONFIG_IMX8M_POWER_DOMAIN) += imx8m-power-domain.o
>>>>>> +obj-$(CONFIG_IMX8M_BLK_CTRL) += imx8m-blk-ctrl.o
>>>>>>     obj-$(CONFIG_IMX8MP_HSIOMIX_BLKCTRL) += imx8mp-hsiomix.o
>>>>>>     obj-$(CONFIG_MTK_POWER_DOMAIN) += mtk-power-domain.o
>>>>>>     obj-$(CONFIG_MESON_GX_VPU_POWER_DOMAIN) += meson-gx-pwrc-vpu.o
>>>>>> diff --git a/drivers/power/domain/imx8m-blk-ctrl.c b/drivers/power/domain/imx8m-blk-ctrl.c
>>>>>> new file mode 100644
>>>>>> index 000000000000..4c89078b991b
>>>>>> --- /dev/null
>>>>>> +++ b/drivers/power/domain/imx8m-blk-ctrl.c
>>>>>> @@ -0,0 +1,438 @@
>>>>>> +// SPDX-License-Identifier: GPL-2.0
>>>>>> +/*
>>>>>> + * Copyright 2023 NXP
>>>>>> + */
>>>>>> +
>>>>>> +#include <dm.h>
>>>>>> +#include <malloc.h>
>>>>>> +#include <power-domain-uclass.h>
>>>>>> +#include <asm/io.h>
>>>>>> +#include <dm/device-internal.h>
>>>>>> +#include <dm/device.h>
>>>>>> +#include <dt-bindings/power/imx8mm-power.h>
>>>>>> +#include <dt-bindings/power/imx8mn-power.h>
>>>>>> +#include <dt-bindings/power/imx8mp-power.h>
>>>>>> +#include <clk.h>
>>>>>> +#include <linux/delay.h>
>>>>>> +
>>>>>> +#define BLK_SFT_RSTN 0x0
>>>>>> +#define BLK_CLK_EN   0x4
>>>>>> +#define BLK_MIPI_RESET_DIV   0x8 /* Mini/Nano/Plus DISPLAY_BLK_CTRL only */
>>>>>> +
>>>>>> +#define DOMAIN_MAX_CLKS 4
>>>>>> +
>>>>>> +struct imx8m_blk_ctrl_domain {
>>>>>> +     struct clk clks[DOMAIN_MAX_CLKS];
>>>>>> +     struct power_domain power_dev;
>>>>>> +};
>>>>>> +
>>>>>> +struct imx8m_blk_ctrl {
>>>>>> +     void __iomem *base;
>>>>>> +     struct power_domain bus_power_dev;
>>>>>> +     struct imx8m_blk_ctrl_domain *domains;
>>>>>> +};
>>>>>> +
>>>>>> +struct imx8m_blk_ctrl_domain_data {
>>>>>> +     const char *name;
>>>>>> +     const char * const *clk_names;
>>>>>> +     const char *gpc_name;
>>>>>> +     int num_clks;
>>>>>> +     u32 rst_mask;
>>>>>> +     u32 clk_mask;
>>>>>> +     u32 mipi_phy_rst_mask;
>>>>>> +};
>>>>>> +
>>>>>> +struct imx8m_blk_ctrl_data {
>>>>>> +     int max_reg;
>>>>>> +     const struct imx8m_blk_ctrl_domain_data *domains;
>>>>>> +     int num_domains;
>>>>>> +     u32 bus_rst_mask;
>>>>>> +     u32 bus_clk_mask;
>>>>>> +};
>>>>>> +
>>>>>> +static int imx8m_blk_ctrl_request(struct power_domain *power_domain)
>>>>>> +{
>>>>>> +     return 0;
>>>>>> +}
>>>>>> +
>>>>>> +static int imx8m_blk_ctrl_free(struct power_domain *power_domain)
>>>>>> +{
>>>>>> +     return 0;
>>>>>> +}
>>>>>> +
>>>>>> +static int imx8m_blk_ctrl_enable_domain_clk(struct udevice *dev, ulong domain_id, bool enable)
>>>>>> +{
>>>>>> +     int ret, i;
>>>>>> +     struct imx8m_blk_ctrl *priv = (struct imx8m_blk_ctrl *)dev_get_priv(dev);
>>>>>> +     struct imx8m_blk_ctrl_data *drv_data =
>>>>>> +             (struct imx8m_blk_ctrl_data *)dev_get_driver_data(dev);
>>>>>> +
>>>>>> +     debug("%s num_clk %u\n", __func__, drv_data->domains[domain_id].num_clks);
>>>>>> +
>>>>>> +     for (i = 0; i < drv_data->domains[domain_id].num_clks; i++) {
>>>>>> +             debug("%s clk %s\n", __func__, drv_data->domains[domain_id].clk_names[i]);
>>>>>> +             if (enable)
>>>>>> +                     ret = clk_enable(&priv->domains[domain_id].clks[i]);
>>>>>> +             else
>>>>>> +                     ret = clk_disable(&priv->domains[domain_id].clks[i]);
>>>>>> +             if (ret && ret != -ENOENT) {
>>>>>> +                     printf("Failed to %s domain clk %s\n", enable ? "enable" : "disable",
>>>>>> +                            drv_data->domains[domain_id].clk_names[i]);
>>>>>> +                     return ret;
>>>>>> +             }
>>>>>> +     }
>>>>>> +
>>>>>> +     return 0;
>>>>>> +}
>>>>>> +
>>>>>> +static int imx8m_blk_ctrl_power_on(struct power_domain *power_domain)
>>>>>> +{
>>>>>> +     struct udevice *dev = power_domain->dev;
>>>>>> +     struct imx8m_blk_ctrl *priv = (struct imx8m_blk_ctrl *)dev_get_priv(dev);
>>>>>> +     struct imx8m_blk_ctrl_data *drv_data =
>>>>>> +             (struct imx8m_blk_ctrl_data *)dev_get_driver_data(dev);
>>>>>> +     int ret;
>>>>>> +
>>>>>> +     debug("%s, id %lu\n", __func__, power_domain->id);
>>>>>> +
>>>>>> +     if (!priv->domains[power_domain->id].power_dev.dev)
>>>>>> +             return -ENODEV;
>>>>>> +
>>>>>> +     ret = power_domain_on(&priv->bus_power_dev);
>>>>>> +     if (ret < 0) {
>>>>>> +             printf("Failed to power up bus domain %d\n", ret);
>>>>>> +             return ret;
>>>>>> +     }
>>>>>> +
>>>>>> +     /* Enable bus clock and deassert bus reset */
>>>>>> +     setbits_le32(priv->base + BLK_CLK_EN, drv_data->bus_clk_mask);
>>>>>> +     setbits_le32(priv->base + BLK_SFT_RSTN, drv_data->bus_rst_mask);
>>>>>> +
>>>>>> +     /* wait for reset to propagate */
>>>>>> +     udelay(5);
>>>>>> +
>>>>>> +     /* put devices into reset */
>>>>>> +     clrbits_le32(priv->base + BLK_SFT_RSTN, drv_data->domains[power_domain->id].rst_mask);
>>>>>> +     if (drv_data->domains[power_domain->id].mipi_phy_rst_mask)
>>>>>> +             clrbits_le32(priv->base + BLK_MIPI_RESET_DIV, d
>>>>>> +                          rv_data->domains[power_domain->id].mipi_phy_rst_mask);
>>>>>
>>>>> Does this build for you?
>>>>>
>>>>> I needed the following fix:
>>>>>
>>>>> diff --git a/drivers/power/domain/imx8m-blk-ctrl.c b/drivers/power/domain/imx8m-blk-ctrl.c
>>>>> index 4c89078b99..b772d50480 100644
>>>>> --- a/drivers/power/domain/imx8m-blk-ctrl.c
>>>>> +++ b/drivers/power/domain/imx8m-blk-ctrl.c
>>>>> @@ -114,8 +114,8 @@ static int imx8m_blk_ctrl_power_on(struct power_domain *power_domain)
>>>>>            /* put devices into reset */
>>>>>            clrbits_le32(priv->base + BLK_SFT_RSTN, drv_data->domains[power_domain->id].rst_mask);
>>>>>            if (drv_data->domains[power_domain->id].mipi_phy_rst_mask)
>>>>> -               clrbits_le32(priv->base + BLK_MIPI_RESET_DIV, d
>>>>> -                            rv_data->domains[power_domain->id].mipi_phy_rst_mask);
>>>>> +               clrbits_le32(priv->base + BLK_MIPI_RESET_DIV,
>>>>> +                            drv_data->domains[power_domain->id].mipi_phy_rst_mask);
>>>>>
>>>>>            /* enable upstream and blk-ctrl clocks to allow reset to propagate */
>>>>>            ret = imx8m_blk_ctrl_enable_domain_clk(dev, power_domain->id, true);
>>>>>
>>>>> to get it building.
>>>>
>>>> Yes, you're right. I made some changes suggested by patman, and before
>>>> applying the
>>>>    patch, I didn't recompile, so I didn't notice.
>>>>
>>>>>
>>>>> BTW: Just also working on bootlogo support for an imx8mp based board!
>>>>>
>>>>> I now applied your patches:
>>>>>
>>>>> clk: Propagate clk_set_rate() if CLK_SET_PARENT_RATE present for gate and mux
>>>>> clk: clk-uclass: Implement CLK_OPS_PARENT_ENABLE
>>>>>
>>>>> And added in my adapted /drivers/clk/imx/clk-imx8mp.c (imported from linux)
>>>>>
>>>>> clk_dm(IMX8MP_CLK_MEDIA_AXI, imx8m_clk_composite_flags("media_axi", imx8mp_media_axi_sels,
>>>>> ARRAY_SIZE(imx8mp_media_axi_sels), base + 0x8a00, CLK_IS_CRITICAL));
>>>>>
>>>>> instead of using imx8m_clk_composite, and dropped my approach to
>>>>> get clocks up and working.
>>>>>
>>>>> Also dropped my similiar approach for mediablock and used your
>>>>>
>>>>> power: Add iMX8M block ctrl driver for dispmix
>>>>>
>>>>> And with this 3 patches, bootlogo works also/still fine for me!
>>>>>
>>>>> I did not applied/need your patches:
>>>>>
>>>>> clk: imx8mn: Prevent clock critical path from disabling during reparent and set_rate
>>>>> clk: imx8mm: Prevent clock critical path from disabling during reparent and set_rate
>>>>> clk: imx8mm: Mark IMX8MM_SYS_PLL2 and IMX8MM_SYS_PLL3 as enabled
>>>>> clk: imx8mn: Mark IMX8MN_SYS_PLL2 and IMX8MN_SYS_PLL3 as enabled
>>>>>
>>>>> Of course, they are for imx8mm, but I mean I do not need similiar patches
>>>>> for imx8mp!
>>>>>
>>>>> Also not applied (as for imx8mm)
>>>>> clk: imx8mn: add video clocks support
>>>>>
>>>>> but as said, have similiar patch for clk-imx8mp.c
>>>>>
>>>>> May you check if using imx8m_clk_composite_flags() is working for you?
>>>>
>>>> I will do it
>>>>
>>>>>
>>>>> I did not applied your patches 09/26 and the following patches from
>>>>> your series, as I made a video bridge driver based on
>>>>>
>>>>> linux driver drivers/gpu/drm/bridge/fsl-ldb.c
>>>>>
>>>>> and a lcdif driver based on linux:/drivers/gpu/drm/mxsfb/lcdif_drv.c
>>>>>
>>>>
>>>> Thank you for you feedback Heiko
>>>
>>> You are welcome!
>>>
>>> Hmm.. unfortunately ... I had applied your 2 clock patches, which
>>> fixed a problem with enabling parent clocks ... but they broke booting
>>> on a carrier which has fec ethernet! After "Net: " output the board hang...
>>>
>>> I reverted your 2 clock patches and it bootet again ... so there is
>>> a problem ... try to get some more time to look into...
>>>
>>
>> We have a fec, but we had I think two patches more on it. I forget to
>> answer Marek
>> about them because I don't have my board now and because he is
>> partially right (or maybe right).
>> Anyway when we boot we could have and we have clocks that are enabled
>> by bootrom or SPL that
>> we need to declare as enable like PLL2/PLL3 those clocks are parts or
>> could be part of reparent so,
>> you need to have a reference counter on them that allow to not disable
>> during the down chain disable
>> and up chain enable. I think that what happens to your ethernet it's
>> that you disable some clock that is
>> critical to the board to survive. I had a patch merged by Tom that
> 
> Yep, thats what I think too! If you access registers in a block for
> which the clock is not enabled ... it just hang...
> 
>> prints the clock name so if you enable
>> the debug of the clock you will find that your board stops working
>> during one of this reparinting.
> 
> I currently work on 2024.07... will rebase if 2024.10 is out...
> 
> Ah, you mean:
> 
> commit a70d991212c9684e09ed80ece69ce1ff7bfd9f08
> Author: Michael Trimarchi <michael@amarulasolutions.com>
> Date:   Tue Jul 9 08:28:13 2024 +0200
> 
>      clk: clk-uclass: Print clk name in clk_enable/clk_disable
> 
>      Print clk name in clk_enable and clk_disable. Make sense to know
>      what clock get disabled/enabled before a system crash or system
>      hang.
> 
>      Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
> 
> I have the same change when I debug :-P
> 
> IIRC I did not see the clock names ... but I will recheck!

I see with your patch the clock names, so fine... and see [1]

Hmm... I am on imx8mp, and I think the changes the patchset do in

"clk: imx8mn: Prevent clock critical path from disabling during reparent and set_rate"

are in clk-imx8mp already ...

Ported the patch from patchset

"[PATCH 05/26] clk: imx8mm: Mark IMX8MM_SYS_PLL2 and IMX8MM_SYS_PLL3 as enabled"

to imx8mp [2] and fec ethernet works again for me on imx8mp!

Could you add this if you post a v2 ?

bye,
Heiko
[1]
│   │    <> Net:   clk_set_defaults(gpio@30230000)
│   │    <> clk_set_default_parents: could not read assigned-clock-parents for 00000000fee74d90 
name=gpio@30230000
│   │    <> clk_set_defaults(aristainetos3-fec-rgmii-grp)
│   │    <> clk_set_default_parents: could not read assigned-clock-parents for 00000000fee75780 
name=aristainetos3-fec-rgmii-grp
│   │    <> clk_set_defaults(ethernet@30be0000)
│   │    <> clk_get_by_indexed_prop(dev=00000000fee7ad20, index=0, clk=00000000fee5e3b8)
│   │    <> clk_of_xlate_default(clk=00000000fee5e3b8)
│   │    <> clk_request(dev=00000000fee77480, clk=00000000fee5e3b8)
│   │    <> clk_get_by_indexed_prop(dev=00000000fee7ad20, index=0, clk=00000000fee5e390)
│   │    <> clk_of_xlate_default(clk=00000000fee5e390)
│   │    <> clk_request(dev=00000000fee77480, clk=00000000fee5e390)
│   │    <> clk_set_parent(clk=00000000fee825c0, parent=00000000fee80680)
│   │    <> clk_get_parent(clk=00000000fee825c0)
│   │    <> clk_enable(clk=00000000fee743d0 name=clock-osc-24m)
│   │    <> clk_enable(clk=00000000fee80680 name=sys_pll1_266m)
│   │    <> clk_enable(clk=00000000fee7fb40 name=sys_pll1_out)
│   │    <> clk_disable(clk=00000000fee80680 name=sys_pll1_266m)
│   │    <> clk_disable(clk=00000000fee7fb40 name=sys_pll1_out)
│   │    <> clk_disable(clk=00000000fee743d0 name=clock-osc-24m)
│   │    <> clk_get_by_indexed_prop(dev=00000000fee7ad20, index=1, clk=00000000fee5e3b8)
│   │    <> clk_of_xlate_default(clk=00000000fee5e3b8)
│   │    <> clk_request(dev=00000000fee77480, clk=00000000fee5e3b8)
│   │    <> clk_get_by_indexed_prop(dev=00000000fee7ad20, index=1, clk=00000000fee5e390)
│   │    <> clk_of_xlate_default(clk=00000000fee5e390)
│   │    <> clk_request(dev=00000000fee77480, clk=00000000fee5e390)
│   │    <> clk_set_parent(clk=00000000fee85b80, parent=00000000fee80b80)
│   │    <> clk_get_parent(clk=00000000fee85b80)
│   │    <> clk_enable(clk=00000000fee743d0 name=clock-osc-24m)
│   │    <> clk_enable(clk=00000000fee80b80 name=sys_pll2_100m)
│   │    <> clk_enable(clk=00000000fee7fc80 name=sys_pll2_out)
│   │    <> clk_enable(clk=00000000fee7f480 name=sys_pll2_bypass)
│   │    <> clk_enable(clk=00000000fee7eb80 name=sys_pll2)
│   │    <> clk_enable(clk=00000000fee7e280 name=sys_pll2_ref_sel)
│   │    <> clk_enable(clk=00000000fee743d0 name=clock-osc-24m)
│   │    <> clk_disable(clk=00000000fee80b80 name=sys_pll2_100m)
│   │    <> clk_disable(clk=00000000fee7fc80 name=sys_pll2_out)
│   │    <> clk_disable(clk=00000000fee7f480 name=sys_pll2_bypass)
│   │    <> clk_disable(clk=00000000fee7eb80 name=sys_pll2)

[2]
diff --git a/drivers/clk/imx/clk-imx8mp.c b/drivers/clk/imx/clk-imx8mp.c
index d6865509cb..f6fa66094d 100644
--- a/drivers/clk/imx/clk-imx8mp.c
+++ b/drivers/clk/imx/clk-imx8mp.c
@@ -235,6 +235,7 @@ static const char * const imx8mp_clkout_sels[] = {"audio_pll1_out", "audio_pll2_
  static int imx8mp_clk_probe(struct udevice *dev)
  {
         struct clk osc_24m_clk, osc_32k_clk;
+       struct clk *clk;
         void __iomem *base;
         int ret;

@@ -303,6 +304,14 @@ static int imx8mp_clk_probe(struct udevice *dev)
                 return ret;
         clk_dm(IMX8MP_CLK_32K, dev_get_clk_ptr(osc_32k_clk.dev));

+       ret = clk_get_by_id(IMX8MP_SYS_PLL2, &clk);
+       if (!ret)
+               clk_enable(clk);
+
+       ret = clk_get_by_id(IMX8MP_SYS_PLL3, &clk);
+       if (!ret)
+               clk_enable(clk);
+
         base = dev_read_addr_ptr(dev);
         if (!base)
                 return -EINVAL;
-- 
DENX Software Engineering GmbH,      Managing Director: Erika Unter
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-52   Fax: +49-8142-66989-80   Email: hs@denx.de

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* Re: [PATCH 08/26] power: Add iMX8M block ctrl driver for dispmix
  2024-10-01  5:51             ` Heiko Schocher
@ 2024-10-01  8:29               ` Miquel Raynal
  2024-10-01  8:33                 ` Michael Nazzareno Trimarchi
  2024-10-01  8:47                 ` Heiko Schocher
  0 siblings, 2 replies; 48+ messages in thread
From: Miquel Raynal @ 2024-10-01  8:29 UTC (permalink / raw)
  To: Heiko Schocher
  Cc: Michael Nazzareno Trimarchi, Dario Binacchi, u-boot,
	Fabio Estevam, linux-amarula, Ye Li, AKASHI Takahiro,
	Jaehoon Chung, Tom Rini

Hi Heiko,


> >>> Hmm.. unfortunately ... I had applied your 2 clock patches, which
> >>> fixed a problem with enabling parent clocks ... but they broke booting
> >>> on a carrier which has fec ethernet! After "Net: " output the board hang...
> >>>
> >>> I reverted your 2 clock patches and it bootet again ... so there is
> >>> a problem ... try to get some more time to look into...
> >>>  
> >>
> >> We have a fec, but we had I think two patches more on it. I forget to
> >> answer Marek
> >> about them because I don't have my board now and because he is
> >> partially right (or maybe right).
> >> Anyway when we boot we could have and we have clocks that are enabled
> >> by bootrom or SPL that
> >> we need to declare as enable like PLL2/PLL3 those clocks are parts or
> >> could be part of reparent so,
> >> you need to have a reference counter on them that allow to not disable
> >> during the down chain disable
> >> and up chain enable. I think that what happens to your ethernet it's
> >> that you disable some clock that is
> >> critical to the board to survive. I had a patch merged by Tom that  
> > 
> > Yep, thats what I think too! If you access registers in a block for
> > which the clock is not enabled ... it just hang...
> >   
> >> prints the clock name so if you enable
> >> the debug of the clock you will find that your board stops working
> >> during one of this reparinting.  
> > 
> > I currently work on 2024.07... will rebase if 2024.10 is out...
> > 
> > Ah, you mean:
> > 
> > commit a70d991212c9684e09ed80ece69ce1ff7bfd9f08
> > Author: Michael Trimarchi <michael@amarulasolutions.com>
> > Date:   Tue Jul 9 08:28:13 2024 +0200
> > 
> >      clk: clk-uclass: Print clk name in clk_enable/clk_disable
> > 
> >      Print clk name in clk_enable and clk_disable. Make sense to know
> >      what clock get disabled/enabled before a system crash or system
> >      hang.
> > 
> >      Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
> > 
> > I have the same change when I debug :-P
> > 
> > IIRC I did not see the clock names ... but I will recheck!  
> 
> I see with your patch the clock names, so fine... and see [1]
> 
> Hmm... I am on imx8mp, and I think the changes the patchset do in
> 
> "clk: imx8mn: Prevent clock critical path from disabling during reparent and set_rate"
> 
> are in clk-imx8mp already ...
> 
> Ported the patch from patchset
> 
> "[PATCH 05/26] clk: imx8mm: Mark IMX8MM_SYS_PLL2 and IMX8MM_SYS_PLL3 as enabled"
> 
> to imx8mp [2] and fec ethernet works again for me on imx8mp!
> 
> Could you add this if you post a v2 ?

TBH I don't feel like the below change is the correct one, it is too
specific. The clock core is recursive and thus should handle the
reparenting situations gracefully.

I posted a series that is targeting the LVDS output on imx8mp. You
should probably consider checking these patches as well if you work
on imx8mp as well. I also had similar breakages with Ethernet which
happened during the assigned-clocks handling. This patch, which is more
future and platform agnostic, fixed it:

https://lore.kernel.org/u-boot/20240910101344.110633-3-miquel.raynal@bootlin.com/

My series is complimentary, even though there are some overlaps that we
need to merge.

Thanks,
Miquèl

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 08/26] power: Add iMX8M block ctrl driver for dispmix
  2024-10-01  8:29               ` Miquel Raynal
@ 2024-10-01  8:33                 ` Michael Nazzareno Trimarchi
  2024-10-01  8:50                   ` Miquel Raynal
  2024-10-01  8:47                 ` Heiko Schocher
  1 sibling, 1 reply; 48+ messages in thread
From: Michael Nazzareno Trimarchi @ 2024-10-01  8:33 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Heiko Schocher, Dario Binacchi, u-boot, Fabio Estevam,
	linux-amarula, Ye Li, AKASHI Takahiro, Jaehoon Chung, Tom Rini

Hi Miguel

On Tue, Oct 1, 2024 at 10:29 AM Miquel Raynal <miquel.raynal@bootlin.com> wrote:
>
> Hi Heiko,
>
>
> > >>> Hmm.. unfortunately ... I had applied your 2 clock patches, which
> > >>> fixed a problem with enabling parent clocks ... but they broke booting
> > >>> on a carrier which has fec ethernet! After "Net: " output the board hang...
> > >>>
> > >>> I reverted your 2 clock patches and it bootet again ... so there is
> > >>> a problem ... try to get some more time to look into...
> > >>>
> > >>
> > >> We have a fec, but we had I think two patches more on it. I forget to
> > >> answer Marek
> > >> about them because I don't have my board now and because he is
> > >> partially right (or maybe right).
> > >> Anyway when we boot we could have and we have clocks that are enabled
> > >> by bootrom or SPL that
> > >> we need to declare as enable like PLL2/PLL3 those clocks are parts or
> > >> could be part of reparent so,
> > >> you need to have a reference counter on them that allow to not disable
> > >> during the down chain disable
> > >> and up chain enable. I think that what happens to your ethernet it's
> > >> that you disable some clock that is
> > >> critical to the board to survive. I had a patch merged by Tom that
> > >
> > > Yep, thats what I think too! If you access registers in a block for
> > > which the clock is not enabled ... it just hang...
> > >
> > >> prints the clock name so if you enable
> > >> the debug of the clock you will find that your board stops working
> > >> during one of this reparinting.
> > >
> > > I currently work on 2024.07... will rebase if 2024.10 is out...
> > >
> > > Ah, you mean:
> > >
> > > commit a70d991212c9684e09ed80ece69ce1ff7bfd9f08
> > > Author: Michael Trimarchi <michael@amarulasolutions.com>
> > > Date:   Tue Jul 9 08:28:13 2024 +0200
> > >
> > >      clk: clk-uclass: Print clk name in clk_enable/clk_disable
> > >
> > >      Print clk name in clk_enable and clk_disable. Make sense to know
> > >      what clock get disabled/enabled before a system crash or system
> > >      hang.
> > >
> > >      Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
> > >
> > > I have the same change when I debug :-P
> > >
> > > IIRC I did not see the clock names ... but I will recheck!
> >
> > I see with your patch the clock names, so fine... and see [1]
> >
> > Hmm... I am on imx8mp, and I think the changes the patchset do in
> >
> > "clk: imx8mn: Prevent clock critical path from disabling during reparent and set_rate"
> >
> > are in clk-imx8mp already ...
> >
> > Ported the patch from patchset
> >
> > "[PATCH 05/26] clk: imx8mm: Mark IMX8MM_SYS_PLL2 and IMX8MM_SYS_PLL3 as enabled"
> >
> > to imx8mp [2] and fec ethernet works again for me on imx8mp!
> >
> > Could you add this if you post a v2 ?
>
> TBH I don't feel like the below change is the correct one, it is too
> specific. The clock core is recursive and thus should handle the
> reparenting situations gracefully.
>
> I posted a series that is targeting the LVDS output on imx8mp. You
> should probably consider checking these patches as well if you work
> on imx8mp as well. I also had similar breakages with Ethernet which
> happened during the assigned-clocks handling. This patch, which is more
> future and platform agnostic, fixed it:
>
> https://lore.kernel.org/u-boot/20240910101344.110633-3-miquel.raynal@bootlin.com/
>

The clock patches are not specific at all. You need to have it working
for the parent for each component.
This is a standard way to do it and nothing magic compared to other
implementations. I don't see
in your series any addressing or reparent clock or take in account
that a clock should be enable before
reparenting.

> My series is complimentary, even though there are some overlaps that we
> need to merge.

The only collision I can see from your series is that you re-write the
imx approach of power domain.
Can you please expand here a bit your point?

Michael

>
> Thanks,
> Miquèl



-- 
Michael Nazzareno Trimarchi
Co-Founder & Chief Executive Officer
M. +39 347 913 2170
michael@amarulasolutions.com
__________________________________

Amarula Solutions BV
Joop Geesinkweg 125, 1114 AB, Amsterdam, NL
T. +31 (0)85 111 9172
info@amarulasolutions.com
www.amarulasolutions.com

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 08/26] power: Add iMX8M block ctrl driver for dispmix
  2024-10-01  8:29               ` Miquel Raynal
  2024-10-01  8:33                 ` Michael Nazzareno Trimarchi
@ 2024-10-01  8:47                 ` Heiko Schocher
  2024-10-01  8:56                   ` Miquel Raynal
  1 sibling, 1 reply; 48+ messages in thread
From: Heiko Schocher @ 2024-10-01  8:47 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Michael Nazzareno Trimarchi, Dario Binacchi, u-boot,
	Fabio Estevam, linux-amarula, Ye Li, AKASHI Takahiro,
	Jaehoon Chung, Tom Rini

Hello Miquel,

On 01.10.24 10:29, Miquel Raynal wrote:
> Hi Heiko,
> 
> 
>>>>> Hmm.. unfortunately ... I had applied your 2 clock patches, which
>>>>> fixed a problem with enabling parent clocks ... but they broke booting
>>>>> on a carrier which has fec ethernet! After "Net: " output the board hang...
>>>>>
>>>>> I reverted your 2 clock patches and it bootet again ... so there is
>>>>> a problem ... try to get some more time to look into...
>>>>>   
>>>>
>>>> We have a fec, but we had I think two patches more on it. I forget to
>>>> answer Marek
>>>> about them because I don't have my board now and because he is
>>>> partially right (or maybe right).
>>>> Anyway when we boot we could have and we have clocks that are enabled
>>>> by bootrom or SPL that
>>>> we need to declare as enable like PLL2/PLL3 those clocks are parts or
>>>> could be part of reparent so,
>>>> you need to have a reference counter on them that allow to not disable
>>>> during the down chain disable
>>>> and up chain enable. I think that what happens to your ethernet it's
>>>> that you disable some clock that is
>>>> critical to the board to survive. I had a patch merged by Tom that
>>>
>>> Yep, thats what I think too! If you access registers in a block for
>>> which the clock is not enabled ... it just hang...
>>>    
>>>> prints the clock name so if you enable
>>>> the debug of the clock you will find that your board stops working
>>>> during one of this reparinting.
>>>
>>> I currently work on 2024.07... will rebase if 2024.10 is out...
>>>
>>> Ah, you mean:
>>>
>>> commit a70d991212c9684e09ed80ece69ce1ff7bfd9f08
>>> Author: Michael Trimarchi <michael@amarulasolutions.com>
>>> Date:   Tue Jul 9 08:28:13 2024 +0200
>>>
>>>       clk: clk-uclass: Print clk name in clk_enable/clk_disable
>>>
>>>       Print clk name in clk_enable and clk_disable. Make sense to know
>>>       what clock get disabled/enabled before a system crash or system
>>>       hang.
>>>
>>>       Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
>>>
>>> I have the same change when I debug :-P
>>>
>>> IIRC I did not see the clock names ... but I will recheck!
>>
>> I see with your patch the clock names, so fine... and see [1]
>>
>> Hmm... I am on imx8mp, and I think the changes the patchset do in
>>
>> "clk: imx8mn: Prevent clock critical path from disabling during reparent and set_rate"
>>
>> are in clk-imx8mp already ...
>>
>> Ported the patch from patchset
>>
>> "[PATCH 05/26] clk: imx8mm: Mark IMX8MM_SYS_PLL2 and IMX8MM_SYS_PLL3 as enabled"
>>
>> to imx8mp [2] and fec ethernet works again for me on imx8mp!
>>
>> Could you add this if you post a v2 ?
> 
> TBH I don't feel like the below change is the correct one, it is too
> specific. The clock core is recursive and thus should handle the
> reparenting situations gracefully.
> 
> I posted a series that is targeting the LVDS output on imx8mp. You
> should probably consider checking these patches as well if you work
> on imx8mp as well. I also had similar breakages with Ethernet which
> happened during the assigned-clocks handling. This patch, which is more
> future and platform agnostic, fixed it:
> 
> https://lore.kernel.org/u-boot/20240910101344.110633-3-miquel.raynal@bootlin.com/

Yes, I also had such a "fix" first, before seeing Darios patchset!

Damn, I did not see your patches...

regarding your patch ... I am unsure which version is the best one ...
I fear of side effects for other plattforms adding this change in
generic "drivers/clk/clk-uclass.c" file...

> My series is complimentary, even though there are some overlaps that we
> need to merge.

I try to find time to test them on my board!

bye,
Heiko
-- 
DENX Software Engineering GmbH,      Managing Director: Erika Unter
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-52   Fax: +49-8142-66989-80   Email: hs@denx.de

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 08/26] power: Add iMX8M block ctrl driver for dispmix
  2024-10-01  8:33                 ` Michael Nazzareno Trimarchi
@ 2024-10-01  8:50                   ` Miquel Raynal
  2024-10-01  8:57                     ` Heiko Schocher
  0 siblings, 1 reply; 48+ messages in thread
From: Miquel Raynal @ 2024-10-01  8:50 UTC (permalink / raw)
  To: Michael Nazzareno Trimarchi
  Cc: Heiko Schocher, Dario Binacchi, u-boot, Fabio Estevam,
	linux-amarula, Ye Li, AKASHI Takahiro, Jaehoon Chung, Tom Rini

Hi Michael,

michael@amarulasolutions.com wrote on Tue, 1 Oct 2024 10:33:56 +0200:

> Hi Miguel
> 
> On Tue, Oct 1, 2024 at 10:29 AM Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> >
> > Hi Heiko,
> >
> >  
> > > >>> Hmm.. unfortunately ... I had applied your 2 clock patches, which
> > > >>> fixed a problem with enabling parent clocks ... but they broke booting
> > > >>> on a carrier which has fec ethernet! After "Net: " output the board hang...
> > > >>>
> > > >>> I reverted your 2 clock patches and it bootet again ... so there is
> > > >>> a problem ... try to get some more time to look into...
> > > >>>  
> > > >>
> > > >> We have a fec, but we had I think two patches more on it. I forget to
> > > >> answer Marek
> > > >> about them because I don't have my board now and because he is
> > > >> partially right (or maybe right).
> > > >> Anyway when we boot we could have and we have clocks that are enabled
> > > >> by bootrom or SPL that
> > > >> we need to declare as enable like PLL2/PLL3 those clocks are parts or
> > > >> could be part of reparent so,
> > > >> you need to have a reference counter on them that allow to not disable
> > > >> during the down chain disable
> > > >> and up chain enable. I think that what happens to your ethernet it's
> > > >> that you disable some clock that is
> > > >> critical to the board to survive. I had a patch merged by Tom that  
> > > >
> > > > Yep, thats what I think too! If you access registers in a block for
> > > > which the clock is not enabled ... it just hang...
> > > >  
> > > >> prints the clock name so if you enable
> > > >> the debug of the clock you will find that your board stops working
> > > >> during one of this reparinting.  
> > > >
> > > > I currently work on 2024.07... will rebase if 2024.10 is out...
> > > >
> > > > Ah, you mean:
> > > >
> > > > commit a70d991212c9684e09ed80ece69ce1ff7bfd9f08
> > > > Author: Michael Trimarchi <michael@amarulasolutions.com>
> > > > Date:   Tue Jul 9 08:28:13 2024 +0200
> > > >
> > > >      clk: clk-uclass: Print clk name in clk_enable/clk_disable
> > > >
> > > >      Print clk name in clk_enable and clk_disable. Make sense to know
> > > >      what clock get disabled/enabled before a system crash or system
> > > >      hang.
> > > >
> > > >      Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
> > > >
> > > > I have the same change when I debug :-P
> > > >
> > > > IIRC I did not see the clock names ... but I will recheck!  
> > >
> > > I see with your patch the clock names, so fine... and see [1]
> > >
> > > Hmm... I am on imx8mp, and I think the changes the patchset do in
> > >
> > > "clk: imx8mn: Prevent clock critical path from disabling during reparent and set_rate"
> > >
> > > are in clk-imx8mp already ...
> > >
> > > Ported the patch from patchset
> > >
> > > "[PATCH 05/26] clk: imx8mm: Mark IMX8MM_SYS_PLL2 and IMX8MM_SYS_PLL3 as enabled"
> > >
> > > to imx8mp [2] and fec ethernet works again for me on imx8mp!
> > >
> > > Could you add this if you post a v2 ?  
> >
> > TBH I don't feel like the below change is the correct one, it is too
> > specific. The clock core is recursive and thus should handle the
> > reparenting situations gracefully.
> >
> > I posted a series that is targeting the LVDS output on imx8mp. You
> > should probably consider checking these patches as well if you work
> > on imx8mp as well. I also had similar breakages with Ethernet which
> > happened during the assigned-clocks handling. This patch, which is more
> > future and platform agnostic, fixed it:
> >
> > https://lore.kernel.org/u-boot/20240910101344.110633-3-miquel.raynal@bootlin.com/
> >  
> 
> The clock patches are not specific at all. You need to have it working
> for the parent for each component.

The diff shown by Heiko is explicitly enabling PLLs by naming them in
the iMX driver. This is not the correct approach. The problem of
having non-enabled new parents is global. Parent clocks should be
enabled before changing muxes, and this should be enforced
by the clock core/uclass, not the SoC drivers.

> This is a standard way to do it and nothing magic compared to other
> implementations.

No, naming PLLs explicitly is not the correct approach.

> I don't see
> in your series any addressing or reparent clock or take in account
> that a clock should be enable before
> reparenting.

That's exactly the link above, whose diff is pasted here for reference:

@@ -595,6 +595,10 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
 	if (!ops->set_parent)
 		return -ENOSYS;
 
+	ret = clk_enable(parent);
+	if (ret)
+		return ret;

> 
> > My series is complimentary, even though there are some overlaps that we
> > need to merge.  
> 
> The only collision I can see from your series is that you re-write the
> imx approach of power domain.
> Can you please expand here a bit your point?

Well, that's what I'd call an overlap :) There are also similar changes
in the clock core IIRC. Well, there is a bit of merging that needs to
happen I guess, but if you don't think there is any then my series can
enter as-is (once the comments addressed, ofc).

Thanks,
Miquèl

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 08/26] power: Add iMX8M block ctrl driver for dispmix
  2024-10-01  8:47                 ` Heiko Schocher
@ 2024-10-01  8:56                   ` Miquel Raynal
  0 siblings, 0 replies; 48+ messages in thread
From: Miquel Raynal @ 2024-10-01  8:56 UTC (permalink / raw)
  To: Heiko Schocher
  Cc: Michael Nazzareno Trimarchi, Dario Binacchi, u-boot,
	Fabio Estevam, linux-amarula, Ye Li, AKASHI Takahiro,
	Jaehoon Chung, Tom Rini

Hi Heiko,

> >> I see with your patch the clock names, so fine... and see [1]
> >>
> >> Hmm... I am on imx8mp, and I think the changes the patchset do in
> >>
> >> "clk: imx8mn: Prevent clock critical path from disabling during reparent and set_rate"
> >>
> >> are in clk-imx8mp already ...
> >>
> >> Ported the patch from patchset
> >>
> >> "[PATCH 05/26] clk: imx8mm: Mark IMX8MM_SYS_PLL2 and IMX8MM_SYS_PLL3 as enabled"
> >>
> >> to imx8mp [2] and fec ethernet works again for me on imx8mp!
> >>
> >> Could you add this if you post a v2 ?  
> > 
> > TBH I don't feel like the below change is the correct one, it is too
> > specific. The clock core is recursive and thus should handle the
> > reparenting situations gracefully.
> > 
> > I posted a series that is targeting the LVDS output on imx8mp. You
> > should probably consider checking these patches as well if you work
> > on imx8mp as well. I also had similar breakages with Ethernet which
> > happened during the assigned-clocks handling. This patch, which is more
> > future and platform agnostic, fixed it:
> > 
> > https://lore.kernel.org/u-boot/20240910101344.110633-3-miquel.raynal@bootlin.com/  
> 
> Yes, I also had such a "fix" first, before seeing Darios patchset!
> 
> Damn, I did not see your patches...
> 
> regarding your patch ... I am unsure which version is the best one ...
> I fear of side effects for other plattforms adding this change in
> generic "drivers/clk/clk-uclass.c" file...

FYI, this is the same approach as Linux. I don't expect any hardware
related breakage, however if people have already tried to workaround
the core's mistakes by doing more than expected in the SoC drivers,
maybe we will observe issues.

> > My series is complimentary, even though there are some overlaps that we
> > need to merge.  
> 
> I try to find time to test them on my board!

Sure, let me know if you have troubles, it's still fresh :-) I will
rework it a bit as it received already interesting feedback, and will
note to Cc you (as well as Dario/Michael) in v2.

Thanks,
Miquèl

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 08/26] power: Add iMX8M block ctrl driver for dispmix
  2024-10-01  8:50                   ` Miquel Raynal
@ 2024-10-01  8:57                     ` Heiko Schocher
  2024-10-01  9:50                       ` Michael Nazzareno Trimarchi
  2024-10-01  9:55                       ` Miquel Raynal
  0 siblings, 2 replies; 48+ messages in thread
From: Heiko Schocher @ 2024-10-01  8:57 UTC (permalink / raw)
  To: Miquel Raynal, Michael Nazzareno Trimarchi
  Cc: Dario Binacchi, u-boot, Fabio Estevam, linux-amarula, Ye Li,
	AKASHI Takahiro, Jaehoon Chung, Tom Rini

Hello Miquel,

On 01.10.24 10:50, Miquel Raynal wrote:
> Hi Michael,
> 
> michael@amarulasolutions.com wrote on Tue, 1 Oct 2024 10:33:56 +0200:
> 
>> Hi Miguel
>>
>> On Tue, Oct 1, 2024 at 10:29 AM Miquel Raynal <miquel.raynal@bootlin.com> wrote:
>>>
>>> Hi Heiko,
>>>
>>>   
>>>>>>> Hmm.. unfortunately ... I had applied your 2 clock patches, which
>>>>>>> fixed a problem with enabling parent clocks ... but they broke booting
>>>>>>> on a carrier which has fec ethernet! After "Net: " output the board hang...
>>>>>>>
>>>>>>> I reverted your 2 clock patches and it bootet again ... so there is
>>>>>>> a problem ... try to get some more time to look into...
>>>>>>>   
>>>>>>
>>>>>> We have a fec, but we had I think two patches more on it. I forget to
>>>>>> answer Marek
>>>>>> about them because I don't have my board now and because he is
>>>>>> partially right (or maybe right).
>>>>>> Anyway when we boot we could have and we have clocks that are enabled
>>>>>> by bootrom or SPL that
>>>>>> we need to declare as enable like PLL2/PLL3 those clocks are parts or
>>>>>> could be part of reparent so,
>>>>>> you need to have a reference counter on them that allow to not disable
>>>>>> during the down chain disable
>>>>>> and up chain enable. I think that what happens to your ethernet it's
>>>>>> that you disable some clock that is
>>>>>> critical to the board to survive. I had a patch merged by Tom that
>>>>>
>>>>> Yep, thats what I think too! If you access registers in a block for
>>>>> which the clock is not enabled ... it just hang...
>>>>>   
>>>>>> prints the clock name so if you enable
>>>>>> the debug of the clock you will find that your board stops working
>>>>>> during one of this reparinting.
>>>>>
>>>>> I currently work on 2024.07... will rebase if 2024.10 is out...
>>>>>
>>>>> Ah, you mean:
>>>>>
>>>>> commit a70d991212c9684e09ed80ece69ce1ff7bfd9f08
>>>>> Author: Michael Trimarchi <michael@amarulasolutions.com>
>>>>> Date:   Tue Jul 9 08:28:13 2024 +0200
>>>>>
>>>>>       clk: clk-uclass: Print clk name in clk_enable/clk_disable
>>>>>
>>>>>       Print clk name in clk_enable and clk_disable. Make sense to know
>>>>>       what clock get disabled/enabled before a system crash or system
>>>>>       hang.
>>>>>
>>>>>       Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
>>>>>
>>>>> I have the same change when I debug :-P
>>>>>
>>>>> IIRC I did not see the clock names ... but I will recheck!
>>>>
>>>> I see with your patch the clock names, so fine... and see [1]
>>>>
>>>> Hmm... I am on imx8mp, and I think the changes the patchset do in
>>>>
>>>> "clk: imx8mn: Prevent clock critical path from disabling during reparent and set_rate"
>>>>
>>>> are in clk-imx8mp already ...
>>>>
>>>> Ported the patch from patchset
>>>>
>>>> "[PATCH 05/26] clk: imx8mm: Mark IMX8MM_SYS_PLL2 and IMX8MM_SYS_PLL3 as enabled"
>>>>
>>>> to imx8mp [2] and fec ethernet works again for me on imx8mp!
>>>>
>>>> Could you add this if you post a v2 ?
>>>
>>> TBH I don't feel like the below change is the correct one, it is too
>>> specific. The clock core is recursive and thus should handle the
>>> reparenting situations gracefully.
>>>
>>> I posted a series that is targeting the LVDS output on imx8mp. You
>>> should probably consider checking these patches as well if you work
>>> on imx8mp as well. I also had similar breakages with Ethernet which
>>> happened during the assigned-clocks handling. This patch, which is more
>>> future and platform agnostic, fixed it:
>>>
>>> https://lore.kernel.org/u-boot/20240910101344.110633-3-miquel.raynal@bootlin.com/
>>>   
>>
>> The clock patches are not specific at all. You need to have it working
>> for the parent for each component.
> 
> The diff shown by Heiko is explicitly enabling PLLs by naming them in
> the iMX driver. This is not the correct approach. The problem of
> having non-enabled new parents is global. Parent clocks should be
> enabled before changing muxes, and this should be enforced
> by the clock core/uclass, not the SoC drivers.

Okay, valid argument.

> 
>> This is a standard way to do it and nothing magic compared to other
>> implementations.
> 
> No, naming PLLs explicitly is not the correct approach.
> 
>> I don't see
>> in your series any addressing or reparent clock or take in account
>> that a clock should be enable before
>> reparenting.
> 
> That's exactly the link above, whose diff is pasted here for reference:
> 
> @@ -595,6 +595,10 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
>   	if (!ops->set_parent)
>   		return -ENOSYS;
>   
> +	ret = clk_enable(parent);
> +	if (ret)
> +		return ret;

As I said before, I had *exact* the same patch and thought I made a big
hack :-P

But I wonder ... if this a generic "problem", why nobody had yet problems
with it...

Thanks!

bye,
Heiko

>>> My series is complimentary, even though there are some overlaps that we
>>> need to merge.
>>
>> The only collision I can see from your series is that you re-write the
>> imx approach of power domain.
>> Can you please expand here a bit your point?
> 
> Well, that's what I'd call an overlap :) There are also similar changes
> in the clock core IIRC. Well, there is a bit of merging that needs to
> happen I guess, but if you don't think there is any then my series can
> enter as-is (once the comments addressed, ofc).
> 
> Thanks,
> Miquèl
> 

-- 
DENX Software Engineering GmbH,      Managing Director: Erika Unter
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-52   Fax: +49-8142-66989-80   Email: hs@denx.de

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 08/26] power: Add iMX8M block ctrl driver for dispmix
  2024-10-01  8:57                     ` Heiko Schocher
@ 2024-10-01  9:50                       ` Michael Nazzareno Trimarchi
  2024-10-01 10:01                         ` Miquel Raynal
  2024-10-01  9:55                       ` Miquel Raynal
  1 sibling, 1 reply; 48+ messages in thread
From: Michael Nazzareno Trimarchi @ 2024-10-01  9:50 UTC (permalink / raw)
  To: hs
  Cc: Miquel Raynal, Dario Binacchi, u-boot, Fabio Estevam,
	linux-amarula, Ye Li, AKASHI Takahiro, Jaehoon Chung, Tom Rini

Hi all

On Tue, Oct 1, 2024 at 10:59 AM Heiko Schocher <hs@denx.de> wrote:
>
> Hello Miquel,
>
> On 01.10.24 10:50, Miquel Raynal wrote:
> > Hi Michael,
> >
> > michael@amarulasolutions.com wrote on Tue, 1 Oct 2024 10:33:56 +0200:
> >
> >> Hi Miguel
> >>
> >> On Tue, Oct 1, 2024 at 10:29 AM Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> >>>
> >>> Hi Heiko,
> >>>
> >>>
> >>>>>>> Hmm.. unfortunately ... I had applied your 2 clock patches, which
> >>>>>>> fixed a problem with enabling parent clocks ... but they broke booting
> >>>>>>> on a carrier which has fec ethernet! After "Net: " output the board hang...
> >>>>>>>
> >>>>>>> I reverted your 2 clock patches and it bootet again ... so there is
> >>>>>>> a problem ... try to get some more time to look into...
> >>>>>>>
> >>>>>>
> >>>>>> We have a fec, but we had I think two patches more on it. I forget to
> >>>>>> answer Marek
> >>>>>> about them because I don't have my board now and because he is
> >>>>>> partially right (or maybe right).
> >>>>>> Anyway when we boot we could have and we have clocks that are enabled
> >>>>>> by bootrom or SPL that
> >>>>>> we need to declare as enable like PLL2/PLL3 those clocks are parts or
> >>>>>> could be part of reparent so,
> >>>>>> you need to have a reference counter on them that allow to not disable
> >>>>>> during the down chain disable
> >>>>>> and up chain enable. I think that what happens to your ethernet it's
> >>>>>> that you disable some clock that is
> >>>>>> critical to the board to survive. I had a patch merged by Tom that
> >>>>>
> >>>>> Yep, thats what I think too! If you access registers in a block for
> >>>>> which the clock is not enabled ... it just hang...
> >>>>>
> >>>>>> prints the clock name so if you enable
> >>>>>> the debug of the clock you will find that your board stops working
> >>>>>> during one of this reparinting.
> >>>>>
> >>>>> I currently work on 2024.07... will rebase if 2024.10 is out...
> >>>>>
> >>>>> Ah, you mean:
> >>>>>
> >>>>> commit a70d991212c9684e09ed80ece69ce1ff7bfd9f08
> >>>>> Author: Michael Trimarchi <michael@amarulasolutions.com>
> >>>>> Date:   Tue Jul 9 08:28:13 2024 +0200
> >>>>>
> >>>>>       clk: clk-uclass: Print clk name in clk_enable/clk_disable
> >>>>>
> >>>>>       Print clk name in clk_enable and clk_disable. Make sense to know
> >>>>>       what clock get disabled/enabled before a system crash or system
> >>>>>       hang.
> >>>>>
> >>>>>       Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
> >>>>>
> >>>>> I have the same change when I debug :-P
> >>>>>
> >>>>> IIRC I did not see the clock names ... but I will recheck!
> >>>>
> >>>> I see with your patch the clock names, so fine... and see [1]
> >>>>
> >>>> Hmm... I am on imx8mp, and I think the changes the patchset do in
> >>>>
> >>>> "clk: imx8mn: Prevent clock critical path from disabling during reparent and set_rate"
> >>>>
> >>>> are in clk-imx8mp already ...
> >>>>
> >>>> Ported the patch from patchset
> >>>>
> >>>> "[PATCH 05/26] clk: imx8mm: Mark IMX8MM_SYS_PLL2 and IMX8MM_SYS_PLL3 as enabled"
> >>>>
> >>>> to imx8mp [2] and fec ethernet works again for me on imx8mp!
> >>>>
> >>>> Could you add this if you post a v2 ?
> >>>
> >>> TBH I don't feel like the below change is the correct one, it is too
> >>> specific. The clock core is recursive and thus should handle the
> >>> reparenting situations gracefully.
> >>>
> >>> I posted a series that is targeting the LVDS output on imx8mp. You
> >>> should probably consider checking these patches as well if you work
> >>> on imx8mp as well. I also had similar breakages with Ethernet which
> >>> happened during the assigned-clocks handling. This patch, which is more
> >>> future and platform agnostic, fixed it:
> >>>
> >>> https://lore.kernel.org/u-boot/20240910101344.110633-3-miquel.raynal@bootlin.com/
> >>>
> >>
> >> The clock patches are not specific at all. You need to have it working
> >> for the parent for each component.
> >
> > The diff shown by Heiko is explicitly enabling PLLs by naming them in
> > the iMX driver. This is not the correct approach. The problem of
> > having non-enabled new parents is global. Parent clocks should be
> > enabled before changing muxes, and this should be enforced
> > by the clock core/uclass, not the SoC drivers.
>
> Okay, valid argument.
>
> >
> >> This is a standard way to do it and nothing magic compared to other
> >> implementations.
> >
> > No, naming PLLs explicitly is not the correct approach.
> >
> >> I don't see
> >> in your series any addressing or reparent clock or take in account
> >> that a clock should be enable before
> >> reparenting.
> >
> > That's exactly the link above, whose diff is pasted here for reference:
> >
> > @@ -595,6 +595,10 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
> >       if (!ops->set_parent)
> >               return -ENOSYS;
> >
> > +     ret = clk_enable(parent);
> > +     if (ret)
> > +             return ret;
>
> As I said before, I had *exact* the same patch and thought I made a big
> hack :-P
>
> But I wonder ... if this a generic "problem", why nobody had yet problems
> with it...

I think that a generic approach that takes into account the reparent
is more valuable, then
this. If a clock is enabled by another stage and we don't aware about
it we need to mark
as enabled. I think that this force of enable it's just a short path
that does not solve the generic
problem. I really tried to abstract what is really implemented in
other OS on the same topic.
I don't want to have a discussion about who should merge first.

Michael

>
> Thanks!
>
> bye,
> Heiko
>
> >>> My series is complimentary, even though there are some overlaps that we
> >>> need to merge.
> >>
> >> The only collision I can see from your series is that you re-write the
> >> imx approach of power domain.
> >> Can you please expand here a bit your point?
> >
> > Well, that's what I'd call an overlap :) There are also similar changes
> > in the clock core IIRC. Well, there is a bit of merging that needs to
> > happen I guess, but if you don't think there is any then my series can
> > enter as-is (once the comments addressed, ofc).
> >
> > Thanks,
> > Miquèl
> >
>
> --
> DENX Software Engineering GmbH,      Managing Director: Erika Unter
> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
> Phone: +49-8142-66989-52   Fax: +49-8142-66989-80   Email: hs@denx.de


--
Michael Nazzareno Trimarchi
Co-Founder & Chief Executive Officer
M. +39 347 913 2170
michael@amarulasolutions.com
__________________________________

Amarula Solutions BV
Joop Geesinkweg 125, 1114 AB, Amsterdam, NL
T. +31 (0)85 111 9172
info@amarulasolutions.com
www.amarulasolutions.com

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 08/26] power: Add iMX8M block ctrl driver for dispmix
  2024-10-01  8:57                     ` Heiko Schocher
  2024-10-01  9:50                       ` Michael Nazzareno Trimarchi
@ 2024-10-01  9:55                       ` Miquel Raynal
  1 sibling, 0 replies; 48+ messages in thread
From: Miquel Raynal @ 2024-10-01  9:55 UTC (permalink / raw)
  To: Heiko Schocher
  Cc: Michael Nazzareno Trimarchi, Dario Binacchi, u-boot,
	Fabio Estevam, linux-amarula, Ye Li, AKASHI Takahiro,
	Jaehoon Chung, Tom Rini

Hi Heiko,

hs@denx.de wrote on Tue, 1 Oct 2024 10:57:27 +0200:

> Hello Miquel,
> 
> On 01.10.24 10:50, Miquel Raynal wrote:
> > Hi Michael,
> > 
> > michael@amarulasolutions.com wrote on Tue, 1 Oct 2024 10:33:56 +0200:
> >   
> >> Hi Miguel
> >>
> >> On Tue, Oct 1, 2024 at 10:29 AM Miquel Raynal <miquel.raynal@bootlin.com> wrote:  
> >>>
> >>> Hi Heiko,
> >>>  
> >>>   >>>>>>> Hmm.. unfortunately ... I had applied your 2 clock patches, which  
> >>>>>>> fixed a problem with enabling parent clocks ... but they broke booting
> >>>>>>> on a carrier which has fec ethernet! After "Net: " output the board hang...
> >>>>>>>
> >>>>>>> I reverted your 2 clock patches and it bootet again ... so there is
> >>>>>>> a problem ... try to get some more time to look into...  
> >>>>>>>   >>>>>>  
> >>>>>> We have a fec, but we had I think two patches more on it. I forget to
> >>>>>> answer Marek
> >>>>>> about them because I don't have my board now and because he is
> >>>>>> partially right (or maybe right).
> >>>>>> Anyway when we boot we could have and we have clocks that are enabled
> >>>>>> by bootrom or SPL that
> >>>>>> we need to declare as enable like PLL2/PLL3 those clocks are parts or
> >>>>>> could be part of reparent so,
> >>>>>> you need to have a reference counter on them that allow to not disable
> >>>>>> during the down chain disable
> >>>>>> and up chain enable. I think that what happens to your ethernet it's
> >>>>>> that you disable some clock that is
> >>>>>> critical to the board to survive. I had a patch merged by Tom that  
> >>>>>
> >>>>> Yep, thats what I think too! If you access registers in a block for
> >>>>> which the clock is not enabled ... it just hang...  
> >>>>>   >>>>>> prints the clock name so if you enable  
> >>>>>> the debug of the clock you will find that your board stops working
> >>>>>> during one of this reparinting.  
> >>>>>
> >>>>> I currently work on 2024.07... will rebase if 2024.10 is out...
> >>>>>
> >>>>> Ah, you mean:
> >>>>>
> >>>>> commit a70d991212c9684e09ed80ece69ce1ff7bfd9f08
> >>>>> Author: Michael Trimarchi <michael@amarulasolutions.com>
> >>>>> Date:   Tue Jul 9 08:28:13 2024 +0200
> >>>>>
> >>>>>       clk: clk-uclass: Print clk name in clk_enable/clk_disable
> >>>>>
> >>>>>       Print clk name in clk_enable and clk_disable. Make sense to know
> >>>>>       what clock get disabled/enabled before a system crash or system
> >>>>>       hang.
> >>>>>
> >>>>>       Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
> >>>>>
> >>>>> I have the same change when I debug :-P
> >>>>>
> >>>>> IIRC I did not see the clock names ... but I will recheck!  
> >>>>
> >>>> I see with your patch the clock names, so fine... and see [1]
> >>>>
> >>>> Hmm... I am on imx8mp, and I think the changes the patchset do in
> >>>>
> >>>> "clk: imx8mn: Prevent clock critical path from disabling during reparent and set_rate"
> >>>>
> >>>> are in clk-imx8mp already ...
> >>>>
> >>>> Ported the patch from patchset
> >>>>
> >>>> "[PATCH 05/26] clk: imx8mm: Mark IMX8MM_SYS_PLL2 and IMX8MM_SYS_PLL3 as enabled"
> >>>>
> >>>> to imx8mp [2] and fec ethernet works again for me on imx8mp!
> >>>>
> >>>> Could you add this if you post a v2 ?  
> >>>
> >>> TBH I don't feel like the below change is the correct one, it is too
> >>> specific. The clock core is recursive and thus should handle the
> >>> reparenting situations gracefully.
> >>>
> >>> I posted a series that is targeting the LVDS output on imx8mp. You
> >>> should probably consider checking these patches as well if you work
> >>> on imx8mp as well. I also had similar breakages with Ethernet which
> >>> happened during the assigned-clocks handling. This patch, which is more
> >>> future and platform agnostic, fixed it:
> >>>
> >>> https://lore.kernel.org/u-boot/20240910101344.110633-3-miquel.raynal@bootlin.com/  
> >>>   >>  
> >> The clock patches are not specific at all. You need to have it working
> >> for the parent for each component.  
> > 
> > The diff shown by Heiko is explicitly enabling PLLs by naming them in
> > the iMX driver. This is not the correct approach. The problem of
> > having non-enabled new parents is global. Parent clocks should be
> > enabled before changing muxes, and this should be enforced
> > by the clock core/uclass, not the SoC drivers.  
> 
> Okay, valid argument.
> 
> >   
> >> This is a standard way to do it and nothing magic compared to other
> >> implementations.  
> > 
> > No, naming PLLs explicitly is not the correct approach.
> >   
> >> I don't see
> >> in your series any addressing or reparent clock or take in account
> >> that a clock should be enable before
> >> reparenting.  
> > 
> > That's exactly the link above, whose diff is pasted here for reference:
> > 
> > @@ -595,6 +595,10 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
> >   	if (!ops->set_parent)
> >   		return -ENOSYS;  
> >   > +	ret = clk_enable(parent);  
> > +	if (ret)
> > +		return ret;  
> 
> As I said before, I had *exact* the same patch and thought I made a big
> hack :-P

I don't think so :-)

> But I wonder ... if this a generic "problem", why nobody had yet problems
> with it...

It depends on your hardware and how you use it I guess. If you look into
the terribly complex clock slices explanation in the imx8mp manual,
you'll see what the target clock interface does behind the scenes when
you use it. There are like 25 steps internally to prevent glitch-free
changes. I suspect one of those actions to stall if the parent is not
enabled early enough during the reparenting procedure.

Now, the reason why parents might be disabled is because of the high
level of configurability this SoC offers which is likely higher than
many other SoCs. But in general, to avoid these stalls, there has been a
quite extensive use of assigned-clocks properties. I believe with yet
another entry in this list, we could probably make it work, but that's
not the correct approach either.

Thanks,
Miquèl

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 08/26] power: Add iMX8M block ctrl driver for dispmix
  2024-10-01  9:50                       ` Michael Nazzareno Trimarchi
@ 2024-10-01 10:01                         ` Miquel Raynal
  2024-10-01 13:02                           ` Michael Nazzareno Trimarchi
  0 siblings, 1 reply; 48+ messages in thread
From: Miquel Raynal @ 2024-10-01 10:01 UTC (permalink / raw)
  To: Michael Nazzareno Trimarchi
  Cc: hs, Dario Binacchi, u-boot, Fabio Estevam, linux-amarula, Ye Li,
	AKASHI Takahiro, Jaehoon Chung, Tom Rini

Hi Michael,

> > >>>> Ported the patch from patchset
> > >>>>
> > >>>> "[PATCH 05/26] clk: imx8mm: Mark IMX8MM_SYS_PLL2 and IMX8MM_SYS_PLL3 as enabled"
> > >>>>
> > >>>> to imx8mp [2] and fec ethernet works again for me on imx8mp!
> > >>>>
> > >>>> Could you add this if you post a v2 ?  
> > >>>
> > >>> TBH I don't feel like the below change is the correct one, it is too
> > >>> specific. The clock core is recursive and thus should handle the
> > >>> reparenting situations gracefully.
> > >>>
> > >>> I posted a series that is targeting the LVDS output on imx8mp. You
> > >>> should probably consider checking these patches as well if you work
> > >>> on imx8mp as well. I also had similar breakages with Ethernet which
> > >>> happened during the assigned-clocks handling. This patch, which is more
> > >>> future and platform agnostic, fixed it:
> > >>>
> > >>> https://lore.kernel.org/u-boot/20240910101344.110633-3-miquel.raynal@bootlin.com/
> > >>>  
> > >>
> > >> The clock patches are not specific at all. You need to have it working
> > >> for the parent for each component.  
> > >
> > > The diff shown by Heiko is explicitly enabling PLLs by naming them in
> > > the iMX driver. This is not the correct approach. The problem of
> > > having non-enabled new parents is global. Parent clocks should be
> > > enabled before changing muxes, and this should be enforced
> > > by the clock core/uclass, not the SoC drivers.  
> >
> > Okay, valid argument.
> >  
> > >  
> > >> This is a standard way to do it and nothing magic compared to other
> > >> implementations.  
> > >
> > > No, naming PLLs explicitly is not the correct approach.
> > >  
> > >> I don't see
> > >> in your series any addressing or reparent clock or take in account
> > >> that a clock should be enable before
> > >> reparenting.  
> > >
> > > That's exactly the link above, whose diff is pasted here for reference:
> > >
> > > @@ -595,6 +595,10 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
> > >       if (!ops->set_parent)
> > >               return -ENOSYS;
> > >
> > > +     ret = clk_enable(parent);
> > > +     if (ret)
> > > +             return ret;  
> >
> > As I said before, I had *exact* the same patch and thought I made a big
> > hack :-P
> >
> > But I wonder ... if this a generic "problem", why nobody had yet problems
> > with it...  
> 
> I think that a generic approach that takes into account the reparent
> is more valuable, then
> this.

I'm sorry I don't fully understand your answer. I assume you agree with
the generic approach quoted above.

> If a clock is enabled by another stage and we don't aware about
> it we need to mark
> as enabled.

clk_enable() already handles this kind of situation.

> I think that this force of enable it's just a short path
> that does not solve the generic
> problem.

What "force of enable"? The parent needs to be enabled before we use it
as parent. The logic is always the same:
- clk_enable() the new parent
- change the parent
- clk_disable() the old parent
I don't see any short path here.

> I really tried to abstract what is really implemented in
> other OS on the same topic.

FYI, Linux does the clk_enable(parent) like above.

Thanks,
Miquèl

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 08/26] power: Add iMX8M block ctrl driver for dispmix
  2024-10-01 10:01                         ` Miquel Raynal
@ 2024-10-01 13:02                           ` Michael Nazzareno Trimarchi
  2024-10-01 20:54                             ` Miquel Raynal
  0 siblings, 1 reply; 48+ messages in thread
From: Michael Nazzareno Trimarchi @ 2024-10-01 13:02 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: hs, Dario Binacchi, u-boot, Fabio Estevam, linux-amarula, Ye Li,
	AKASHI Takahiro, Jaehoon Chung, Tom Rini

Hi

On Tue, Oct 1, 2024 at 12:01 PM Miquel Raynal <miquel.raynal@bootlin.com> wrote:
>
> Hi Michael,
>
> > > >>>> Ported the patch from patchset
> > > >>>>
> > > >>>> "[PATCH 05/26] clk: imx8mm: Mark IMX8MM_SYS_PLL2 and IMX8MM_SYS_PLL3 as enabled"
> > > >>>>
> > > >>>> to imx8mp [2] and fec ethernet works again for me on imx8mp!
> > > >>>>
> > > >>>> Could you add this if you post a v2 ?
> > > >>>
> > > >>> TBH I don't feel like the below change is the correct one, it is too
> > > >>> specific. The clock core is recursive and thus should handle the
> > > >>> reparenting situations gracefully.
> > > >>>
> > > >>> I posted a series that is targeting the LVDS output on imx8mp. You
> > > >>> should probably consider checking these patches as well if you work
> > > >>> on imx8mp as well. I also had similar breakages with Ethernet which
> > > >>> happened during the assigned-clocks handling. This patch, which is more
> > > >>> future and platform agnostic, fixed it:
> > > >>>
> > > >>> https://lore.kernel.org/u-boot/20240910101344.110633-3-miquel.raynal@bootlin.com/
> > > >>>
> > > >>
> > > >> The clock patches are not specific at all. You need to have it working
> > > >> for the parent for each component.
> > > >
> > > > The diff shown by Heiko is explicitly enabling PLLs by naming them in
> > > > the iMX driver. This is not the correct approach. The problem of
> > > > having non-enabled new parents is global. Parent clocks should be
> > > > enabled before changing muxes, and this should be enforced
> > > > by the clock core/uclass, not the SoC drivers.
> > >
> > > Okay, valid argument.
> > >
> > > >
> > > >> This is a standard way to do it and nothing magic compared to other
> > > >> implementations.
> > > >
> > > > No, naming PLLs explicitly is not the correct approach.
> > > >
> > > >> I don't see
> > > >> in your series any addressing or reparent clock or take in account
> > > >> that a clock should be enable before
> > > >> reparenting.
> > > >
> > > > That's exactly the link above, whose diff is pasted here for reference:
> > > >
> > > > @@ -595,6 +595,10 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
> > > >       if (!ops->set_parent)
> > > >               return -ENOSYS;
> > > >
> > > > +     ret = clk_enable(parent);
> > > > +     if (ret)
> > > > +             return ret;
> > >
> > > As I said before, I had *exact* the same patch and thought I made a big
> > > hack :-P
> > >
> > > But I wonder ... if this a generic "problem", why nobody had yet problems
> > > with it...
> >
> > I think that a generic approach that takes into account the reparent
> > is more valuable, then
> > this.
>
> I'm sorry I don't fully understand your answer. I assume you agree with
> the generic approach quoted above.
>
> > If a clock is enabled by another stage and we don't aware about
> > it we need to mark
> > as enabled.
>
> clk_enable() already handles this kind of situation.
>
> > I think that this force of enable it's just a short path
> > that does not solve the generic
> > problem.
>
> What "force of enable"? The parent needs to be enabled before we use it
> as parent. The logic is always the same:
> - clk_enable() the new parent
> - change the parent
> - clk_disable() the old parent
> I don't see any short path here.
>
> > I really tried to abstract what is really implemented in
> > other OS on the same topic.
>
> FYI, Linux does the clk_enable(parent) like above.
>

You mean linux enables a clock in set_parent even if the clock_chain
is not yet enabled.
clock a disable
clock b disable

clk_set_parent(a, b) b->a now b is enabled?

Michael

> Thanks,
> Miquèl



-- 
Michael Nazzareno Trimarchi
Co-Founder & Chief Executive Officer
M. +39 347 913 2170
michael@amarulasolutions.com
__________________________________

Amarula Solutions BV
Joop Geesinkweg 125, 1114 AB, Amsterdam, NL
T. +31 (0)85 111 9172
info@amarulasolutions.com
www.amarulasolutions.com

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [PATCH 08/26] power: Add iMX8M block ctrl driver for dispmix
  2024-10-01 13:02                           ` Michael Nazzareno Trimarchi
@ 2024-10-01 20:54                             ` Miquel Raynal
  0 siblings, 0 replies; 48+ messages in thread
From: Miquel Raynal @ 2024-10-01 20:54 UTC (permalink / raw)
  To: Michael Nazzareno Trimarchi
  Cc: hs, Dario Binacchi, u-boot, Fabio Estevam, linux-amarula, Ye Li,
	AKASHI Takahiro, Jaehoon Chung, Tom Rini

Hi Michael,

michael@amarulasolutions.com wrote on Tue, 1 Oct 2024 15:02:56 +0200:

> Hi
> 
> On Tue, Oct 1, 2024 at 12:01 PM Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> >
> > Hi Michael,
> >  
> > > > >>>> Ported the patch from patchset
> > > > >>>>
> > > > >>>> "[PATCH 05/26] clk: imx8mm: Mark IMX8MM_SYS_PLL2 and IMX8MM_SYS_PLL3 as enabled"
> > > > >>>>
> > > > >>>> to imx8mp [2] and fec ethernet works again for me on imx8mp!
> > > > >>>>
> > > > >>>> Could you add this if you post a v2 ?  
> > > > >>>
> > > > >>> TBH I don't feel like the below change is the correct one, it is too
> > > > >>> specific. The clock core is recursive and thus should handle the
> > > > >>> reparenting situations gracefully.
> > > > >>>
> > > > >>> I posted a series that is targeting the LVDS output on imx8mp. You
> > > > >>> should probably consider checking these patches as well if you work
> > > > >>> on imx8mp as well. I also had similar breakages with Ethernet which
> > > > >>> happened during the assigned-clocks handling. This patch, which is more
> > > > >>> future and platform agnostic, fixed it:
> > > > >>>
> > > > >>> https://lore.kernel.org/u-boot/20240910101344.110633-3-miquel.raynal@bootlin.com/
> > > > >>>  
> > > > >>
> > > > >> The clock patches are not specific at all. You need to have it working
> > > > >> for the parent for each component.  
> > > > >
> > > > > The diff shown by Heiko is explicitly enabling PLLs by naming them in
> > > > > the iMX driver. This is not the correct approach. The problem of
> > > > > having non-enabled new parents is global. Parent clocks should be
> > > > > enabled before changing muxes, and this should be enforced
> > > > > by the clock core/uclass, not the SoC drivers.  
> > > >
> > > > Okay, valid argument.
> > > >  
> > > > >  
> > > > >> This is a standard way to do it and nothing magic compared to other
> > > > >> implementations.  
> > > > >
> > > > > No, naming PLLs explicitly is not the correct approach.
> > > > >  
> > > > >> I don't see
> > > > >> in your series any addressing or reparent clock or take in account
> > > > >> that a clock should be enable before
> > > > >> reparenting.  
> > > > >
> > > > > That's exactly the link above, whose diff is pasted here for reference:
> > > > >
> > > > > @@ -595,6 +595,10 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
> > > > >       if (!ops->set_parent)
> > > > >               return -ENOSYS;
> > > > >
> > > > > +     ret = clk_enable(parent);
> > > > > +     if (ret)
> > > > > +             return ret;  
> > > >
> > > > As I said before, I had *exact* the same patch and thought I made a big
> > > > hack :-P
> > > >
> > > > But I wonder ... if this a generic "problem", why nobody had yet problems
> > > > with it...  
> > >
> > > I think that a generic approach that takes into account the reparent
> > > is more valuable, then
> > > this.  
> >
> > I'm sorry I don't fully understand your answer. I assume you agree with
> > the generic approach quoted above.
> >  
> > > If a clock is enabled by another stage and we don't aware about
> > > it we need to mark
> > > as enabled.  
> >
> > clk_enable() already handles this kind of situation.
> >  
> > > I think that this force of enable it's just a short path
> > > that does not solve the generic
> > > problem.  
> >
> > What "force of enable"? The parent needs to be enabled before we use it
> > as parent. The logic is always the same:
> > - clk_enable() the new parent
> > - change the parent
> > - clk_disable() the old parent
> > I don't see any short path here.
> >  
> > > I really tried to abstract what is really implemented in
> > > other OS on the same topic.  
> >
> > FYI, Linux does the clk_enable(parent) like above.
> >  
> 
> You mean linux enables a clock in set_parent even if the clock_chain
> is not yet enabled.
> clock a disable
> clock b disable
> 
> clk_set_parent(a, b) b->a now b is enabled?

Actually you're right Linux does the enable call only if a flag is set
(and anyway it's not in the faulty case reported above) or when the
reparented clock is already clocking. I'll have to check again with
this clk_enable() solves the situation and what could be done instead.

Thanks,
Miquèl

^ permalink raw reply	[flat|nested] 48+ messages in thread

end of thread, other threads:[~2024-10-01 20:55 UTC | newest]

Thread overview: 48+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-09-13  9:55 [PATCH 00/26] Support display (and even more) on the BSH SMM S2/PRO boards Dario Binacchi
2024-09-13  9:55 ` [PATCH 01/26] clk: Propagate clk_set_rate() if CLK_SET_PARENT_RATE present for gate and mux Dario Binacchi
2024-09-13  9:55 ` [PATCH 02/26] clk: imx8mn: Prevent clock critical path from disabling during reparent and set_rate Dario Binacchi
2024-09-13  9:55 ` [PATCH 03/26] clk: imx8mm: " Dario Binacchi
2024-09-13 10:09   ` Marek Vasut
2024-09-13  9:55 ` [PATCH 04/26] clk: clk-uclass: Implement CLK_OPS_PARENT_ENABLE Dario Binacchi
2024-09-13  9:55 ` [PATCH 05/26] clk: imx8mm: Mark IMX8MM_SYS_PLL2 and IMX8MM_SYS_PLL3 as enabled Dario Binacchi
2024-09-13 10:07   ` Marek Vasut
2024-09-13  9:55 ` [PATCH 06/26] clk: imx8mn: Mark IMX8MN_SYS_PLL2 and IMX8MN_SYS_PLL3 " Dario Binacchi
2024-09-13  9:55 ` [PATCH 07/26] clk: imx8mn: add video clocks support Dario Binacchi
2024-09-13  9:55 ` [PATCH 08/26] power: Add iMX8M block ctrl driver for dispmix Dario Binacchi
2024-09-24  9:05   ` Heiko Schocher
2024-09-30 13:20     ` Dario Binacchi
2024-10-01  4:21       ` Heiko Schocher
2024-10-01  5:01         ` Michael Nazzareno Trimarchi
2024-10-01  5:14           ` Heiko Schocher
2024-10-01  5:51             ` Heiko Schocher
2024-10-01  8:29               ` Miquel Raynal
2024-10-01  8:33                 ` Michael Nazzareno Trimarchi
2024-10-01  8:50                   ` Miquel Raynal
2024-10-01  8:57                     ` Heiko Schocher
2024-10-01  9:50                       ` Michael Nazzareno Trimarchi
2024-10-01 10:01                         ` Miquel Raynal
2024-10-01 13:02                           ` Michael Nazzareno Trimarchi
2024-10-01 20:54                             ` Miquel Raynal
2024-10-01  9:55                       ` Miquel Raynal
2024-10-01  8:47                 ` Heiko Schocher
2024-10-01  8:56                   ` Miquel Raynal
2024-09-13  9:55 ` [PATCH 09/26] video: Add video link framework Dario Binacchi
2024-09-13  9:55 ` [PATCH 10/26] video: bridge: Add check_timing interface Dario Binacchi
2024-09-13  9:55 ` [PATCH 11/26] video: dsi_host: add disable host interface Dario Binacchi
2024-09-13  9:55 ` [PATCH 12/26] video: Update mxsfb video drivers for iMX8MM/iMX8MN display Dario Binacchi
2024-09-13  9:55 ` [PATCH 13/26] video: Enable DM_UC_FLAG_SEQ_ALIAS for display and bridge Dario Binacchi
2024-09-13  9:55 ` [PATCH 14/26] phy: dphy: add support to calculate the timing based on hs_clk_rate Dario Binacchi
2024-09-13  9:55 ` [PATCH 15/26] phy: dphy: Correct lpx parameter and its derivatives(ta_{get, go, sure}) Dario Binacchi
2024-09-13  9:55 ` [PATCH 16/26] phy: dphy: Correct clk_pre parameter Dario Binacchi
2024-09-13  9:55 ` [PATCH 17/26] lib: div64: sync with Linux Dario Binacchi
2024-09-13  9:56 ` [PATCH 18/26] video: bridge: Add Samsung DSIM bridge Dario Binacchi
2024-09-13  9:56 ` [PATCH 19/26] video: Add Synaptics R63353 panel driver Dario Binacchi
2024-09-13  9:56 ` [PATCH 20/26] imx8mn_bsh_smm_s2/pro: Enable display on reference design Dario Binacchi
2024-09-13  9:56 ` [PATCH 21/26] boot: fdt_simplefb: add a debug message Dario Binacchi
2024-09-13  9:56 ` [PATCH 22/26] video: mxsfb: support simple frame-buffer Dario Binacchi
2024-09-13  9:56 ` [PATCH 23/26] video: bridge: samsung: " Dario Binacchi
2024-09-13  9:56 ` [PATCH 24/26] imx8mn_bsh_smm_s2/pro: " Dario Binacchi
2024-09-13  9:56 ` [PATCH 25/26] imx8mn_bsh_smm_s2/pro: enable " Dario Binacchi
2024-09-13  9:56 ` [PATCH 26/26] imx8mn_bsh_smm_s2/pro: add splash screen with BSH logo Dario Binacchi
2024-09-30  9:43 ` [PATCH 00/26] Support display (and even more) on the BSH SMM S2/PRO boards Miquel Raynal
2024-09-30 13:07   ` Dario Binacchi

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