linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v6 0/4] Add support for DU/DSI clocks and DSI driver support for the Renesas RZ/V2H(P) SoC
@ 2025-05-30 17:18 Prabhakar
  2025-05-30 17:18 ` [PATCH v6 1/4] clk: renesas: rzv2h-cpg: Add support for DSI clocks Prabhakar
                   ` (3 more replies)
  0 siblings, 4 replies; 18+ messages in thread
From: Prabhakar @ 2025-05-30 17:18 UTC (permalink / raw)
  To: Geert Uytterhoeven, Andrzej Hajda, Neil Armstrong, Robert Foss,
	Laurent Pinchart, Jonas Karlman, Jernej Skrabec,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Michael Turquette, Stephen Boyd, Biju Das, Magnus Damm
  Cc: dri-devel, devicetree, linux-kernel, linux-renesas-soc, linux-clk,
	Prabhakar, Fabrizio Castro, Lad Prabhakar

From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>

Hi All,

This patch series adds DU/DSI clocks and provides support for the
MIPI DSI interface on the RZ/V2H(P) SoC. It was originally part of
series [0], but has now been split into 4 patches due to dependencies
on the clock driver, making it easier to review and merge.

[0] https://lore.kernel.org/all/20250430204112.342123-1-prabhakar.mahadev-lad.rj@bp.renesas.com/

Note: This patch series applies on top of the following patch series:
[1] https://lore.kernel.org/all/20250530165906.411144-1-prabhakar.mahadev-lad.rj@bp.renesas.com/

v5-> v6:
- Renamed CPG_PLL_STBY_SSCGEN_WEN to CPG_PLL_STBY_SSC_EN_WEN
- Updated CPG_PLL_CLK1_DIV_K, CPG_PLL_CLK1_DIV_M, and
  CPG_PLL_CLK1_DIV_P macros to use GENMASK
- Updated req->rate in rzv2h_cpg_plldsi_div_determine_rate()
- Dropped the cast in rzv2h_cpg_plldsi_div_set_rate()
- Dropped rzv2h_cpg_plldsi_round_rate() and implemented
  rzv2h_cpg_plldsi_determine_rate() instead
- Made use of FIELD_PREP()
- Moved CPG_CSDIV1 macro in patch 2/4
- Dropped two_pow_s in rzv2h_dsi_get_pll_parameters_values()
- Used mul_u32_u32() while calculating output_m and output_k_range
- Used div_s64() instead of div64_s64() while calculating
  pll_k
- Used mul_u32_u32() while calculating fvco and fvco checks
- Rounded the final output using DIV_U64_ROUND_CLOSEST()
- Renamed CLK_DIV_PLLETH_LPCLK to CLK_CDIV4_PLLETH_LPCLK
- Renamed CLK_CSDIV_PLLETH_LPCLK to CLK_PLLETH_LPCLK_GEAR
- Renamed CLK_PLLDSI_SDIV2 to CLK_PLLDSI_GEAR
- Renamed plldsi_sdiv2 to plldsi_gear
- Preserved the sort order (by part number).
- Added reviewed tag from Geert.
- Made use of GENMASK() macro for PLLCLKSET0R_PLL_*,
  PHYTCLKSETR_* and PHYTHSSETR_* macros.
- Replaced 10000000UL with 10 * MEGA
- Renamed mode_freq_hz to mode_freq_khz in rzv2h_dsi_mode_calc
- Replaced `i -= 1;` with `i--;`
- Renamed RZV2H_MIPI_DPHY_FOUT_MIN_IN_MEGA to
  RZV2H_MIPI_DPHY_FOUT_MIN_IN_MHZ and
  RZV2H_MIPI_DPHY_FOUT_MAX_IN_MEGA to
  RZV2H_MIPI_DPHY_FOUT_MAX_IN_MHZ.
  
Cheers,
Prabhakar

Lad Prabhakar (4):
  clk: renesas: rzv2h-cpg: Add support for DSI clocks
  clk: renesas: r9a09g057: Add clock and reset entries for DSI and LCDC
  dt-bindings: display: bridge: renesas,dsi: Add support for RZ/V2H(P)
    SoC
  drm: renesas: rz-du: mipi_dsi: Add support for RZ/V2H(P) SoC

 .../bindings/display/bridge/renesas,dsi.yaml  | 116 ++++--
 drivers/clk/renesas/r9a09g057-cpg.c           |  63 ++++
 drivers/clk/renesas/rzv2h-cpg.c               | 278 +++++++++++++-
 drivers/clk/renesas/rzv2h-cpg.h               |  17 +
 .../gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c    | 345 ++++++++++++++++++
 .../drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h   |  34 ++
 include/linux/clk/renesas-rzv2h-dsi.h         | 210 +++++++++++
 7 files changed, 1025 insertions(+), 38 deletions(-)
 create mode 100644 include/linux/clk/renesas-rzv2h-dsi.h

-- 
2.49.0


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

* [PATCH v6 1/4] clk: renesas: rzv2h-cpg: Add support for DSI clocks
  2025-05-30 17:18 [PATCH v6 0/4] Add support for DU/DSI clocks and DSI driver support for the Renesas RZ/V2H(P) SoC Prabhakar
@ 2025-05-30 17:18 ` Prabhakar
  2025-06-13  5:57   ` Biju Das
  2025-05-30 17:18 ` [PATCH v6 2/4] clk: renesas: r9a09g057: Add clock and reset entries for DSI and LCDC Prabhakar
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 18+ messages in thread
From: Prabhakar @ 2025-05-30 17:18 UTC (permalink / raw)
  To: Geert Uytterhoeven, Andrzej Hajda, Neil Armstrong, Robert Foss,
	Laurent Pinchart, Jonas Karlman, Jernej Skrabec,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Michael Turquette, Stephen Boyd, Biju Das, Magnus Damm
  Cc: dri-devel, devicetree, linux-kernel, linux-renesas-soc, linux-clk,
	Prabhakar, Fabrizio Castro, Lad Prabhakar

From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>

Add support for PLLDSI and PLLDSI divider clocks.

Introduce the `renesas-rzv2h-dsi.h` header to centralize and share
PLLDSI-related data structures, limits, and algorithms between the RZ/V2H
CPG and DSI drivers.

The DSI PLL is functionally similar to the CPG's PLLDSI, but has slightly
different parameter limits and omits the programmable divider present in
CPG. To ensure precise frequency calculations-especially for milliHz-level
accuracy needed by the DSI driver-the shared algorithm allows both drivers
to compute PLL parameters consistently using the same logic and input
clock.

Co-developed-by: Fabrizio Castro <fabrizio.castro.jz@renesas.com>
Signed-off-by: Fabrizio Castro <fabrizio.castro.jz@renesas.com>
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
v5->v6:
- Renamed CPG_PLL_STBY_SSCGEN_WEN to CPG_PLL_STBY_SSC_EN_WEN
- Updated CPG_PLL_CLK1_DIV_K, CPG_PLL_CLK1_DIV_M, and
  CPG_PLL_CLK1_DIV_P macros to use GENMASK
- Updated req->rate in rzv2h_cpg_plldsi_div_determine_rate()
- Dropped the cast in rzv2h_cpg_plldsi_div_set_rate()
- Dropped rzv2h_cpg_plldsi_round_rate() and implemented
  rzv2h_cpg_plldsi_determine_rate() instead
- Made use of FIELD_PREP()
- Moved CPG_CSDIV1 macro in patch 2/4
- Dropped two_pow_s in rzv2h_dsi_get_pll_parameters_values()
- Used mul_u32_u32() while calculating output_m and output_k_range
- Used div_s64() instead of div64_s64() while calculating
  pll_k
- Used mul_u32_u32() while calculating fvco and fvco checks
- Rounded the final output using DIV_U64_ROUND_CLOSEST()

v4->v5:
- No changes

v3->v4:
- Corrected parameter name in rzv2h_dsi_get_pll_parameters_values()
  description freq_millihz

v2->v3:
- Update the commit message to clarify the purpose of `renesas-rzv2h-dsi.h`
  header
- Used mul_u32_u32() in rzv2h_cpg_plldsi_div_determine_rate()
- Replaced *_mhz to *_millihz for clarity
- Updated u64->u32 for fvco limits
- Initialized the members in declaration order for
  RZV2H_CPG_PLL_DSI_LIMITS() macro
- Used clk_div_mask() in rzv2h_cpg_plldsi_div_recalc_rate()
- Replaced `unsigned long long` with u64
- Dropped rzv2h_cpg_plldsi_clk_recalc_rate() and reused
  rzv2h_cpg_pll_clk_recalc_rate() instead
- In rzv2h_cpg_plldsi_div_set_rate() followed the same style
  of RMW-operation as done in the other functions
- Renamed rzv2h_cpg_plldsi_set_rate() to rzv2h_cpg_pll_set_rate()
- Dropped rzv2h_cpg_plldsi_clk_register() and reused
  rzv2h_cpg_pll_clk_register() instead
- Added a gaurd in renesas-rzv2h-dsi.h header

v1->v2:
- No changes
---
 drivers/clk/renesas/rzv2h-cpg.c       | 278 +++++++++++++++++++++++++-
 drivers/clk/renesas/rzv2h-cpg.h       |  13 ++
 include/linux/clk/renesas-rzv2h-dsi.h | 210 +++++++++++++++++++
 3 files changed, 492 insertions(+), 9 deletions(-)
 create mode 100644 include/linux/clk/renesas-rzv2h-dsi.h

diff --git a/drivers/clk/renesas/rzv2h-cpg.c b/drivers/clk/renesas/rzv2h-cpg.c
index 761da3bf77ce..d590f9f47371 100644
--- a/drivers/clk/renesas/rzv2h-cpg.c
+++ b/drivers/clk/renesas/rzv2h-cpg.c
@@ -14,9 +14,13 @@
 #include <linux/bitfield.h>
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/clk/renesas-rzv2h-dsi.h>
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/iopoll.h>
+#include <linux/math.h>
+#include <linux/math64.h>
+#include <linux/minmax.h>
 #include <linux/mod_devicetable.h>
 #include <linux/module.h>
 #include <linux/of.h>
@@ -26,6 +30,7 @@
 #include <linux/refcount.h>
 #include <linux/reset-controller.h>
 #include <linux/string_choices.h>
+#include <linux/units.h>
 
 #include <dt-bindings/clock/renesas-cpg-mssr.h>
 
@@ -48,12 +53,13 @@
 #define CPG_PLL_STBY(x)		((x))
 #define CPG_PLL_STBY_RESETB	BIT(0)
 #define CPG_PLL_STBY_RESETB_WEN	BIT(16)
+#define CPG_PLL_STBY_SSC_EN_WEN BIT(18)
 #define CPG_PLL_CLK1(x)		((x) + 0x004)
-#define CPG_PLL_CLK1_KDIV(x)	((s16)FIELD_GET(GENMASK(31, 16), (x)))
-#define CPG_PLL_CLK1_MDIV(x)	FIELD_GET(GENMASK(15, 6), (x))
-#define CPG_PLL_CLK1_PDIV(x)	FIELD_GET(GENMASK(5, 0), (x))
+#define CPG_PLL_CLK1_KDIV	GENMASK(31, 16)
+#define CPG_PLL_CLK1_MDIV	GENMASK(15, 6)
+#define CPG_PLL_CLK1_PDIV	GENMASK(5, 0)
 #define CPG_PLL_CLK2(x)		((x) + 0x008)
-#define CPG_PLL_CLK2_SDIV(x)	FIELD_GET(GENMASK(2, 0), (x))
+#define CPG_PLL_CLK2_SDIV	GENMASK(2, 0)
 #define CPG_PLL_MON(x)		((x) + 0x010)
 #define CPG_PLL_MON_RESETB	BIT(0)
 #define CPG_PLL_MON_LOCK	BIT(4)
@@ -79,6 +85,8 @@
  * @last_dt_core_clk: ID of the last Core Clock exported to DT
  * @mstop_count: Array of mstop values
  * @rcdev: Reset controller entity
+ * @dsi_limits: PLL DSI parameters limits
+ * @plldsi_div_parameters: PLL DSI and divider parameters configuration
  */
 struct rzv2h_cpg_priv {
 	struct device *dev;
@@ -95,6 +103,9 @@ struct rzv2h_cpg_priv {
 	atomic_t *mstop_count;
 
 	struct reset_controller_dev rcdev;
+
+	const struct rzv2h_pll_div_limits *dsi_limits;
+	struct rzv2h_plldsi_parameters plldsi_div_parameters;
 };
 
 #define rcdev_to_priv(x)	container_of(x, struct rzv2h_cpg_priv, rcdev)
@@ -150,6 +161,24 @@ struct ddiv_clk {
 
 #define to_ddiv_clock(_div) container_of(_div, struct ddiv_clk, div)
 
+/**
+ * struct rzv2h_plldsi_div_clk - PLL DSI DDIV clock
+ *
+ * @dtable: divider table
+ * @priv: CPG private data
+ * @hw: divider clk
+ * @ddiv: divider configuration
+ */
+struct rzv2h_plldsi_div_clk {
+	const struct clk_div_table *dtable;
+	struct rzv2h_cpg_priv *priv;
+	struct clk_hw hw;
+	struct ddiv ddiv;
+};
+
+#define to_plldsi_div_clk(_hw) \
+	container_of(_hw, struct rzv2h_plldsi_div_clk, hw)
+
 static int rzv2h_cpg_pll_clk_is_enabled(struct clk_hw *hw)
 {
 	struct pll_clk *pll_clk = to_pll(hw);
@@ -198,6 +227,214 @@ static int rzv2h_cpg_pll_clk_enable(struct clk_hw *hw)
 	return ret;
 }
 
+static unsigned long rzv2h_cpg_plldsi_div_recalc_rate(struct clk_hw *hw,
+						      unsigned long parent_rate)
+{
+	struct rzv2h_plldsi_div_clk *dsi_div = to_plldsi_div_clk(hw);
+	struct rzv2h_cpg_priv *priv = dsi_div->priv;
+	struct ddiv ddiv = dsi_div->ddiv;
+	u32 div;
+
+	div = readl(priv->base + ddiv.offset);
+	div >>= ddiv.shift;
+	div &= clk_div_mask(ddiv.width);
+	div = dsi_div->dtable[div].div;
+
+	return DIV_ROUND_CLOSEST_ULL(parent_rate, div);
+}
+
+static int rzv2h_cpg_plldsi_div_determine_rate(struct clk_hw *hw,
+					       struct clk_rate_request *req)
+{
+	struct rzv2h_plldsi_div_clk *dsi_div = to_plldsi_div_clk(hw);
+	struct rzv2h_cpg_priv *priv = dsi_div->priv;
+	struct rzv2h_plldsi_parameters *dsi_dividers = &priv->plldsi_div_parameters;
+	u64 rate_millihz;
+
+	/*
+	 * Adjust the requested clock rate (`req->rate`) to ensure it falls within
+	 * the supported range of 5.44 MHz to 187.5 MHz.
+	 */
+	req->rate = clamp(req->rate, 5440000UL, 187500000UL);
+
+	rate_millihz = mul_u32_u32(req->rate, MILLI);
+	if (rate_millihz == dsi_dividers->error_millihz + dsi_dividers->freq_millihz)
+		goto exit_determine_rate;
+
+	if (!rzv2h_dsi_get_pll_parameters_values(priv->dsi_limits,
+						 dsi_dividers, rate_millihz)) {
+		dev_err(priv->dev,
+			"failed to determine rate for req->rate: %lu\n",
+			req->rate);
+		return -EINVAL;
+	}
+
+exit_determine_rate:
+	req->best_parent_rate = req->rate * dsi_dividers->csdiv;
+	req->rate = DIV_ROUND_CLOSEST_ULL(dsi_dividers->freq_millihz, MILLI);
+
+	return 0;
+};
+
+static int rzv2h_cpg_plldsi_div_set_rate(struct clk_hw *hw,
+					 unsigned long rate,
+					 unsigned long parent_rate)
+{
+	struct rzv2h_plldsi_div_clk *dsi_div = to_plldsi_div_clk(hw);
+	struct rzv2h_cpg_priv *priv = dsi_div->priv;
+	struct rzv2h_plldsi_parameters *dsi_dividers = &priv->plldsi_div_parameters;
+	struct ddiv ddiv = dsi_div->ddiv;
+	const struct clk_div_table *clkt;
+	bool div_found = false;
+	u32 val, shift, div;
+
+	div = dsi_dividers->csdiv;
+	for (clkt = dsi_div->dtable; clkt->div; clkt++) {
+		if (clkt->div == div) {
+			div_found = true;
+			break;
+		}
+	}
+
+	if (!div_found)
+		return -EINVAL;
+
+	shift = ddiv.shift;
+	val = readl(priv->base + ddiv.offset) | DDIV_DIVCTL_WEN(shift);
+	val &= ~(clk_div_mask(ddiv.width) << shift);
+	val |= clkt->val << shift;
+	writel(val, priv->base + ddiv.offset);
+
+	return 0;
+};
+
+static const struct clk_ops rzv2h_cpg_plldsi_div_ops = {
+	.recalc_rate = rzv2h_cpg_plldsi_div_recalc_rate,
+	.determine_rate = rzv2h_cpg_plldsi_div_determine_rate,
+	.set_rate = rzv2h_cpg_plldsi_div_set_rate,
+};
+
+static struct clk * __init
+rzv2h_cpg_plldsi_div_clk_register(const struct cpg_core_clk *core,
+				  struct rzv2h_cpg_priv *priv)
+{
+	struct rzv2h_plldsi_div_clk *clk_hw_data;
+	struct clk **clks = priv->clks;
+	struct clk_init_data init;
+	const struct clk *parent;
+	const char *parent_name;
+	struct clk_hw *clk_hw;
+	int ret;
+
+	parent = clks[core->parent];
+	if (IS_ERR(parent))
+		return ERR_CAST(parent);
+
+	clk_hw_data = devm_kzalloc(priv->dev, sizeof(*clk_hw_data), GFP_KERNEL);
+	if (!clk_hw_data)
+		return ERR_PTR(-ENOMEM);
+
+	clk_hw_data->priv = priv;
+	clk_hw_data->ddiv = core->cfg.ddiv;
+	clk_hw_data->dtable = core->dtable;
+
+	parent_name = __clk_get_name(parent);
+	init.name = core->name;
+	init.ops = &rzv2h_cpg_plldsi_div_ops;
+	init.flags = core->flag;
+	init.parent_names = &parent_name;
+	init.num_parents = 1;
+
+	clk_hw = &clk_hw_data->hw;
+	clk_hw->init = &init;
+
+	ret = devm_clk_hw_register(priv->dev, clk_hw);
+	if (ret)
+		return ERR_PTR(ret);
+
+	return clk_hw->clk;
+}
+
+static int rzv2h_cpg_plldsi_determine_rate(struct clk_hw *hw,
+					   struct clk_rate_request *req)
+{
+	struct rzv2h_pll_div_limits dsi_limits;
+	struct rzv2h_plldsi_parameters dsi_dividers;
+	struct pll_clk *pll_clk = to_pll(hw);
+	struct rzv2h_cpg_priv *priv = pll_clk->priv;
+	u64 rate_millihz;
+
+	memcpy(&dsi_limits, priv->dsi_limits, sizeof(dsi_limits));
+	dsi_limits.csdiv.min = 1;
+	dsi_limits.csdiv.max = 1;
+
+	req->rate = clamp(req->rate, 25000000UL, 375000000UL);
+
+	rate_millihz = mul_u32_u32(req->rate, MILLI);
+	if (!rzv2h_dsi_get_pll_parameters_values(priv->dsi_limits,
+						 &dsi_dividers, rate_millihz)) {
+		dev_err(priv->dev,
+			"failed to determine rate for req->rate: %lu\n",
+			req->rate);
+		return -EINVAL;
+	}
+
+	req->best_parent_rate = req->rate * dsi_dividers.csdiv;
+	req->rate = DIV_ROUND_CLOSEST_ULL(dsi_dividers.freq_millihz, MILLI);
+
+	return 0;
+}
+
+static int rzv2h_cpg_pll_set_rate(struct clk_hw *hw,
+				  unsigned long rate,
+				  unsigned long parent_rate)
+{
+	struct pll_clk *pll_clk = to_pll(hw);
+	struct rzv2h_cpg_priv *priv = pll_clk->priv;
+	struct rzv2h_plldsi_parameters *dsi_dividers;
+	struct pll pll = pll_clk->pll;
+	u16 offset = pll.offset;
+	u32 val;
+	int ret;
+
+	/* Put PLL into standby mode */
+	writel(CPG_PLL_STBY_RESETB_WEN, priv->base + CPG_PLL_STBY(offset));
+	ret = readl_poll_timeout_atomic(priv->base + CPG_PLL_MON(offset),
+					val, !(val & CPG_PLL_MON_LOCK),
+					100, 2000);
+	if (ret) {
+		dev_err(priv->dev, "Failed to put PLLDSI into standby mode");
+		return ret;
+	}
+
+	dsi_dividers = &priv->plldsi_div_parameters;
+	/* Output clock setting 1 */
+	writel(FIELD_PREP(CPG_PLL_CLK1_KDIV, (u16)dsi_dividers->k) |
+	       FIELD_PREP(CPG_PLL_CLK1_MDIV, dsi_dividers->m) |
+	       FIELD_PREP(CPG_PLL_CLK1_PDIV, dsi_dividers->p),
+	       priv->base + CPG_PLL_CLK1(offset));
+
+	/* Output clock setting 2 */
+	val = readl(priv->base + CPG_PLL_CLK2(offset));
+	writel((val & ~CPG_PLL_CLK2_SDIV) | FIELD_PREP(CPG_PLL_CLK2_SDIV, dsi_dividers->s),
+	       priv->base + CPG_PLL_CLK2(offset));
+
+	/* Put PLL to normal mode */
+	writel(CPG_PLL_STBY_RESETB_WEN | CPG_PLL_STBY_RESETB,
+	       priv->base + CPG_PLL_STBY(offset));
+
+	/* PLL normal mode transition, output clock stability check */
+	ret = readl_poll_timeout_atomic(priv->base + CPG_PLL_MON(offset),
+					val, (val & CPG_PLL_MON_LOCK),
+					100, 2000);
+	if (ret) {
+		dev_err(priv->dev, "Failed to put PLLDSI into normal mode");
+		return ret;
+	}
+
+	return 0;
+};
+
 static unsigned long rzv2h_cpg_pll_clk_recalc_rate(struct clk_hw *hw,
 						   unsigned long parent_rate)
 {
@@ -213,12 +450,19 @@ static unsigned long rzv2h_cpg_pll_clk_recalc_rate(struct clk_hw *hw,
 	clk1 = readl(priv->base + CPG_PLL_CLK1(pll.offset));
 	clk2 = readl(priv->base + CPG_PLL_CLK2(pll.offset));
 
-	rate = mul_u64_u32_shr(parent_rate, (CPG_PLL_CLK1_MDIV(clk1) << 16) +
-			       CPG_PLL_CLK1_KDIV(clk1), 16 + CPG_PLL_CLK2_SDIV(clk2));
+	rate = mul_u64_u32_shr(parent_rate, (FIELD_GET(CPG_PLL_CLK1_MDIV, clk1) << 16) +
+			       (s16)FIELD_GET(CPG_PLL_CLK1_KDIV, clk1),
+			       16 + FIELD_GET(CPG_PLL_CLK2_SDIV, clk2));
 
-	return DIV_ROUND_CLOSEST_ULL(rate, CPG_PLL_CLK1_PDIV(clk1));
+	return DIV_ROUND_CLOSEST_ULL(rate, FIELD_GET(CPG_PLL_CLK1_PDIV, clk1));
 }
 
+static const struct clk_ops rzv2h_cpg_plldsi_ops = {
+	.recalc_rate = rzv2h_cpg_pll_clk_recalc_rate,
+	.determine_rate = rzv2h_cpg_plldsi_determine_rate,
+	.set_rate = rzv2h_cpg_pll_set_rate,
+};
+
 static const struct clk_ops rzv2h_cpg_pll_ops = {
 	.is_enabled = rzv2h_cpg_pll_clk_is_enabled,
 	.enable = rzv2h_cpg_pll_clk_enable,
@@ -228,7 +472,8 @@ static const struct clk_ops rzv2h_cpg_pll_ops = {
 static struct clk * __init
 rzv2h_cpg_pll_clk_register(const struct cpg_core_clk *core,
 			   struct rzv2h_cpg_priv *priv,
-			   const struct clk_ops *ops)
+			   const struct clk_ops *ops,
+			   bool turn_on)
 {
 	void __iomem *base = priv->base;
 	struct device *dev = priv->dev;
@@ -258,6 +503,13 @@ rzv2h_cpg_pll_clk_register(const struct cpg_core_clk *core,
 	pll_clk->base = base;
 	pll_clk->priv = priv;
 
+	if (turn_on) {
+		/* Disable SSC and turn on PLL clock when init */
+		writel(CPG_PLL_STBY_RESETB_WEN | CPG_PLL_STBY_RESETB |
+		       CPG_PLL_STBY_SSC_EN_WEN,
+		       base + CPG_PLL_STBY(pll_clk->pll.offset));
+	}
+
 	ret = devm_clk_hw_register(dev, &pll_clk->hw);
 	if (ret)
 		return ERR_PTR(ret);
@@ -500,7 +752,7 @@ rzv2h_cpg_register_core_clk(const struct cpg_core_clk *core,
 			clk = clk_hw->clk;
 		break;
 	case CLK_TYPE_PLL:
-		clk = rzv2h_cpg_pll_clk_register(core, priv, &rzv2h_cpg_pll_ops);
+		clk = rzv2h_cpg_pll_clk_register(core, priv, &rzv2h_cpg_pll_ops, false);
 		break;
 	case CLK_TYPE_DDIV:
 		clk = rzv2h_cpg_ddiv_clk_register(core, priv);
@@ -508,6 +760,12 @@ rzv2h_cpg_register_core_clk(const struct cpg_core_clk *core,
 	case CLK_TYPE_SMUX:
 		clk = rzv2h_cpg_mux_clk_register(core, priv);
 		break;
+	case CLK_TYPE_PLLDSI:
+		clk = rzv2h_cpg_pll_clk_register(core, priv, &rzv2h_cpg_plldsi_ops, true);
+		break;
+	case CLK_TYPE_PLLDSI_DIV:
+		clk = rzv2h_cpg_plldsi_div_clk_register(core, priv);
+		break;
 	default:
 		goto fail;
 	}
@@ -1043,6 +1301,8 @@ static int __init rzv2h_cpg_probe(struct platform_device *pdev)
 	priv->last_dt_core_clk = info->last_dt_core_clk;
 	priv->num_resets = info->num_resets;
 
+	priv->dsi_limits = info->plldsi_limits;
+
 	for (i = 0; i < nclks; i++)
 		clks[i] = ERR_PTR(-ENOENT);
 
diff --git a/drivers/clk/renesas/rzv2h-cpg.h b/drivers/clk/renesas/rzv2h-cpg.h
index 7321b085f937..1f1ef2fcf878 100644
--- a/drivers/clk/renesas/rzv2h-cpg.h
+++ b/drivers/clk/renesas/rzv2h-cpg.h
@@ -166,6 +166,8 @@ enum clk_types {
 	CLK_TYPE_PLL,
 	CLK_TYPE_DDIV,		/* Dynamic Switching Divider */
 	CLK_TYPE_SMUX,		/* Static Mux */
+	CLK_TYPE_PLLDSI,	/* PLLDSI */
+	CLK_TYPE_PLLDSI_DIV,	/* PLLDSI divider */
 };
 
 #define DEF_TYPE(_name, _id, _type...) \
@@ -193,6 +195,14 @@ enum clk_types {
 		 .num_parents = ARRAY_SIZE(_parent_names), \
 		 .flag = CLK_SET_RATE_PARENT, \
 		 .mux_flags = CLK_MUX_HIWORD_MASK)
+#define DEF_PLLDSI(_name, _id, _parent, _pll_packed) \
+	DEF_TYPE(_name, _id, CLK_TYPE_PLLDSI, .parent = _parent, .cfg.pll = _pll_packed)
+#define DEF_PLLDSI_DIV(_name, _id, _parent, _ddiv_packed, _dtable) \
+	DEF_TYPE(_name, _id, CLK_TYPE_PLLDSI_DIV, \
+		 .cfg.ddiv = _ddiv_packed, \
+		 .dtable = _dtable, \
+		 .parent = _parent, \
+		 .flag = CLK_SET_RATE_PARENT)
 
 /**
  * struct rzv2h_mod_clk - Module Clocks definitions
@@ -293,6 +303,7 @@ struct rzv2h_reset {
  *
  * @num_mstop_bits: Maximum number of MSTOP bits supported, equivalent to the
  *		    number of CPG_BUS_m_MSTOP registers multiplied by 16.
+ * @plldsi_limits: PLL DSI parameters limits
  */
 struct rzv2h_cpg_info {
 	/* Core Clocks */
@@ -311,6 +322,8 @@ struct rzv2h_cpg_info {
 	unsigned int num_resets;
 
 	unsigned int num_mstop_bits;
+
+	const struct rzv2h_pll_div_limits *plldsi_limits;
 };
 
 extern const struct rzv2h_cpg_info r9a09g047_cpg_info;
diff --git a/include/linux/clk/renesas-rzv2h-dsi.h b/include/linux/clk/renesas-rzv2h-dsi.h
new file mode 100644
index 000000000000..b77f9bc3777e
--- /dev/null
+++ b/include/linux/clk/renesas-rzv2h-dsi.h
@@ -0,0 +1,210 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Renesas RZ/V2H(P) DSI CPG helper
+ *
+ * Copyright (C) 2025 Renesas Electronics Corp.
+ */
+#ifndef __RENESAS_RZV2H_DSI_H__
+#define __RENESAS_RZV2H_DSI_H__
+
+#include <linux/limits.h>
+#include <linux/math.h>
+#include <linux/math64.h>
+#include <linux/units.h>
+
+#define OSC_CLK_IN_MEGA		(24 * MEGA)
+
+struct rzv2h_pll_div_limits {
+	struct {
+		u32 min;
+		u32 max;
+	} fvco;
+
+	struct {
+		u16 min;
+		u16 max;
+	} m;
+
+	struct {
+		u8 min;
+		u8 max;
+	} p;
+
+	struct {
+		u8 min;
+		u8 max;
+	} s;
+
+	struct {
+		s16 min;
+		s16 max;
+	} k;
+
+	struct {
+		u8 min;
+		u8 max;
+	} csdiv;
+};
+
+struct rzv2h_plldsi_parameters {
+	u64 freq_millihz;
+	s64 error_millihz;
+	u16 m;
+	s16 k;
+	u8 csdiv;
+	u8 p;
+	u8 s;
+};
+
+#define RZV2H_CPG_PLL_DSI_LIMITS(name)					\
+	static const struct rzv2h_pll_div_limits (name) = {		\
+		.fvco = { .min = 1600 * MEGA, .max = 3200 * MEGA },	\
+		.m = { .min = 64, .max = 533 },				\
+		.p = { .min = 1, .max = 4 },				\
+		.s = { .min = 0, .max = 6 },				\
+		.k = { .min = -32768, .max = 32767 },			\
+		.csdiv = { .min = 2, .max = 32 },			\
+	}								\
+
+/**
+ * rzv2h_dsi_get_pll_parameters_values - Finds the best combination of PLL parameters
+ * and divider value for a given frequency.
+ *
+ * @limits: Pointer to the structure containing the limits for the PLL parameters and
+ * divider values
+ * @pars: Pointer to the structure where the best calculated PLL parameters and divider
+ * values will be stored
+ * @freq_millihz: Target output frequency in millihertz
+ *
+ * This function calculates the best set of PLL parameters (M, K, P, S) and divider
+ * value (CSDIV) to achieve the desired frequency.
+ * There is no direct formula to calculate the PLL parameters and the divider value,
+ * as it's an open system of equations, therefore this function uses an iterative
+ * approach to determine the best solution. The best solution is one that minimizes
+ * the error (desired frequency - actual frequency).
+ *
+ * Return: true if a valid set of divider values is found, false otherwise.
+ */
+static __maybe_unused bool
+rzv2h_dsi_get_pll_parameters_values(const struct rzv2h_pll_div_limits *limits,
+				    struct rzv2h_plldsi_parameters *pars,
+				    u64 freq_millihz)
+{
+	struct rzv2h_plldsi_parameters p, best;
+
+	/* Initialize best error to maximum possible value */
+	best.error_millihz = S64_MAX;
+
+	for (p.csdiv = limits->csdiv.min; p.csdiv <= limits->csdiv.max; p.csdiv += 2) {
+		for (p.p = limits->p.min; p.p <= limits->p.max; p.p++) {
+			u32 fref = OSC_CLK_IN_MEGA / p.p;
+			u16 divider;
+
+			for (divider = p.csdiv << limits->s.min, p.s = limits->s.min;
+			     p.s <= limits->s.max; p.s++, divider *= 2) {
+				for (p.m = limits->m.min; p.m <= limits->m.max; p.m++) {
+					u64 output_m, output_k_range;
+					s64 pll_k, output_k;
+					u64 fvco, output;
+
+					/*
+					 * The frequency generated by the combination of the
+					 * PLL + divider is calculated as follows:
+					 *
+					 * Freq = Ffout / csdiv
+					 *
+					 * With:
+					 * Ffout = Ffvco / 2^(pll_s)
+					 * Ffvco = (pll_m + (pll_k / 65536)) * Ffref
+					 * Ffref = 24MHz / pll_p
+					 *
+					 * Freq can also be rewritten as:
+					 * Freq = Ffvco / (2^(pll_s) * csdiv))
+					 *      = Ffvco / divider
+					 *      = (pll_m * Ffref) / divider + ((pll_k / 65536) * Ffref) / divider
+					 *      = output_m + output_k
+					 *
+					 * Every parameter has been determined at this point, but pll_k.
+					 * Considering that:
+					 * -32768 <= pll_k <= 32767
+					 * Then:
+					 * -0.5 <= (pll_k / 65536) < 0.5
+					 * Therefore:
+					 * -Ffref / (2 * divider) <= output_k < Ffref / (2 * divider)
+					 */
+
+					/* Compute output M component (in mHz) */
+					output_m = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(p.m, fref) * MILLI,
+									 divider);
+					/* Compute range for output K (in mHz) */
+					output_k_range = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(fref, MILLI),
+									       divider * 2);
+					/*
+					 * No point in continuing if we can't achieve the
+					 * desired frequency
+					 */
+					if (freq_millihz <  (output_m - output_k_range) ||
+					    freq_millihz >= (output_m + output_k_range))
+						continue;
+
+					/*
+					 * Compute the K component
+					 *
+					 * Since:
+					 * Freq = output_m + output_k
+					 * Then:
+					 * output_k = Freq - output_m
+					 *          = ((pll_k / 65536) * Ffref) / divider
+					 * Therefore:
+					 * pll_k = (output_k * 65536 * divider) / Ffref
+					 */
+					output_k = freq_millihz - output_m;
+					pll_k = div_s64(output_k * 65536ULL * divider, fref);
+					pll_k = DIV_S64_ROUND_CLOSEST(pll_k, MILLI);
+
+					/* Validate K value within allowed limits */
+					if (pll_k < limits->k.min || pll_k > limits->k.max)
+						continue;
+
+					p.k = pll_k;
+
+					/* Compute (Ffvco * 65536) */
+					fvco = mul_u32_u32(p.m * 65536 + p.k, fref);
+					if ((fvco < mul_u32_u32(limits->fvco.min, 65536)) ||
+					    (fvco > mul_u32_u32(limits->fvco.max, 65536)))
+						continue;
+
+					/* PLL_M component of (output * 65536 * PLL_P) */
+					output = mul_u32_u32(p.m * 65536, OSC_CLK_IN_MEGA);
+					/* PLL_K component of (output * 65536 * PLL_P) */
+					output += p.k * OSC_CLK_IN_MEGA;
+					/* Make it in mHz */
+					output *= MILLI;
+					output = DIV_U64_ROUND_CLOSEST(output, 65536 * p.p * divider);
+
+					p.error_millihz = freq_millihz - output;
+					p.freq_millihz = output;
+
+					/* If an exact match is found, return immediately */
+					if (p.error_millihz == 0) {
+						*pars = p;
+						return true;
+					}
+
+					/* Update best match if error is smaller */
+					if (abs(best.error_millihz) > abs(p.error_millihz))
+						best = p;
+				}
+			}
+		}
+	}
+
+	/* If no valid parameters were found, return false */
+	if (best.error_millihz == S64_MAX)
+		return false;
+
+	*pars = best;
+	return true;
+}
+
+#endif	/* __RENESAS_RZV2H_DSI_H__ */
-- 
2.49.0


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

* [PATCH v6 2/4] clk: renesas: r9a09g057: Add clock and reset entries for DSI and LCDC
  2025-05-30 17:18 [PATCH v6 0/4] Add support for DU/DSI clocks and DSI driver support for the Renesas RZ/V2H(P) SoC Prabhakar
  2025-05-30 17:18 ` [PATCH v6 1/4] clk: renesas: rzv2h-cpg: Add support for DSI clocks Prabhakar
@ 2025-05-30 17:18 ` Prabhakar
  2025-05-30 17:18 ` [PATCH v6 3/4] dt-bindings: display: bridge: renesas,dsi: Add support for RZ/V2H(P) SoC Prabhakar
  2025-05-30 17:18 ` [PATCH v6 4/4] drm: renesas: rz-du: mipi_dsi: " Prabhakar
  3 siblings, 0 replies; 18+ messages in thread
From: Prabhakar @ 2025-05-30 17:18 UTC (permalink / raw)
  To: Geert Uytterhoeven, Andrzej Hajda, Neil Armstrong, Robert Foss,
	Laurent Pinchart, Jonas Karlman, Jernej Skrabec,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Michael Turquette, Stephen Boyd, Biju Das, Magnus Damm
  Cc: dri-devel, devicetree, linux-kernel, linux-renesas-soc, linux-clk,
	Prabhakar, Fabrizio Castro, Lad Prabhakar

From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>

Add clock and reset entries for the DSI and LCDC peripherals.

Co-developed-by: Fabrizio Castro <fabrizio.castro.jz@renesas.com>
Signed-off-by: Fabrizio Castro <fabrizio.castro.jz@renesas.com>
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
v5->v6:
- Renamed CLK_DIV_PLLETH_LPCLK to CLK_CDIV4_PLLETH_LPCLK
- Renamed CLK_CSDIV_PLLETH_LPCLK to CLK_PLLETH_LPCLK_GEAR
- Renamed CLK_PLLDSI_SDIV2 to CLK_PLLDSI_GEAR
- Renamed plldsi_sdiv2 to plldsi_gear

v4->v5:
- No changes

v3->v4:
- No changes

v2->v3:
- Reverted CSDIV0_DIVCTL2() to use DDIV_PACK()
- Renamed plleth_lpclk_div4 -> cdiv4_plleth_lpclk
- Renamed plleth_lpclk -> plleth_lpclk_gear

v1->v2:
- Changed CSDIV0_DIVCTL2 to the NO_RMW
---
 drivers/clk/renesas/r9a09g057-cpg.c | 63 +++++++++++++++++++++++++++++
 drivers/clk/renesas/rzv2h-cpg.h     |  4 ++
 2 files changed, 67 insertions(+)

diff --git a/drivers/clk/renesas/r9a09g057-cpg.c b/drivers/clk/renesas/r9a09g057-cpg.c
index 0a877cd30219..4be8240b2505 100644
--- a/drivers/clk/renesas/r9a09g057-cpg.c
+++ b/drivers/clk/renesas/r9a09g057-cpg.c
@@ -6,6 +6,7 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/clk/renesas-rzv2h-dsi.h>
 #include <linux/device.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -30,6 +31,7 @@ enum clk_ids {
 	CLK_PLLCA55,
 	CLK_PLLVDO,
 	CLK_PLLETH,
+	CLK_PLLDSI,
 	CLK_PLLGPU,
 
 	/* Internal Core Clocks */
@@ -63,6 +65,9 @@ enum clk_ids {
 	CLK_SMUX2_GBE0_RXCLK,
 	CLK_SMUX2_GBE1_TXCLK,
 	CLK_SMUX2_GBE1_RXCLK,
+	CLK_CDIV4_PLLETH_LPCLK,
+	CLK_PLLETH_LPCLK_GEAR,
+	CLK_PLLDSI_GEAR,
 	CLK_PLLGPU_GEAR,
 
 	/* Module Clocks */
@@ -91,6 +96,26 @@ static const struct clk_div_table dtable_2_16[] = {
 	{0, 0},
 };
 
+static const struct clk_div_table dtable_2_32[] = {
+	{0, 2},
+	{1, 4},
+	{2, 6},
+	{3, 8},
+	{4, 10},
+	{5, 12},
+	{6, 14},
+	{7, 16},
+	{8, 18},
+	{9, 20},
+	{10, 22},
+	{11, 24},
+	{12, 26},
+	{13, 28},
+	{14, 30},
+	{15, 32},
+	{0, 0},
+};
+
 static const struct clk_div_table dtable_2_64[] = {
 	{0, 2},
 	{1, 4},
@@ -107,6 +132,14 @@ static const struct clk_div_table dtable_2_100[] = {
 	{0, 0},
 };
 
+static const struct clk_div_table dtable_16_128[] = {
+	{0, 16},
+	{1, 32},
+	{2, 64},
+	{3, 128},
+	{0, 0},
+};
+
 /* Mux clock tables */
 static const char * const smux2_gbe0_rxclk[] = { ".plleth_gbe0", "et0_rxclk" };
 static const char * const smux2_gbe0_txclk[] = { ".plleth_gbe0", "et0_txclk" };
@@ -128,6 +161,7 @@ static const struct cpg_core_clk r9a09g057_core_clks[] __initconst = {
 	DEF_PLL(".pllca55", CLK_PLLCA55, CLK_QEXTAL, PLLCA55),
 	DEF_FIXED(".pllvdo", CLK_PLLVDO, CLK_QEXTAL, 105, 2),
 	DEF_FIXED(".plleth", CLK_PLLETH, CLK_QEXTAL, 125, 3),
+	DEF_PLLDSI(".plldsi", CLK_PLLDSI, CLK_QEXTAL, PLLDSI),
 	DEF_PLL(".pllgpu", CLK_PLLGPU, CLK_QEXTAL, PLLGPU),
 
 	/* Internal Core Clocks */
@@ -169,6 +203,12 @@ static const struct cpg_core_clk r9a09g057_core_clks[] __initconst = {
 	DEF_SMUX(".smux2_gbe0_rxclk", CLK_SMUX2_GBE0_RXCLK, SSEL0_SELCTL3, smux2_gbe0_rxclk),
 	DEF_SMUX(".smux2_gbe1_txclk", CLK_SMUX2_GBE1_TXCLK, SSEL1_SELCTL0, smux2_gbe1_txclk),
 	DEF_SMUX(".smux2_gbe1_rxclk", CLK_SMUX2_GBE1_RXCLK, SSEL1_SELCTL1, smux2_gbe1_rxclk),
+	DEF_FIXED(".cdiv4_plleth_lpclk", CLK_CDIV4_PLLETH_LPCLK, CLK_PLLETH, 1, 4),
+	DEF_CSDIV(".plleth_lpclk_gear", CLK_PLLETH_LPCLK_GEAR, CLK_CDIV4_PLLETH_LPCLK,
+		  CSDIV0_DIVCTL2, dtable_16_128),
+
+	DEF_PLLDSI_DIV(".plldsi_gear", CLK_PLLDSI_GEAR, CLK_PLLDSI,
+		       CSDIV1_DIVCTL2, dtable_2_32),
 
 	DEF_DDIV(".pllgpu_gear", CLK_PLLGPU_GEAR, CLK_PLLGPU, CDDIV3_DIVCTL1, dtable_2_64),
 
@@ -347,6 +387,22 @@ static const struct rzv2h_mod_clk r9a09g057_mod_clks[] __initconst = {
 						BUS_MSTOP(9, BIT(7))),
 	DEF_MOD("cru_3_pclk",			CLK_PLLDTY_DIV16, 13, 13, 6, 29,
 						BUS_MSTOP(9, BIT(7))),
+	DEF_MOD("dsi_0_pclk",			CLK_PLLDTY_DIV16, 14, 8, 7, 8,
+						BUS_MSTOP(9, BIT(14) | BIT(15))),
+	DEF_MOD("dsi_0_aclk",			CLK_PLLDTY_ACPU_DIV2, 14, 9, 7, 9,
+						BUS_MSTOP(9, BIT(14) | BIT(15))),
+	DEF_MOD("dsi_0_vclk1",			CLK_PLLDSI_GEAR, 14, 10, 7, 10,
+						BUS_MSTOP(9, BIT(14) | BIT(15))),
+	DEF_MOD("dsi_0_lpclk",			CLK_PLLETH_LPCLK_GEAR, 14, 11, 7, 11,
+						BUS_MSTOP(9, BIT(14) | BIT(15))),
+	DEF_MOD("dsi_0_pllref_clk",		CLK_QEXTAL, 14, 12, 7, 12,
+						BUS_MSTOP(9, BIT(14) | BIT(15))),
+	DEF_MOD("lcdc_0_clk_a",			CLK_PLLDTY_ACPU_DIV2, 14, 13, 7, 13,
+						BUS_MSTOP(10, BIT(1) | BIT(2) | BIT(3))),
+	DEF_MOD("lcdc_0_clk_p",			CLK_PLLDTY_DIV16, 14, 14, 7, 14,
+						BUS_MSTOP(10, BIT(1) | BIT(2) | BIT(3))),
+	DEF_MOD("lcdc_0_clk_d",			CLK_PLLDSI_GEAR, 14, 15, 7, 15,
+						BUS_MSTOP(10, BIT(1) | BIT(2) | BIT(3))),
 	DEF_MOD("gpu_0_clk",			CLK_PLLGPU_GEAR, 15, 0, 7, 16,
 						BUS_MSTOP(3, BIT(4))),
 	DEF_MOD("gpu_0_axi_clk",		CLK_PLLDTY_ACPU_DIV2, 15, 1, 7, 17,
@@ -410,11 +466,16 @@ static const struct rzv2h_reset r9a09g057_resets[] __initconst = {
 	DEF_RST(12, 14, 5, 31),		/* CRU_3_PRESETN */
 	DEF_RST(12, 15, 6, 0),		/* CRU_3_ARESETN */
 	DEF_RST(13, 0, 6, 1),		/* CRU_3_S_RESETN */
+	DEF_RST(13, 7, 6, 8),		/* DSI_0_PRESETN */
+	DEF_RST(13, 8, 6, 9),		/* DSI_0_ARESETN */
+	DEF_RST(13, 12, 6, 13),		/* LCDC_0_RESET_N */
 	DEF_RST(13, 13, 6, 14),		/* GPU_0_RESETN */
 	DEF_RST(13, 14, 6, 15),		/* GPU_0_AXI_RESETN */
 	DEF_RST(13, 15, 6, 16),		/* GPU_0_ACE_RESETN */
 };
 
+RZV2H_CPG_PLL_DSI_LIMITS(rzv2h_cpg_pll_dsi_limits);
+
 const struct rzv2h_cpg_info r9a09g057_cpg_info __initconst = {
 	/* Core Clocks */
 	.core_clks = r9a09g057_core_clks,
@@ -432,4 +493,6 @@ const struct rzv2h_cpg_info r9a09g057_cpg_info __initconst = {
 	.num_resets = ARRAY_SIZE(r9a09g057_resets),
 
 	.num_mstop_bits = 192,
+
+	.plldsi_limits = &rzv2h_cpg_pll_dsi_limits,
 };
diff --git a/drivers/clk/renesas/rzv2h-cpg.h b/drivers/clk/renesas/rzv2h-cpg.h
index 1f1ef2fcf878..864f5e7e8745 100644
--- a/drivers/clk/renesas/rzv2h-cpg.h
+++ b/drivers/clk/renesas/rzv2h-cpg.h
@@ -28,6 +28,7 @@ struct pll {
 	})
 
 #define PLLCA55		PLL_PACK(0x60, 1)
+#define PLLDSI		PLL_PACK(0xc0, 1)
 #define PLLGPU		PLL_PACK(0x120, 1)
 
 /**
@@ -100,6 +101,7 @@ struct smuxed {
 #define CPG_CDDIV3		(0x40C)
 #define CPG_CDDIV4		(0x410)
 #define CPG_CSDIV0		(0x500)
+#define CPG_CSDIV1		(0x504)
 
 #define CDDIV0_DIVCTL1	DDIV_PACK(CPG_CDDIV0, 4, 3, 1)
 #define CDDIV0_DIVCTL2	DDIV_PACK(CPG_CDDIV0, 8, 3, 2)
@@ -116,7 +118,9 @@ struct smuxed {
 
 #define CSDIV0_DIVCTL0	DDIV_PACK(CPG_CSDIV0, 0, 2, CSDIV_NO_MON)
 #define CSDIV0_DIVCTL1	DDIV_PACK(CPG_CSDIV0, 4, 2, CSDIV_NO_MON)
+#define CSDIV0_DIVCTL2	DDIV_PACK(CPG_CSDIV0, 8, 2, CSDIV_NO_MON)
 #define CSDIV0_DIVCTL3	DDIV_PACK_NO_RMW(CPG_CSDIV0, 12, 2, CSDIV_NO_MON)
+#define CSDIV1_DIVCTL2	DDIV_PACK(CPG_CSDIV1, 8, 4, CSDIV_NO_MON)
 
 #define SSEL0_SELCTL2	SMUX_PACK(CPG_SSEL0, 8, 1)
 #define SSEL0_SELCTL3	SMUX_PACK(CPG_SSEL0, 12, 1)
-- 
2.49.0


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

* [PATCH v6 3/4] dt-bindings: display: bridge: renesas,dsi: Add support for RZ/V2H(P) SoC
  2025-05-30 17:18 [PATCH v6 0/4] Add support for DU/DSI clocks and DSI driver support for the Renesas RZ/V2H(P) SoC Prabhakar
  2025-05-30 17:18 ` [PATCH v6 1/4] clk: renesas: rzv2h-cpg: Add support for DSI clocks Prabhakar
  2025-05-30 17:18 ` [PATCH v6 2/4] clk: renesas: r9a09g057: Add clock and reset entries for DSI and LCDC Prabhakar
@ 2025-05-30 17:18 ` Prabhakar
  2025-06-26  6:10   ` Biju Das
  2025-05-30 17:18 ` [PATCH v6 4/4] drm: renesas: rz-du: mipi_dsi: " Prabhakar
  3 siblings, 1 reply; 18+ messages in thread
From: Prabhakar @ 2025-05-30 17:18 UTC (permalink / raw)
  To: Geert Uytterhoeven, Andrzej Hajda, Neil Armstrong, Robert Foss,
	Laurent Pinchart, Jonas Karlman, Jernej Skrabec,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Michael Turquette, Stephen Boyd, Biju Das, Magnus Damm
  Cc: dri-devel, devicetree, linux-kernel, linux-renesas-soc, linux-clk,
	Prabhakar, Fabrizio Castro, Lad Prabhakar, Krzysztof Kozlowski

From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>

The MIPI DSI interface on the RZ/V2H(P) SoC is nearly identical to that of
the RZ/G2L SoC. While the LINK registers are the same for both SoCs, the
D-PHY registers differ. Additionally, the number of resets for DSI on
RZ/V2H(P) is two compared to three on the RZ/G2L.

To accommodate these differences, a SoC-specific
`renesas,r9a09g057-mipi-dsi` compatible string has been added for the
RZ/V2H(P) SoC.

Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
v5->v6:
- Preserved the sort order (by part number).
- Added reviewed tag from Geert.

v4->v5:
- No changes

v3->v4:
- No changes

v2->v3:
- Collected reviewed tag from Krzysztof

v1->v2:
- Kept the sort order for schema validation
- Added  `port@1: false` for RZ/V2H(P) SoC
---
 .../bindings/display/bridge/renesas,dsi.yaml  | 116 +++++++++++++-----
 1 file changed, 87 insertions(+), 29 deletions(-)

diff --git a/Documentation/devicetree/bindings/display/bridge/renesas,dsi.yaml b/Documentation/devicetree/bindings/display/bridge/renesas,dsi.yaml
index e08c24633926..8c7e2b17ba79 100644
--- a/Documentation/devicetree/bindings/display/bridge/renesas,dsi.yaml
+++ b/Documentation/devicetree/bindings/display/bridge/renesas,dsi.yaml
@@ -14,16 +14,17 @@ description: |
   RZ/G2L alike family of SoC's. The encoder can operate in DSI mode, with
   up to four data lanes.
 
-allOf:
-  - $ref: /schemas/display/dsi-controller.yaml#
-
 properties:
   compatible:
-    items:
+    oneOf:
+      - items:
+          - enum:
+              - renesas,r9a07g044-mipi-dsi # RZ/G2{L,LC}
+              - renesas,r9a07g054-mipi-dsi # RZ/V2L
+          - const: renesas,rzg2l-mipi-dsi
+
       - enum:
-          - renesas,r9a07g044-mipi-dsi # RZ/G2{L,LC}
-          - renesas,r9a07g054-mipi-dsi # RZ/V2L
-      - const: renesas,rzg2l-mipi-dsi
+          - renesas,r9a09g057-mipi-dsi # RZ/V2H(P)
 
   reg:
     maxItems: 1
@@ -49,34 +50,56 @@ properties:
       - const: debug
 
   clocks:
-    items:
-      - description: DSI D-PHY PLL multiplied clock
-      - description: DSI D-PHY system clock
-      - description: DSI AXI bus clock
-      - description: DSI Register access clock
-      - description: DSI Video clock
-      - description: DSI D-PHY Escape mode transmit clock
+    oneOf:
+      - items:
+          - description: DSI D-PHY PLL multiplied clock
+          - description: DSI D-PHY system clock
+          - description: DSI AXI bus clock
+          - description: DSI Register access clock
+          - description: DSI Video clock
+          - description: DSI D-PHY Escape mode transmit clock
+      - items:
+          - description: DSI D-PHY PLL multiplied clock
+          - description: DSI AXI bus clock
+          - description: DSI Register access clock
+          - description: DSI Video clock
+          - description: DSI D-PHY Escape mode transmit clock
 
   clock-names:
-    items:
-      - const: pllclk
-      - const: sysclk
-      - const: aclk
-      - const: pclk
-      - const: vclk
-      - const: lpclk
+    oneOf:
+      - items:
+          - const: pllclk
+          - const: sysclk
+          - const: aclk
+          - const: pclk
+          - const: vclk
+          - const: lpclk
+      - items:
+          - const: pllclk
+          - const: aclk
+          - const: pclk
+          - const: vclk
+          - const: lpclk
 
   resets:
-    items:
-      - description: MIPI_DSI_CMN_RSTB
-      - description: MIPI_DSI_ARESET_N
-      - description: MIPI_DSI_PRESET_N
+    oneOf:
+      - items:
+          - description: MIPI_DSI_CMN_RSTB
+          - description: MIPI_DSI_ARESET_N
+          - description: MIPI_DSI_PRESET_N
+      - items:
+          - description: MIPI_DSI_ARESET_N
+          - description: MIPI_DSI_PRESET_N
 
   reset-names:
-    items:
-      - const: rst
-      - const: arst
-      - const: prst
+    oneOf:
+      - items:
+          - const: rst
+          - const: arst
+          - const: prst
+      - items:
+          - const: arst
+          - const: prst
 
   power-domains:
     maxItems: 1
@@ -130,6 +153,41 @@ required:
 
 additionalProperties: false
 
+allOf:
+  - $ref: ../dsi-controller.yaml#
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: renesas,r9a09g057-mipi-dsi
+    then:
+      properties:
+        clocks:
+          maxItems: 5
+
+        clock-names:
+          maxItems: 5
+
+        resets:
+          maxItems: 2
+
+        reset-names:
+          maxItems: 2
+    else:
+      properties:
+        clocks:
+          minItems: 6
+
+        clock-names:
+          minItems: 6
+
+        resets:
+          minItems: 3
+
+        reset-names:
+          minItems: 3
+
 examples:
   - |
     #include <dt-bindings/clock/r9a07g044-cpg.h>
-- 
2.49.0


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

* [PATCH v6 4/4] drm: renesas: rz-du: mipi_dsi: Add support for RZ/V2H(P) SoC
  2025-05-30 17:18 [PATCH v6 0/4] Add support for DU/DSI clocks and DSI driver support for the Renesas RZ/V2H(P) SoC Prabhakar
                   ` (2 preceding siblings ...)
  2025-05-30 17:18 ` [PATCH v6 3/4] dt-bindings: display: bridge: renesas,dsi: Add support for RZ/V2H(P) SoC Prabhakar
@ 2025-05-30 17:18 ` Prabhakar
  2025-06-13  6:17   ` Biju Das
  3 siblings, 1 reply; 18+ messages in thread
From: Prabhakar @ 2025-05-30 17:18 UTC (permalink / raw)
  To: Geert Uytterhoeven, Andrzej Hajda, Neil Armstrong, Robert Foss,
	Laurent Pinchart, Jonas Karlman, Jernej Skrabec,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Michael Turquette, Stephen Boyd, Biju Das, Magnus Damm
  Cc: dri-devel, devicetree, linux-kernel, linux-renesas-soc, linux-clk,
	Prabhakar, Fabrizio Castro, Lad Prabhakar

From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>

Add DSI support for Renesas RZ/V2H(P) SoC.

Co-developed-by: Fabrizio Castro <fabrizio.castro.jz@renesas.com>
Signed-off-by: Fabrizio Castro <fabrizio.castro.jz@renesas.com>
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
v5->v6:
- Made use of GENMASK() macro for PLLCLKSET0R_PLL_*,
  PHYTCLKSETR_* and PHYTHSSETR_* macros.
- Replaced 10000000UL with 10 * MEGA
- Renamed mode_freq_hz to mode_freq_khz in rzv2h_dsi_mode_calc
- Replaced `i -= 1;` with `i--;`
- Renamed RZV2H_MIPI_DPHY_FOUT_MIN_IN_MEGA to
  RZV2H_MIPI_DPHY_FOUT_MIN_IN_MHZ and
  RZV2H_MIPI_DPHY_FOUT_MAX_IN_MEGA to
  RZV2H_MIPI_DPHY_FOUT_MAX_IN_MHZ.

v4->v5:
- No changes

v3->v4
- In rzv2h_dphy_find_ulpsexit() made the array static const.

v2->v3:
- Simplifed V2H DSI timings array to save space
- Switched to use fsleep() instead of udelay()

v1->v2:
- Dropped unused macros
- Added missing LPCLK flag to rzv2h info
---
 .../gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c    | 345 ++++++++++++++++++
 .../drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h   |  34 ++
 2 files changed, 379 insertions(+)

diff --git a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
index a31f9b6aa920..ea554ced6713 100644
--- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
+++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
@@ -5,6 +5,7 @@
  * Copyright (C) 2022 Renesas Electronics Corporation
  */
 #include <linux/clk.h>
+#include <linux/clk/renesas-rzv2h-dsi.h>
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/iopoll.h>
@@ -30,6 +31,9 @@
 
 #define RZ_MIPI_DSI_FEATURE_16BPP	BIT(0)
 
+#define RZV2H_MIPI_DPHY_FOUT_MIN_IN_MHZ	(80 * MEGA)
+#define RZV2H_MIPI_DPHY_FOUT_MAX_IN_MHZ	(1500 * MEGA)
+
 struct rzg2l_mipi_dsi;
 
 struct rzg2l_mipi_dsi_hw_info {
@@ -40,6 +44,7 @@ struct rzg2l_mipi_dsi_hw_info {
 			      u64 *hsfreq_millihz);
 	unsigned int (*dphy_mode_clk_check)(struct rzg2l_mipi_dsi *dsi,
 					    unsigned long mode_freq);
+	const struct rzv2h_pll_div_limits *cpg_dsi_limits;
 	u32 phy_reg_offset;
 	u32 link_reg_offset;
 	unsigned long min_dclk;
@@ -47,6 +52,11 @@ struct rzg2l_mipi_dsi_hw_info {
 	u8 features;
 };
 
+struct rzv2h_dsi_mode_calc {
+	unsigned long mode_freq_khz;
+	u64 mode_freq_hz;
+};
+
 struct rzg2l_mipi_dsi {
 	struct device *dev;
 	void __iomem *mmio;
@@ -68,6 +78,18 @@ struct rzg2l_mipi_dsi {
 	unsigned int num_data_lanes;
 	unsigned int lanes;
 	unsigned long mode_flags;
+
+	struct rzv2h_dsi_mode_calc mode_calc;
+	struct rzv2h_plldsi_parameters dsi_parameters;
+};
+
+static const struct rzv2h_pll_div_limits rzv2h_plldsi_div_limits = {
+	.fvco = { .min = 1050 * MEGA, .max = 2100 * MEGA },
+	.m = { .min = 64, .max = 1023 },
+	.p = { .min = 1, .max = 4 },
+	.s = { .min = 0, .max = 5 },
+	.k = { .min = -32768, .max = 32767 },
+	.csdiv = { .min = 1, .max = 1 },
 };
 
 static inline struct rzg2l_mipi_dsi *
@@ -184,6 +206,155 @@ static const struct rzg2l_mipi_dsi_timings rzg2l_mipi_dsi_global_timings[] = {
 	},
 };
 
+struct rzv2h_mipi_dsi_timings {
+	const u8 *hsfreq;
+	u8 len;
+	u8 start_index;
+};
+
+enum {
+	TCLKPRPRCTL,
+	TCLKZEROCTL,
+	TCLKPOSTCTL,
+	TCLKTRAILCTL,
+	THSPRPRCTL,
+	THSZEROCTL,
+	THSTRAILCTL,
+	TLPXCTL,
+	THSEXITCTL,
+};
+
+static const u8 tclkprprctl[] = {
+	15, 26, 37, 47, 58, 69, 79, 90, 101, 111, 122, 133, 143, 150,
+};
+
+static const u8 tclkzeroctl[] = {
+	9, 11, 13, 15, 18, 21, 23, 24, 25, 27, 29, 31, 34, 36, 38,
+	41, 43, 45, 47, 50, 52, 54, 57, 59, 61, 63, 66, 68, 70, 73,
+	75, 77, 79, 82, 84, 86, 89, 91, 93, 95, 98, 100, 102, 105,
+	107, 109, 111, 114, 116, 118, 121, 123, 125, 127, 130, 132,
+	134, 137, 139, 141, 143, 146, 148, 150,
+};
+
+static const u8 tclkpostctl[] = {
+	8, 21, 34, 48, 61, 74, 88, 101, 114, 128, 141, 150,
+};
+
+static const u8 tclktrailctl[] = {
+	14, 25, 37, 48, 59, 71, 82, 94, 105, 117, 128, 139, 150,
+};
+
+static const u8 thsprprctl[] = {
+	11, 19, 29, 40, 50, 61, 72, 82, 93, 103, 114, 125, 135, 146, 150,
+};
+
+static const u8 thszeroctl[] = {
+	18, 24, 29, 35, 40, 46, 51, 57, 62, 68, 73, 79, 84, 90,
+	95, 101, 106, 112, 117, 123, 128, 134, 139, 145, 150,
+};
+
+static const u8 thstrailctl[] = {
+	10, 21, 32, 42, 53, 64, 75, 85, 96, 107, 118, 128, 139, 150,
+};
+
+static const u8 tlpxctl[] = {
+	13, 26, 39, 53, 66, 79, 93, 106, 119, 133, 146,	150,
+};
+
+static const u8 thsexitctl[] = {
+	15, 23, 31, 39, 47, 55, 63, 71, 79, 87,
+	95, 103, 111, 119, 127, 135, 143, 150,
+};
+
+static const struct rzv2h_mipi_dsi_timings rzv2h_dsi_timings_tables[] = {
+	[TCLKPRPRCTL] = {
+		.hsfreq = tclkprprctl,
+		.len = ARRAY_SIZE(tclkprprctl),
+		.start_index = 0,
+	},
+	[TCLKZEROCTL] = {
+		.hsfreq = tclkzeroctl,
+		.len = ARRAY_SIZE(tclkzeroctl),
+		.start_index = 2,
+	},
+	[TCLKPOSTCTL] = {
+		.hsfreq = tclkpostctl,
+		.len = ARRAY_SIZE(tclkpostctl),
+		.start_index = 6,
+	},
+	[TCLKTRAILCTL] = {
+		.hsfreq = tclktrailctl,
+		.len = ARRAY_SIZE(tclktrailctl),
+		.start_index = 1,
+	},
+	[THSPRPRCTL] = {
+		.hsfreq = thsprprctl,
+		.len = ARRAY_SIZE(thsprprctl),
+		.start_index = 0,
+	},
+	[THSZEROCTL] = {
+		.hsfreq = thszeroctl,
+		.len = ARRAY_SIZE(thszeroctl),
+		.start_index = 0,
+	},
+	[THSTRAILCTL] = {
+		.hsfreq = thstrailctl,
+		.len = ARRAY_SIZE(thstrailctl),
+		.start_index = 3,
+	},
+	[TLPXCTL] = {
+		.hsfreq = tlpxctl,
+		.len = ARRAY_SIZE(tlpxctl),
+		.start_index = 0,
+	},
+	[THSEXITCTL] = {
+		.hsfreq = thsexitctl,
+		.len = ARRAY_SIZE(thsexitctl),
+		.start_index = 1,
+	},
+};
+
+static u16 rzv2h_dphy_find_ulpsexit(unsigned long freq)
+{
+	static const unsigned long hsfreq[] = {
+		1953125UL,
+		3906250UL,
+		7812500UL,
+		15625000UL,
+	};
+	static const u16 ulpsexit[] = {49, 98, 195, 391};
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(hsfreq); i++) {
+		if (freq <= hsfreq[i])
+			break;
+	}
+
+	if (i == ARRAY_SIZE(hsfreq))
+		i--;
+
+	return ulpsexit[i];
+}
+
+static u16 rzv2h_dphy_find_timings_val(unsigned long freq, u8 index)
+{
+	const struct rzv2h_mipi_dsi_timings *timings;
+	u16 i;
+
+	timings = &rzv2h_dsi_timings_tables[index];
+	for (i = 0; i < timings->len; i++) {
+		unsigned long hsfreq = timings->hsfreq[i] * 10 * MEGA;
+
+		if (freq <= hsfreq)
+			break;
+	}
+
+	if (i == timings->len)
+		i--;
+
+	return timings->start_index + i;
+};
+
 static void rzg2l_mipi_dsi_phy_write(struct rzg2l_mipi_dsi *dsi, u32 reg, u32 data)
 {
 	iowrite32(data, dsi->mmio + dsi->info->phy_reg_offset + reg);
@@ -308,6 +479,160 @@ static int rzg2l_dphy_conf_clks(struct rzg2l_mipi_dsi *dsi, unsigned long mode_f
 	return 0;
 }
 
+static unsigned int rzv2h_dphy_mode_clk_check(struct rzg2l_mipi_dsi *dsi,
+					      unsigned long mode_freq)
+{
+	struct rzv2h_plldsi_parameters cpg_dsi_parameters;
+	struct rzv2h_plldsi_parameters dsi_parameters;
+	u64 hsfreq_millihz, mode_freq_hz, mode_freq_millihz;
+	unsigned int bpp, i;
+
+	bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
+
+	for (i = 0; i < 10; i += 1) {
+		unsigned long hsfreq;
+		bool parameters_found;
+
+		mode_freq_hz = mul_u32_u32(mode_freq, KILO) + i;
+		mode_freq_millihz = mode_freq_hz * MILLI;
+		parameters_found = rzv2h_dsi_get_pll_parameters_values(dsi->info->cpg_dsi_limits,
+								       &cpg_dsi_parameters,
+								       mode_freq_millihz);
+		if (!parameters_found)
+			continue;
+
+		hsfreq_millihz = DIV_ROUND_CLOSEST_ULL(cpg_dsi_parameters.freq_millihz * bpp,
+						       dsi->lanes);
+		parameters_found = rzv2h_dsi_get_pll_parameters_values(&rzv2h_plldsi_div_limits,
+								       &dsi_parameters,
+								       hsfreq_millihz);
+		if (!parameters_found)
+			continue;
+
+		if (abs(dsi_parameters.error_millihz) >= 500)
+			continue;
+
+		hsfreq = DIV_ROUND_CLOSEST_ULL(hsfreq_millihz, MILLI);
+		if (hsfreq >= RZV2H_MIPI_DPHY_FOUT_MIN_IN_MHZ &&
+		    hsfreq <= RZV2H_MIPI_DPHY_FOUT_MAX_IN_MHZ) {
+			memcpy(&dsi->dsi_parameters, &dsi_parameters, sizeof(dsi->dsi_parameters));
+			dsi->mode_calc.mode_freq_khz = mode_freq;
+			dsi->mode_calc.mode_freq_hz = mode_freq_hz;
+			return MODE_OK;
+		}
+	}
+
+	return MODE_CLOCK_RANGE;
+}
+
+static int rzv2h_dphy_conf_clks(struct rzg2l_mipi_dsi *dsi, unsigned long mode_freq,
+				u64 *hsfreq_millihz)
+{
+	struct rzv2h_plldsi_parameters *dsi_parameters = &dsi->dsi_parameters;
+	unsigned long status;
+
+	if (dsi->mode_calc.mode_freq_khz != mode_freq) {
+		status = rzv2h_dphy_mode_clk_check(dsi, mode_freq);
+		if (status != MODE_OK) {
+			dev_err(dsi->dev, "No PLL parameters found for mode clk %lu\n",
+				mode_freq);
+			return -EINVAL;
+		}
+	}
+
+	clk_set_rate(dsi->vclk, dsi->mode_calc.mode_freq_hz);
+	*hsfreq_millihz = dsi_parameters->freq_millihz;
+
+	return 0;
+}
+
+static int rzv2h_mipi_dsi_dphy_init(struct rzg2l_mipi_dsi *dsi,
+				    u64 hsfreq_millihz)
+{
+	struct rzv2h_plldsi_parameters *dsi_parameters = &dsi->dsi_parameters;
+	unsigned long lpclk_rate = clk_get_rate(dsi->lpclk);
+	u32 phytclksetr, phythssetr, phytlpxsetr, phycr;
+	struct rzg2l_mipi_dsi_timings dphy_timings;
+	u16 ulpsexit;
+	u64 hsfreq;
+
+	hsfreq = DIV_ROUND_CLOSEST_ULL(hsfreq_millihz, MILLI);
+
+	if (dsi_parameters->freq_millihz == hsfreq_millihz)
+		goto parameters_found;
+
+	if (rzv2h_dsi_get_pll_parameters_values(&rzv2h_plldsi_div_limits,
+						dsi_parameters, hsfreq_millihz))
+		goto parameters_found;
+
+	dev_err(dsi->dev, "No PLL parameters found for HSFREQ %lluHz\n", hsfreq);
+	return -EINVAL;
+
+parameters_found:
+	dphy_timings.tclk_trail =
+		rzv2h_dphy_find_timings_val(hsfreq, TCLKTRAILCTL);
+	dphy_timings.tclk_post =
+		rzv2h_dphy_find_timings_val(hsfreq, TCLKPOSTCTL);
+	dphy_timings.tclk_zero =
+		rzv2h_dphy_find_timings_val(hsfreq, TCLKZEROCTL);
+	dphy_timings.tclk_prepare =
+		rzv2h_dphy_find_timings_val(hsfreq, TCLKPRPRCTL);
+	dphy_timings.ths_exit =
+		rzv2h_dphy_find_timings_val(hsfreq, THSEXITCTL);
+	dphy_timings.ths_trail =
+		rzv2h_dphy_find_timings_val(hsfreq, THSTRAILCTL);
+	dphy_timings.ths_zero =
+		rzv2h_dphy_find_timings_val(hsfreq, THSZEROCTL);
+	dphy_timings.ths_prepare =
+		rzv2h_dphy_find_timings_val(hsfreq, THSPRPRCTL);
+	dphy_timings.tlpx =
+		rzv2h_dphy_find_timings_val(hsfreq, TLPXCTL);
+	ulpsexit = rzv2h_dphy_find_ulpsexit(lpclk_rate);
+
+	phytclksetr = FIELD_PREP(PHYTCLKSETR_TCLKTRAILCTL, dphy_timings.tclk_trail) |
+		      FIELD_PREP(PHYTCLKSETR_TCLKPOSTCTL, dphy_timings.tclk_post) |
+		      FIELD_PREP(PHYTCLKSETR_TCLKZEROCTL, dphy_timings.tclk_zero) |
+		      FIELD_PREP(PHYTCLKSETR_TCLKPRPRCTL, dphy_timings.tclk_prepare);
+	phythssetr = FIELD_PREP(PHYTHSSETR_THSEXITCTL, dphy_timings.ths_exit) |
+		     FIELD_PREP(PHYTHSSETR_THSTRAILCTL, dphy_timings.ths_trail) |
+		     FIELD_PREP(PHYTHSSETR_THSZEROCTL, dphy_timings.ths_zero) |
+		     FIELD_PREP(PHYTHSSETR_THSPRPRCTL, dphy_timings.ths_prepare);
+	phytlpxsetr = rzg2l_mipi_dsi_phy_read(dsi, PHYTLPXSETR) & ~PHYTLPXSETR_TLPXCTL;
+	phytlpxsetr |= FIELD_PREP(PHYTLPXSETR_TLPXCTL, dphy_timings.tlpx);
+	phycr = rzg2l_mipi_dsi_phy_read(dsi, PHYCR) & ~GENMASK(9, 0);
+	phycr |= FIELD_PREP(PHYCR_ULPSEXIT, ulpsexit);
+
+	/* Setting all D-PHY Timings Registers */
+	rzg2l_mipi_dsi_phy_write(dsi, PHYTCLKSETR, phytclksetr);
+	rzg2l_mipi_dsi_phy_write(dsi, PHYTHSSETR, phythssetr);
+	rzg2l_mipi_dsi_phy_write(dsi, PHYTLPXSETR, phytlpxsetr);
+	rzg2l_mipi_dsi_phy_write(dsi, PHYCR, phycr);
+
+	rzg2l_mipi_dsi_phy_write(dsi, PLLCLKSET0R,
+				 FIELD_PREP(PLLCLKSET0R_PLL_S, dsi_parameters->s) |
+				 FIELD_PREP(PLLCLKSET0R_PLL_P, dsi_parameters->p) |
+				 FIELD_PREP(PLLCLKSET0R_PLL_M, dsi_parameters->m));
+	rzg2l_mipi_dsi_phy_write(dsi, PLLCLKSET1R,
+				 FIELD_PREP(PLLCLKSET1R_PLL_K, dsi_parameters->k));
+	fsleep(20);
+
+	rzg2l_mipi_dsi_phy_write(dsi, PLLENR, PLLENR_PLLEN);
+	fsleep(500);
+
+	return 0;
+}
+
+static void rzv2h_mipi_dsi_dphy_startup_late_init(struct rzg2l_mipi_dsi *dsi)
+{
+	fsleep(220);
+	rzg2l_mipi_dsi_phy_write(dsi, PHYRSTR, PHYRSTR_PHYMRSTN);
+}
+
+static void rzv2h_mipi_dsi_dphy_exit(struct rzg2l_mipi_dsi *dsi)
+{
+	rzg2l_mipi_dsi_phy_write(dsi, PLLENR, 0);
+}
+
 static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi,
 				  const struct drm_display_mode *mode)
 {
@@ -410,6 +735,9 @@ static void rzg2l_mipi_dsi_set_display_timing(struct rzg2l_mipi_dsi *dsi,
 	case 18:
 		vich1ppsetr = VICH1PPSETR_DT_RGB18;
 		break;
+	case 16:
+		vich1ppsetr = VICH1PPSETR_DT_RGB16;
+		break;
 	}
 
 	if ((dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) &&
@@ -862,6 +1190,22 @@ static void rzg2l_mipi_dsi_remove(struct platform_device *pdev)
 	pm_runtime_disable(&pdev->dev);
 }
 
+RZV2H_CPG_PLL_DSI_LIMITS(rzv2h_cpg_pll_dsi_limits);
+
+static const struct rzg2l_mipi_dsi_hw_info rzv2h_mipi_dsi_info = {
+	.dphy_init = rzv2h_mipi_dsi_dphy_init,
+	.dphy_startup_late_init = rzv2h_mipi_dsi_dphy_startup_late_init,
+	.dphy_exit = rzv2h_mipi_dsi_dphy_exit,
+	.dphy_mode_clk_check = rzv2h_dphy_mode_clk_check,
+	.dphy_conf_clks = rzv2h_dphy_conf_clks,
+	.cpg_dsi_limits = &rzv2h_cpg_pll_dsi_limits,
+	.phy_reg_offset = 0x10000,
+	.link_reg_offset = 0,
+	.min_dclk = 5440,
+	.max_dclk = 187500,
+	.features = RZ_MIPI_DSI_FEATURE_16BPP,
+};
+
 static const struct rzg2l_mipi_dsi_hw_info rzg2l_mipi_dsi_info = {
 	.dphy_init = rzg2l_mipi_dsi_dphy_init,
 	.dphy_exit = rzg2l_mipi_dsi_dphy_exit,
@@ -872,6 +1216,7 @@ static const struct rzg2l_mipi_dsi_hw_info rzg2l_mipi_dsi_info = {
 };
 
 static const struct of_device_id rzg2l_mipi_dsi_of_table[] = {
+	{ .compatible = "renesas,r9a09g057-mipi-dsi", .data = &rzv2h_mipi_dsi_info, },
 	{ .compatible = "renesas,rzg2l-mipi-dsi", .data = &rzg2l_mipi_dsi_info, },
 	{ /* sentinel */ }
 };
diff --git a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h
index 16efe4dc59f4..87963871cacd 100644
--- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h
+++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h
@@ -40,6 +40,39 @@
 #define DSIDPHYTIM3_THS_TRAIL(x)	((x) << 8)
 #define DSIDPHYTIM3_THS_ZERO(x)		((x) << 0)
 
+/* RZ/V2H DPHY Registers */
+#define PLLENR				0x000
+#define PLLENR_PLLEN			BIT(0)
+
+#define PHYRSTR				0x004
+#define PHYRSTR_PHYMRSTN		BIT(0)
+
+#define PLLCLKSET0R			0x010
+#define PLLCLKSET0R_PLL_S		GENMASK(2, 0)
+#define PLLCLKSET0R_PLL_P		GENMASK(13, 8)
+#define PLLCLKSET0R_PLL_M		GENMASK(25, 16)
+
+#define PLLCLKSET1R			0x014
+#define PLLCLKSET1R_PLL_K		GENMASK(15, 0)
+
+#define PHYTCLKSETR			0x020
+#define PHYTCLKSETR_TCLKTRAILCTL        GENMASK(7, 0)
+#define PHYTCLKSETR_TCLKPOSTCTL         GENMASK(15, 8)
+#define PHYTCLKSETR_TCLKZEROCTL         GENMASK(23, 16)
+#define PHYTCLKSETR_TCLKPRPRCTL         GENMASK(31, 24)
+
+#define PHYTHSSETR			0x024
+#define PHYTHSSETR_THSEXITCTL           GENMASK(7, 0)
+#define PHYTHSSETR_THSTRAILCTL          GENMASK(15, 8)
+#define PHYTHSSETR_THSZEROCTL           GENMASK(23, 16)
+#define PHYTHSSETR_THSPRPRCTL           GENMASK(31, 24)
+
+#define PHYTLPXSETR			0x028
+#define PHYTLPXSETR_TLPXCTL             GENMASK(7, 0)
+
+#define PHYCR				0x030
+#define PHYCR_ULPSEXIT                  GENMASK(9, 0)
+
 /* --------------------------------------------------------*/
 
 /* Link Status Register */
@@ -116,6 +149,7 @@
 
 /* Video-Input Channel 1 Pixel Packet Set Register */
 #define VICH1PPSETR			0x420
+#define VICH1PPSETR_DT_RGB16		(0x0e << 16)
 #define VICH1PPSETR_DT_RGB18		(0x1e << 16)
 #define VICH1PPSETR_DT_RGB18_LS		(0x2e << 16)
 #define VICH1PPSETR_DT_RGB24		(0x3e << 16)
-- 
2.49.0


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

* RE: [PATCH v6 1/4] clk: renesas: rzv2h-cpg: Add support for DSI clocks
  2025-05-30 17:18 ` [PATCH v6 1/4] clk: renesas: rzv2h-cpg: Add support for DSI clocks Prabhakar
@ 2025-06-13  5:57   ` Biju Das
  2025-06-16 10:44     ` Lad, Prabhakar
  0 siblings, 1 reply; 18+ messages in thread
From: Biju Das @ 2025-06-13  5:57 UTC (permalink / raw)
  To: Prabhakar, Geert Uytterhoeven, Andrzej Hajda, Neil Armstrong,
	Robert Foss, laurent.pinchart, Jonas Karlman, Jernej Skrabec,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Michael Turquette, Stephen Boyd, Magnus Damm
  Cc: dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-renesas-soc@vger.kernel.org,
	linux-clk@vger.kernel.org, Fabrizio Castro, Prabhakar Mahadev Lad

Hi Prabhakar,

> -----Original Message-----
> From: Prabhakar <prabhakar.csengg@gmail.com>
> Sent: 30 May 2025 18:19
.castro.jz@renesas.com>; Prabhakar Mahadev Lad <prabhakar.mahadev-
> lad.rj@bp.renesas.com>
> Subject: [PATCH v6 1/4] clk: renesas: rzv2h-cpg: Add support for DSI clocks
> 
> From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> 
> Add support for PLLDSI and PLLDSI divider clocks.
> 
> Introduce the `renesas-rzv2h-dsi.h` header to centralize and share PLLDSI-related data structures,
> limits, and algorithms between the RZ/V2H CPG and DSI drivers.
> 
> The DSI PLL is functionally similar to the CPG's PLLDSI, but has slightly different parameter limits
> and omits the programmable divider present in CPG. To ensure precise frequency calculations-especially
> for milliHz-level accuracy needed by the DSI driver-the shared algorithm allows both drivers to
> compute PLL parameters consistently using the same logic and input clock.
> 
> Co-developed-by: Fabrizio Castro <fabrizio.castro.jz@renesas.com>
> Signed-off-by: Fabrizio Castro <fabrizio.castro.jz@renesas.com>
> Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> ---
> v5->v6:
> - Renamed CPG_PLL_STBY_SSCGEN_WEN to CPG_PLL_STBY_SSC_EN_WEN
> - Updated CPG_PLL_CLK1_DIV_K, CPG_PLL_CLK1_DIV_M, and
>   CPG_PLL_CLK1_DIV_P macros to use GENMASK
> - Updated req->rate in rzv2h_cpg_plldsi_div_determine_rate()
> - Dropped the cast in rzv2h_cpg_plldsi_div_set_rate()
> - Dropped rzv2h_cpg_plldsi_round_rate() and implemented
>   rzv2h_cpg_plldsi_determine_rate() instead
> - Made use of FIELD_PREP()
> - Moved CPG_CSDIV1 macro in patch 2/4
> - Dropped two_pow_s in rzv2h_dsi_get_pll_parameters_values()
> - Used mul_u32_u32() while calculating output_m and output_k_range
> - Used div_s64() instead of div64_s64() while calculating
>   pll_k
> - Used mul_u32_u32() while calculating fvco and fvco checks
> - Rounded the final output using DIV_U64_ROUND_CLOSEST()
> 
> v4->v5:
> - No changes
> 
> v3->v4:
> - Corrected parameter name in rzv2h_dsi_get_pll_parameters_values()
>   description freq_millihz
> 
> v2->v3:
> - Update the commit message to clarify the purpose of `renesas-rzv2h-dsi.h`
>   header
> - Used mul_u32_u32() in rzv2h_cpg_plldsi_div_determine_rate()
> - Replaced *_mhz to *_millihz for clarity
> - Updated u64->u32 for fvco limits
> - Initialized the members in declaration order for
>   RZV2H_CPG_PLL_DSI_LIMITS() macro
> - Used clk_div_mask() in rzv2h_cpg_plldsi_div_recalc_rate()
> - Replaced `unsigned long long` with u64
> - Dropped rzv2h_cpg_plldsi_clk_recalc_rate() and reused
>   rzv2h_cpg_pll_clk_recalc_rate() instead
> - In rzv2h_cpg_plldsi_div_set_rate() followed the same style
>   of RMW-operation as done in the other functions
> - Renamed rzv2h_cpg_plldsi_set_rate() to rzv2h_cpg_pll_set_rate()
> - Dropped rzv2h_cpg_plldsi_clk_register() and reused
>   rzv2h_cpg_pll_clk_register() instead
> - Added a gaurd in renesas-rzv2h-dsi.h header
> 
> v1->v2:
> - No changes
> ---
>  drivers/clk/renesas/rzv2h-cpg.c       | 278 +++++++++++++++++++++++++-
>  drivers/clk/renesas/rzv2h-cpg.h       |  13 ++
>  include/linux/clk/renesas-rzv2h-dsi.h | 210 +++++++++++++++++++
>  3 files changed, 492 insertions(+), 9 deletions(-)  create mode 100644 include/linux/clk/renesas-
> rzv2h-dsi.h
> 
> diff --git a/drivers/clk/renesas/rzv2h-cpg.c b/drivers/clk/renesas/rzv2h-cpg.c index
> 761da3bf77ce..d590f9f47371 100644
> --- a/drivers/clk/renesas/rzv2h-cpg.c
> +++ b/drivers/clk/renesas/rzv2h-cpg.c
> @@ -14,9 +14,13 @@
>  #include <linux/bitfield.h>
>  #include <linux/clk.h>
>  #include <linux/clk-provider.h>
> +#include <linux/clk/renesas-rzv2h-dsi.h>
>  #include <linux/delay.h>
>  #include <linux/init.h>
>  #include <linux/iopoll.h>
> +#include <linux/math.h>
> +#include <linux/math64.h>
> +#include <linux/minmax.h>
>  #include <linux/mod_devicetable.h>
>  #include <linux/module.h>
>  #include <linux/of.h>
> @@ -26,6 +30,7 @@
>  #include <linux/refcount.h>
>  #include <linux/reset-controller.h>
>  #include <linux/string_choices.h>
> +#include <linux/units.h>
> 
>  #include <dt-bindings/clock/renesas-cpg-mssr.h>
> 
> @@ -48,12 +53,13 @@
>  #define CPG_PLL_STBY(x)		((x))
>  #define CPG_PLL_STBY_RESETB	BIT(0)
>  #define CPG_PLL_STBY_RESETB_WEN	BIT(16)
> +#define CPG_PLL_STBY_SSC_EN_WEN BIT(18)
>  #define CPG_PLL_CLK1(x)		((x) + 0x004)
> -#define CPG_PLL_CLK1_KDIV(x)	((s16)FIELD_GET(GENMASK(31, 16), (x)))
> -#define CPG_PLL_CLK1_MDIV(x)	FIELD_GET(GENMASK(15, 6), (x))
> -#define CPG_PLL_CLK1_PDIV(x)	FIELD_GET(GENMASK(5, 0), (x))
> +#define CPG_PLL_CLK1_KDIV	GENMASK(31, 16)
> +#define CPG_PLL_CLK1_MDIV	GENMASK(15, 6)
> +#define CPG_PLL_CLK1_PDIV	GENMASK(5, 0)
>  #define CPG_PLL_CLK2(x)		((x) + 0x008)
> -#define CPG_PLL_CLK2_SDIV(x)	FIELD_GET(GENMASK(2, 0), (x))
> +#define CPG_PLL_CLK2_SDIV	GENMASK(2, 0)
>  #define CPG_PLL_MON(x)		((x) + 0x010)
>  #define CPG_PLL_MON_RESETB	BIT(0)
>  #define CPG_PLL_MON_LOCK	BIT(4)
> @@ -79,6 +85,8 @@
>   * @last_dt_core_clk: ID of the last Core Clock exported to DT
>   * @mstop_count: Array of mstop values
>   * @rcdev: Reset controller entity
> + * @dsi_limits: PLL DSI parameters limits
> + * @plldsi_div_parameters: PLL DSI and divider parameters configuration
>   */
>  struct rzv2h_cpg_priv {
>  	struct device *dev;
> @@ -95,6 +103,9 @@ struct rzv2h_cpg_priv {
>  	atomic_t *mstop_count;
> 
>  	struct reset_controller_dev rcdev;
> +
> +	const struct rzv2h_pll_div_limits *dsi_limits;
> +	struct rzv2h_plldsi_parameters plldsi_div_parameters;
>  };
> 
>  #define rcdev_to_priv(x)	container_of(x, struct rzv2h_cpg_priv, rcdev)
> @@ -150,6 +161,24 @@ struct ddiv_clk {
> 
>  #define to_ddiv_clock(_div) container_of(_div, struct ddiv_clk, div)
> 
> +/**
> + * struct rzv2h_plldsi_div_clk - PLL DSI DDIV clock
> + *
> + * @dtable: divider table
> + * @priv: CPG private data
> + * @hw: divider clk
> + * @ddiv: divider configuration
> + */
> +struct rzv2h_plldsi_div_clk {
> +	const struct clk_div_table *dtable;
> +	struct rzv2h_cpg_priv *priv;
> +	struct clk_hw hw;
> +	struct ddiv ddiv;
> +};
> +
> +#define to_plldsi_div_clk(_hw) \
> +	container_of(_hw, struct rzv2h_plldsi_div_clk, hw)
> +
>  static int rzv2h_cpg_pll_clk_is_enabled(struct clk_hw *hw)  {
>  	struct pll_clk *pll_clk = to_pll(hw);
> @@ -198,6 +227,214 @@ static int rzv2h_cpg_pll_clk_enable(struct clk_hw *hw)
>  	return ret;
>  }
> 
> +static unsigned long rzv2h_cpg_plldsi_div_recalc_rate(struct clk_hw *hw,
> +						      unsigned long parent_rate)
> +{
> +	struct rzv2h_plldsi_div_clk *dsi_div = to_plldsi_div_clk(hw);
> +	struct rzv2h_cpg_priv *priv = dsi_div->priv;
> +	struct ddiv ddiv = dsi_div->ddiv;
> +	u32 div;
> +
> +	div = readl(priv->base + ddiv.offset);
> +	div >>= ddiv.shift;
> +	div &= clk_div_mask(ddiv.width);
> +	div = dsi_div->dtable[div].div;
> +
> +	return DIV_ROUND_CLOSEST_ULL(parent_rate, div); }
> +
> +static int rzv2h_cpg_plldsi_div_determine_rate(struct clk_hw *hw,
> +					       struct clk_rate_request *req) {
> +	struct rzv2h_plldsi_div_clk *dsi_div = to_plldsi_div_clk(hw);
> +	struct rzv2h_cpg_priv *priv = dsi_div->priv;
> +	struct rzv2h_plldsi_parameters *dsi_dividers = &priv->plldsi_div_parameters;
> +	u64 rate_millihz;
> +
> +	/*
> +	 * Adjust the requested clock rate (`req->rate`) to ensure it falls within
> +	 * the supported range of 5.44 MHz to 187.5 MHz.
> +	 */
> +	req->rate = clamp(req->rate, 5440000UL, 187500000UL);
> +
> +	rate_millihz = mul_u32_u32(req->rate, MILLI);
> +	if (rate_millihz == dsi_dividers->error_millihz + dsi_dividers->freq_millihz)
> +		goto exit_determine_rate;
> +
> +	if (!rzv2h_dsi_get_pll_parameters_values(priv->dsi_limits,
> +						 dsi_dividers, rate_millihz)) {
> +		dev_err(priv->dev,
> +			"failed to determine rate for req->rate: %lu\n",
> +			req->rate);
> +		return -EINVAL;
> +	}


> +
> +exit_determine_rate:
> +	req->best_parent_rate = req->rate * dsi_dividers->csdiv;

I believe this has to go after below assignment.

As parent_rate = rate * calculated DSI divider value.

req->rate = DIV_ROUND_CLOSEST_ULL(dsi_dividers->freq_millihz, MILLI);
req->best_parent_rate = req->rate * dsi_dividers->csdiv;



> +	req->rate = DIV_ROUND_CLOSEST_ULL(dsi_dividers->freq_millihz, MILLI);
> +
> +	return 0;
> +};
> +
> +static int rzv2h_cpg_plldsi_div_set_rate(struct clk_hw *hw,
> +					 unsigned long rate,
> +					 unsigned long parent_rate)
> +{
> +	struct rzv2h_plldsi_div_clk *dsi_div = to_plldsi_div_clk(hw);
> +	struct rzv2h_cpg_priv *priv = dsi_div->priv;
> +	struct rzv2h_plldsi_parameters *dsi_dividers = &priv->plldsi_div_parameters;
> +	struct ddiv ddiv = dsi_div->ddiv;
> +	const struct clk_div_table *clkt;
> +	bool div_found = false;
> +	u32 val, shift, div;
> +
> +	div = dsi_dividers->csdiv;
> +	for (clkt = dsi_div->dtable; clkt->div; clkt++) {
> +		if (clkt->div == div) {
> +			div_found = true;
> +			break;
> +		}
> +	}
> +
> +	if (!div_found)
> +		return -EINVAL;

This check can be done in determine rate and cache the divider??

> +
> +	shift = ddiv.shift;
> +	val = readl(priv->base + ddiv.offset) | DDIV_DIVCTL_WEN(shift);
> +	val &= ~(clk_div_mask(ddiv.width) << shift);
> +	val |= clkt->val << shift;
> +	writel(val, priv->base + ddiv.offset);
> +
> +	return 0;
> +};
> +
> +static const struct clk_ops rzv2h_cpg_plldsi_div_ops = {
> +	.recalc_rate = rzv2h_cpg_plldsi_div_recalc_rate,
> +	.determine_rate = rzv2h_cpg_plldsi_div_determine_rate,
> +	.set_rate = rzv2h_cpg_plldsi_div_set_rate, };
> +
> +static struct clk * __init
> +rzv2h_cpg_plldsi_div_clk_register(const struct cpg_core_clk *core,
> +				  struct rzv2h_cpg_priv *priv)
> +{
> +	struct rzv2h_plldsi_div_clk *clk_hw_data;
> +	struct clk **clks = priv->clks;
> +	struct clk_init_data init;
> +	const struct clk *parent;
> +	const char *parent_name;
> +	struct clk_hw *clk_hw;
> +	int ret;
> +
> +	parent = clks[core->parent];
> +	if (IS_ERR(parent))
> +		return ERR_CAST(parent);
> +
> +	clk_hw_data = devm_kzalloc(priv->dev, sizeof(*clk_hw_data), GFP_KERNEL);
> +	if (!clk_hw_data)
> +		return ERR_PTR(-ENOMEM);
> +
> +	clk_hw_data->priv = priv;
> +	clk_hw_data->ddiv = core->cfg.ddiv;
> +	clk_hw_data->dtable = core->dtable;
> +
> +	parent_name = __clk_get_name(parent);
> +	init.name = core->name;
> +	init.ops = &rzv2h_cpg_plldsi_div_ops;
> +	init.flags = core->flag;
> +	init.parent_names = &parent_name;
> +	init.num_parents = 1;
> +
> +	clk_hw = &clk_hw_data->hw;
> +	clk_hw->init = &init;
> +
> +	ret = devm_clk_hw_register(priv->dev, clk_hw);
> +	if (ret)
> +		return ERR_PTR(ret);
> +
> +	return clk_hw->clk;
> +}
> +
> +static int rzv2h_cpg_plldsi_determine_rate(struct clk_hw *hw,
> +					   struct clk_rate_request *req)
> +{
> +	struct rzv2h_pll_div_limits dsi_limits;
> +	struct rzv2h_plldsi_parameters dsi_dividers;
> +	struct pll_clk *pll_clk = to_pll(hw);
> +	struct rzv2h_cpg_priv *priv = pll_clk->priv;
> +	u64 rate_millihz;
> +
> +	memcpy(&dsi_limits, priv->dsi_limits, sizeof(dsi_limits));
> +	dsi_limits.csdiv.min = 1;
> +	dsi_limits.csdiv.max = 1;
> +
> +	req->rate = clamp(req->rate, 25000000UL, 375000000UL);

I guess this clamping is not required as the child already has clamping
and max DSI divider is fixed.

rate(Max) = 187500 * 1000 * divider = 187.5 MHz(clamped value) * dsi divider

> +
> +	rate_millihz = mul_u32_u32(req->rate, MILLI);
> +	if (!rzv2h_dsi_get_pll_parameters_values(priv->dsi_limits,
> +						 &dsi_dividers, rate_millihz)) {
> +		dev_err(priv->dev,
> +			"failed to determine rate for req->rate: %lu\n",
> +			req->rate);
> +		return -EINVAL;
> +	}
> +
> +	req->best_parent_rate = req->rate * dsi_dividers.csdiv;

This is wrong as it will lead to high value for  parent as the rate is fixed 24MHz.

24MHz-> PLL_DSI(This clock) -> DSI DIVIDER-> DoT clock


Cheers,
Biju

> +	req->rate = DIV_ROUND_CLOSEST_ULL(dsi_dividers.freq_millihz, MILLI);
> +
> +	return 0;
> +}
> +
> +static int rzv2h_cpg_pll_set_rate(struct clk_hw *hw,
> +				  unsigned long rate,
> +				  unsigned long parent_rate)
> +{
> +	struct pll_clk *pll_clk = to_pll(hw);
> +	struct rzv2h_cpg_priv *priv = pll_clk->priv;
> +	struct rzv2h_plldsi_parameters *dsi_dividers;
> +	struct pll pll = pll_clk->pll;
> +	u16 offset = pll.offset;
> +	u32 val;
> +	int ret;
> +
> +	/* Put PLL into standby mode */
> +	writel(CPG_PLL_STBY_RESETB_WEN, priv->base + CPG_PLL_STBY(offset));
> +	ret = readl_poll_timeout_atomic(priv->base + CPG_PLL_MON(offset),
> +					val, !(val & CPG_PLL_MON_LOCK),
> +					100, 2000);
> +	if (ret) {
> +		dev_err(priv->dev, "Failed to put PLLDSI into standby mode");
> +		return ret;
> +	}
> +
> +	dsi_dividers = &priv->plldsi_div_parameters;
> +	/* Output clock setting 1 */
> +	writel(FIELD_PREP(CPG_PLL_CLK1_KDIV, (u16)dsi_dividers->k) |
> +	       FIELD_PREP(CPG_PLL_CLK1_MDIV, dsi_dividers->m) |
> +	       FIELD_PREP(CPG_PLL_CLK1_PDIV, dsi_dividers->p),
> +	       priv->base + CPG_PLL_CLK1(offset));
> +
> +	/* Output clock setting 2 */
> +	val = readl(priv->base + CPG_PLL_CLK2(offset));
> +	writel((val & ~CPG_PLL_CLK2_SDIV) | FIELD_PREP(CPG_PLL_CLK2_SDIV, dsi_dividers->s),
> +	       priv->base + CPG_PLL_CLK2(offset));
> +
> +	/* Put PLL to normal mode */
> +	writel(CPG_PLL_STBY_RESETB_WEN | CPG_PLL_STBY_RESETB,
> +	       priv->base + CPG_PLL_STBY(offset));
> +
> +	/* PLL normal mode transition, output clock stability check */
> +	ret = readl_poll_timeout_atomic(priv->base + CPG_PLL_MON(offset),
> +					val, (val & CPG_PLL_MON_LOCK),
> +					100, 2000);
> +	if (ret) {
> +		dev_err(priv->dev, "Failed to put PLLDSI into normal mode");
> +		return ret;
> +	}
> +
> +	return 0;
> +};
> +
>  static unsigned long rzv2h_cpg_pll_clk_recalc_rate(struct clk_hw *hw,
>  						   unsigned long parent_rate)
>  {
> @@ -213,12 +450,19 @@ static unsigned long rzv2h_cpg_pll_clk_recalc_rate(struct clk_hw *hw,
>  	clk1 = readl(priv->base + CPG_PLL_CLK1(pll.offset));
>  	clk2 = readl(priv->base + CPG_PLL_CLK2(pll.offset));
> 
> -	rate = mul_u64_u32_shr(parent_rate, (CPG_PLL_CLK1_MDIV(clk1) << 16) +
> -			       CPG_PLL_CLK1_KDIV(clk1), 16 + CPG_PLL_CLK2_SDIV(clk2));
> +	rate = mul_u64_u32_shr(parent_rate, (FIELD_GET(CPG_PLL_CLK1_MDIV, clk1) << 16) +
> +			       (s16)FIELD_GET(CPG_PLL_CLK1_KDIV, clk1),
> +			       16 + FIELD_GET(CPG_PLL_CLK2_SDIV, clk2));
> 
> -	return DIV_ROUND_CLOSEST_ULL(rate, CPG_PLL_CLK1_PDIV(clk1));
> +	return DIV_ROUND_CLOSEST_ULL(rate, FIELD_GET(CPG_PLL_CLK1_PDIV,
> +clk1));
>  }
> 
> +static const struct clk_ops rzv2h_cpg_plldsi_ops = {
> +	.recalc_rate = rzv2h_cpg_pll_clk_recalc_rate,
> +	.determine_rate = rzv2h_cpg_plldsi_determine_rate,
> +	.set_rate = rzv2h_cpg_pll_set_rate,
> +};
> +
>  static const struct clk_ops rzv2h_cpg_pll_ops = {
>  	.is_enabled = rzv2h_cpg_pll_clk_is_enabled,
>  	.enable = rzv2h_cpg_pll_clk_enable,
> @@ -228,7 +472,8 @@ static const struct clk_ops rzv2h_cpg_pll_ops = {  static struct clk * __init
> rzv2h_cpg_pll_clk_register(const struct cpg_core_clk *core,
>  			   struct rzv2h_cpg_priv *priv,
> -			   const struct clk_ops *ops)
> +			   const struct clk_ops *ops,
> +			   bool turn_on)
>  {
>  	void __iomem *base = priv->base;
>  	struct device *dev = priv->dev;
> @@ -258,6 +503,13 @@ rzv2h_cpg_pll_clk_register(const struct cpg_core_clk *core,
>  	pll_clk->base = base;
>  	pll_clk->priv = priv;
> 
> +	if (turn_on) {
> +		/* Disable SSC and turn on PLL clock when init */
> +		writel(CPG_PLL_STBY_RESETB_WEN | CPG_PLL_STBY_RESETB |
> +		       CPG_PLL_STBY_SSC_EN_WEN,
> +		       base + CPG_PLL_STBY(pll_clk->pll.offset));
> +	}
> +
>  	ret = devm_clk_hw_register(dev, &pll_clk->hw);
>  	if (ret)
>  		return ERR_PTR(ret);
> @@ -500,7 +752,7 @@ rzv2h_cpg_register_core_clk(const struct cpg_core_clk *core,
>  			clk = clk_hw->clk;
>  		break;
>  	case CLK_TYPE_PLL:
> -		clk = rzv2h_cpg_pll_clk_register(core, priv, &rzv2h_cpg_pll_ops);
> +		clk = rzv2h_cpg_pll_clk_register(core, priv, &rzv2h_cpg_pll_ops,
> +false);
>  		break;
>  	case CLK_TYPE_DDIV:
>  		clk = rzv2h_cpg_ddiv_clk_register(core, priv); @@ -508,6 +760,12 @@
> rzv2h_cpg_register_core_clk(const struct cpg_core_clk *core,
>  	case CLK_TYPE_SMUX:
>  		clk = rzv2h_cpg_mux_clk_register(core, priv);
>  		break;
> +	case CLK_TYPE_PLLDSI:
> +		clk = rzv2h_cpg_pll_clk_register(core, priv, &rzv2h_cpg_plldsi_ops, true);
> +		break;
> +	case CLK_TYPE_PLLDSI_DIV:
> +		clk = rzv2h_cpg_plldsi_div_clk_register(core, priv);
> +		break;
>  	default:
>  		goto fail;
>  	}
> @@ -1043,6 +1301,8 @@ static int __init rzv2h_cpg_probe(struct platform_device *pdev)
>  	priv->last_dt_core_clk = info->last_dt_core_clk;
>  	priv->num_resets = info->num_resets;
> 
> +	priv->dsi_limits = info->plldsi_limits;
> +
>  	for (i = 0; i < nclks; i++)
>  		clks[i] = ERR_PTR(-ENOENT);
> 
> diff --git a/drivers/clk/renesas/rzv2h-cpg.h b/drivers/clk/renesas/rzv2h-cpg.h index
> 7321b085f937..1f1ef2fcf878 100644
> --- a/drivers/clk/renesas/rzv2h-cpg.h
> +++ b/drivers/clk/renesas/rzv2h-cpg.h
> @@ -166,6 +166,8 @@ enum clk_types {
>  	CLK_TYPE_PLL,
>  	CLK_TYPE_DDIV,		/* Dynamic Switching Divider */
>  	CLK_TYPE_SMUX,		/* Static Mux */
> +	CLK_TYPE_PLLDSI,	/* PLLDSI */
> +	CLK_TYPE_PLLDSI_DIV,	/* PLLDSI divider */
>  };
> 
>  #define DEF_TYPE(_name, _id, _type...) \ @@ -193,6 +195,14 @@ enum clk_types {
>  		 .num_parents = ARRAY_SIZE(_parent_names), \
>  		 .flag = CLK_SET_RATE_PARENT, \
>  		 .mux_flags = CLK_MUX_HIWORD_MASK)
> +#define DEF_PLLDSI(_name, _id, _parent, _pll_packed) \
> +	DEF_TYPE(_name, _id, CLK_TYPE_PLLDSI, .parent = _parent, .cfg.pll =
> +_pll_packed) #define DEF_PLLDSI_DIV(_name, _id, _parent, _ddiv_packed, _dtable) \
> +	DEF_TYPE(_name, _id, CLK_TYPE_PLLDSI_DIV, \
> +		 .cfg.ddiv = _ddiv_packed, \
> +		 .dtable = _dtable, \
> +		 .parent = _parent, \
> +		 .flag = CLK_SET_RATE_PARENT)
> 
>  /**
>   * struct rzv2h_mod_clk - Module Clocks definitions @@ -293,6 +303,7 @@ struct rzv2h_reset {
>   *
>   * @num_mstop_bits: Maximum number of MSTOP bits supported, equivalent to the
>   *		    number of CPG_BUS_m_MSTOP registers multiplied by 16.
> + * @plldsi_limits: PLL DSI parameters limits
>   */
>  struct rzv2h_cpg_info {
>  	/* Core Clocks */
> @@ -311,6 +322,8 @@ struct rzv2h_cpg_info {
>  	unsigned int num_resets;
> 
>  	unsigned int num_mstop_bits;
> +
> +	const struct rzv2h_pll_div_limits *plldsi_limits;
>  };
> 
>  extern const struct rzv2h_cpg_info r9a09g047_cpg_info; diff --git a/include/linux/clk/renesas-rzv2h-
> dsi.h b/include/linux/clk/renesas-rzv2h-dsi.h
> new file mode 100644
> index 000000000000..b77f9bc3777e
> --- /dev/null
> +++ b/include/linux/clk/renesas-rzv2h-dsi.h
> @@ -0,0 +1,210 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Renesas RZ/V2H(P) DSI CPG helper
> + *
> + * Copyright (C) 2025 Renesas Electronics Corp.
> + */
> +#ifndef __RENESAS_RZV2H_DSI_H__
> +#define __RENESAS_RZV2H_DSI_H__
> +
> +#include <linux/limits.h>
> +#include <linux/math.h>
> +#include <linux/math64.h>
> +#include <linux/units.h>
> +
> +#define OSC_CLK_IN_MEGA		(24 * MEGA)
> +
> +struct rzv2h_pll_div_limits {
> +	struct {
> +		u32 min;
> +		u32 max;
> +	} fvco;
> +
> +	struct {
> +		u16 min;
> +		u16 max;
> +	} m;
> +
> +	struct {
> +		u8 min;
> +		u8 max;
> +	} p;
> +
> +	struct {
> +		u8 min;
> +		u8 max;
> +	} s;
> +
> +	struct {
> +		s16 min;
> +		s16 max;
> +	} k;
> +
> +	struct {
> +		u8 min;
> +		u8 max;
> +	} csdiv;
> +};
> +
> +struct rzv2h_plldsi_parameters {
> +	u64 freq_millihz;
> +	s64 error_millihz;
> +	u16 m;
> +	s16 k;
> +	u8 csdiv;
> +	u8 p;
> +	u8 s;
> +};
> +
> +#define RZV2H_CPG_PLL_DSI_LIMITS(name)					\
> +	static const struct rzv2h_pll_div_limits (name) = {		\
> +		.fvco = { .min = 1600 * MEGA, .max = 3200 * MEGA },	\
> +		.m = { .min = 64, .max = 533 },				\
> +		.p = { .min = 1, .max = 4 },				\
> +		.s = { .min = 0, .max = 6 },				\
> +		.k = { .min = -32768, .max = 32767 },			\
> +		.csdiv = { .min = 2, .max = 32 },			\
> +	}								\
> +
> +/**
> + * rzv2h_dsi_get_pll_parameters_values - Finds the best combination of
> +PLL parameters
> + * and divider value for a given frequency.
> + *
> + * @limits: Pointer to the structure containing the limits for the PLL
> +parameters and
> + * divider values
> + * @pars: Pointer to the structure where the best calculated PLL
> +parameters and divider
> + * values will be stored
> + * @freq_millihz: Target output frequency in millihertz
> + *
> + * This function calculates the best set of PLL parameters (M, K, P, S)
> +and divider
> + * value (CSDIV) to achieve the desired frequency.
> + * There is no direct formula to calculate the PLL parameters and the
> +divider value,
> + * as it's an open system of equations, therefore this function uses an
> +iterative
> + * approach to determine the best solution. The best solution is one
> +that minimizes
> + * the error (desired frequency - actual frequency).
> + *
> + * Return: true if a valid set of divider values is found, false otherwise.
> + */
> +static __maybe_unused bool
> +rzv2h_dsi_get_pll_parameters_values(const struct rzv2h_pll_div_limits *limits,
> +				    struct rzv2h_plldsi_parameters *pars,
> +				    u64 freq_millihz)
> +{
> +	struct rzv2h_plldsi_parameters p, best;
> +
> +	/* Initialize best error to maximum possible value */
> +	best.error_millihz = S64_MAX;
> +
> +	for (p.csdiv = limits->csdiv.min; p.csdiv <= limits->csdiv.max; p.csdiv += 2) {
> +		for (p.p = limits->p.min; p.p <= limits->p.max; p.p++) {
> +			u32 fref = OSC_CLK_IN_MEGA / p.p;
> +			u16 divider;
> +
> +			for (divider = p.csdiv << limits->s.min, p.s = limits->s.min;
> +			     p.s <= limits->s.max; p.s++, divider *= 2) {
> +				for (p.m = limits->m.min; p.m <= limits->m.max; p.m++) {
> +					u64 output_m, output_k_range;
> +					s64 pll_k, output_k;
> +					u64 fvco, output;
> +
> +					/*
> +					 * The frequency generated by the combination of the
> +					 * PLL + divider is calculated as follows:
> +					 *
> +					 * Freq = Ffout / csdiv
> +					 *
> +					 * With:
> +					 * Ffout = Ffvco / 2^(pll_s)
> +					 * Ffvco = (pll_m + (pll_k / 65536)) * Ffref
> +					 * Ffref = 24MHz / pll_p
> +					 *
> +					 * Freq can also be rewritten as:
> +					 * Freq = Ffvco / (2^(pll_s) * csdiv))
> +					 *      = Ffvco / divider
> +					 *      = (pll_m * Ffref) / divider + ((pll_k / 65536) * Ffref) /
> divider
> +					 *      = output_m + output_k
> +					 *
> +					 * Every parameter has been determined at this point, but pll_k.
> +					 * Considering that:
> +					 * -32768 <= pll_k <= 32767
> +					 * Then:
> +					 * -0.5 <= (pll_k / 65536) < 0.5
> +					 * Therefore:
> +					 * -Ffref / (2 * divider) <= output_k < Ffref / (2 * divider)
> +					 */
> +
> +					/* Compute output M component (in mHz) */
> +					output_m = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(p.m, fref) * MILLI,
> +									 divider);
> +					/* Compute range for output K (in mHz) */
> +					output_k_range = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(fref, MILLI),
> +									       divider * 2);
> +					/*
> +					 * No point in continuing if we can't achieve the
> +					 * desired frequency
> +					 */
> +					if (freq_millihz <  (output_m - output_k_range) ||
> +					    freq_millihz >= (output_m + output_k_range))
> +						continue;
> +
> +					/*
> +					 * Compute the K component
> +					 *
> +					 * Since:
> +					 * Freq = output_m + output_k
> +					 * Then:
> +					 * output_k = Freq - output_m
> +					 *          = ((pll_k / 65536) * Ffref) / divider
> +					 * Therefore:
> +					 * pll_k = (output_k * 65536 * divider) / Ffref
> +					 */
> +					output_k = freq_millihz - output_m;
> +					pll_k = div_s64(output_k * 65536ULL * divider, fref);
> +					pll_k = DIV_S64_ROUND_CLOSEST(pll_k, MILLI);
> +
> +					/* Validate K value within allowed limits */
> +					if (pll_k < limits->k.min || pll_k > limits->k.max)
> +						continue;
> +
> +					p.k = pll_k;
> +
> +					/* Compute (Ffvco * 65536) */
> +					fvco = mul_u32_u32(p.m * 65536 + p.k, fref);
> +					if ((fvco < mul_u32_u32(limits->fvco.min, 65536)) ||
> +					    (fvco > mul_u32_u32(limits->fvco.max, 65536)))
> +						continue;
> +
> +					/* PLL_M component of (output * 65536 * PLL_P) */
> +					output = mul_u32_u32(p.m * 65536, OSC_CLK_IN_MEGA);
> +					/* PLL_K component of (output * 65536 * PLL_P) */
> +					output += p.k * OSC_CLK_IN_MEGA;
> +					/* Make it in mHz */
> +					output *= MILLI;
> +					output = DIV_U64_ROUND_CLOSEST(output, 65536 * p.p * divider);
> +
> +					p.error_millihz = freq_millihz - output;
> +					p.freq_millihz = output;
> +
> +					/* If an exact match is found, return immediately */
> +					if (p.error_millihz == 0) {
> +						*pars = p;
> +						return true;
> +					}
> +
> +					/* Update best match if error is smaller */
> +					if (abs(best.error_millihz) > abs(p.error_millihz))
> +						best = p;
> +				}
> +			}
> +		}
> +	}
> +
> +	/* If no valid parameters were found, return false */
> +	if (best.error_millihz == S64_MAX)
> +		return false;
> +
> +	*pars = best;
> +	return true;
> +}
> +
> +#endif	/* __RENESAS_RZV2H_DSI_H__ */
> --
> 2.49.0


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

* RE: [PATCH v6 4/4] drm: renesas: rz-du: mipi_dsi: Add support for RZ/V2H(P) SoC
  2025-05-30 17:18 ` [PATCH v6 4/4] drm: renesas: rz-du: mipi_dsi: " Prabhakar
@ 2025-06-13  6:17   ` Biju Das
  2025-06-16 10:48     ` Lad, Prabhakar
  0 siblings, 1 reply; 18+ messages in thread
From: Biju Das @ 2025-06-13  6:17 UTC (permalink / raw)
  To: Prabhakar, Geert Uytterhoeven, Andrzej Hajda, Neil Armstrong,
	Robert Foss, laurent.pinchart, Jonas Karlman, Jernej Skrabec,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Michael Turquette, Stephen Boyd, Magnus Damm
  Cc: dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-renesas-soc@vger.kernel.org,
	linux-clk@vger.kernel.org, Fabrizio Castro, Prabhakar Mahadev Lad

Hi Prabhakar,

> -----Original Message-----
> From: Prabhakar <prabhakar.csengg@gmail.com>
> Sent: 30 May 2025 18:19
> Subject: [PATCH v6 4/4] drm: renesas: rz-du: mipi_dsi: Add support for RZ/V2H(P) SoC
> 
> From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> 
> Add DSI support for Renesas RZ/V2H(P) SoC.
> 
> Co-developed-by: Fabrizio Castro <fabrizio.castro.jz@renesas.com>
> Signed-off-by: Fabrizio Castro <fabrizio.castro.jz@renesas.com>
> Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> ---
> v5->v6:
> - Made use of GENMASK() macro for PLLCLKSET0R_PLL_*,
>   PHYTCLKSETR_* and PHYTHSSETR_* macros.
> - Replaced 10000000UL with 10 * MEGA
> - Renamed mode_freq_hz to mode_freq_khz in rzv2h_dsi_mode_calc
> - Replaced `i -= 1;` with `i--;`
> - Renamed RZV2H_MIPI_DPHY_FOUT_MIN_IN_MEGA to
>   RZV2H_MIPI_DPHY_FOUT_MIN_IN_MHZ and
>   RZV2H_MIPI_DPHY_FOUT_MAX_IN_MEGA to
>   RZV2H_MIPI_DPHY_FOUT_MAX_IN_MHZ.
> 
> v4->v5:
> - No changes
> 
> v3->v4
> - In rzv2h_dphy_find_ulpsexit() made the array static const.
> 
> v2->v3:
> - Simplifed V2H DSI timings array to save space
> - Switched to use fsleep() instead of udelay()
> 
> v1->v2:
> - Dropped unused macros
> - Added missing LPCLK flag to rzv2h info
> ---
>  .../gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c    | 345 ++++++++++++++++++
>  .../drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h   |  34 ++
>  2 files changed, 379 insertions(+)
> 
> diff --git a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c b/drivers/gpu/drm/renesas/rz-
> du/rzg2l_mipi_dsi.c
> index a31f9b6aa920..ea554ced6713 100644
> --- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
> +++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
> @@ -5,6 +5,7 @@
>   * Copyright (C) 2022 Renesas Electronics Corporation
>   */
>  #include <linux/clk.h>
> +#include <linux/clk/renesas-rzv2h-dsi.h>
>  #include <linux/delay.h>
>  #include <linux/io.h>
>  #include <linux/iopoll.h>
> @@ -30,6 +31,9 @@
> 
>  #define RZ_MIPI_DSI_FEATURE_16BPP	BIT(0)
> 
> +#define RZV2H_MIPI_DPHY_FOUT_MIN_IN_MHZ	(80 * MEGA)
> +#define RZV2H_MIPI_DPHY_FOUT_MAX_IN_MHZ	(1500 * MEGA)
> +
>  struct rzg2l_mipi_dsi;
> 
>  struct rzg2l_mipi_dsi_hw_info {
> @@ -40,6 +44,7 @@ struct rzg2l_mipi_dsi_hw_info {
>  			      u64 *hsfreq_millihz);
>  	unsigned int (*dphy_mode_clk_check)(struct rzg2l_mipi_dsi *dsi,
>  					    unsigned long mode_freq);
> +	const struct rzv2h_pll_div_limits *cpg_dsi_limits;
>  	u32 phy_reg_offset;
>  	u32 link_reg_offset;
>  	unsigned long min_dclk;
> @@ -47,6 +52,11 @@ struct rzg2l_mipi_dsi_hw_info {
>  	u8 features;
>  };
> 
> +struct rzv2h_dsi_mode_calc {
> +	unsigned long mode_freq_khz;
> +	u64 mode_freq_hz;
> +};
> +
>  struct rzg2l_mipi_dsi {
>  	struct device *dev;
>  	void __iomem *mmio;
> @@ -68,6 +78,18 @@ struct rzg2l_mipi_dsi {
>  	unsigned int num_data_lanes;
>  	unsigned int lanes;
>  	unsigned long mode_flags;
> +
> +	struct rzv2h_dsi_mode_calc mode_calc;
> +	struct rzv2h_plldsi_parameters dsi_parameters; };
> +
> +static const struct rzv2h_pll_div_limits rzv2h_plldsi_div_limits = {
> +	.fvco = { .min = 1050 * MEGA, .max = 2100 * MEGA },
> +	.m = { .min = 64, .max = 1023 },
> +	.p = { .min = 1, .max = 4 },
> +	.s = { .min = 0, .max = 5 },
> +	.k = { .min = -32768, .max = 32767 },
> +	.csdiv = { .min = 1, .max = 1 },
>  };
> 
>  static inline struct rzg2l_mipi_dsi *
> @@ -184,6 +206,155 @@ static const struct rzg2l_mipi_dsi_timings rzg2l_mipi_dsi_global_timings[] = {
>  	},
>  };
> 
> +struct rzv2h_mipi_dsi_timings {
> +	const u8 *hsfreq;
> +	u8 len;
> +	u8 start_index;
> +};
> +
> +enum {
> +	TCLKPRPRCTL,
> +	TCLKZEROCTL,
> +	TCLKPOSTCTL,
> +	TCLKTRAILCTL,
> +	THSPRPRCTL,
> +	THSZEROCTL,
> +	THSTRAILCTL,
> +	TLPXCTL,
> +	THSEXITCTL,
> +};
> +
> +static const u8 tclkprprctl[] = {
> +	15, 26, 37, 47, 58, 69, 79, 90, 101, 111, 122, 133, 143, 150, };
> +
> +static const u8 tclkzeroctl[] = {
> +	9, 11, 13, 15, 18, 21, 23, 24, 25, 27, 29, 31, 34, 36, 38,
> +	41, 43, 45, 47, 50, 52, 54, 57, 59, 61, 63, 66, 68, 70, 73,
> +	75, 77, 79, 82, 84, 86, 89, 91, 93, 95, 98, 100, 102, 105,
> +	107, 109, 111, 114, 116, 118, 121, 123, 125, 127, 130, 132,
> +	134, 137, 139, 141, 143, 146, 148, 150, };
> +
> +static const u8 tclkpostctl[] = {
> +	8, 21, 34, 48, 61, 74, 88, 101, 114, 128, 141, 150, };
> +
> +static const u8 tclktrailctl[] = {
> +	14, 25, 37, 48, 59, 71, 82, 94, 105, 117, 128, 139, 150, };
> +
> +static const u8 thsprprctl[] = {
> +	11, 19, 29, 40, 50, 61, 72, 82, 93, 103, 114, 125, 135, 146, 150, };
> +
> +static const u8 thszeroctl[] = {
> +	18, 24, 29, 35, 40, 46, 51, 57, 62, 68, 73, 79, 84, 90,
> +	95, 101, 106, 112, 117, 123, 128, 134, 139, 145, 150, };
> +
> +static const u8 thstrailctl[] = {
> +	10, 21, 32, 42, 53, 64, 75, 85, 96, 107, 118, 128, 139, 150, };
> +
> +static const u8 tlpxctl[] = {
> +	13, 26, 39, 53, 66, 79, 93, 106, 119, 133, 146,	150,
> +};
> +
> +static const u8 thsexitctl[] = {
> +	15, 23, 31, 39, 47, 55, 63, 71, 79, 87,
> +	95, 103, 111, 119, 127, 135, 143, 150, };
> +
> +static const struct rzv2h_mipi_dsi_timings rzv2h_dsi_timings_tables[] = {
> +	[TCLKPRPRCTL] = {
> +		.hsfreq = tclkprprctl,
> +		.len = ARRAY_SIZE(tclkprprctl),
> +		.start_index = 0,
> +	},
> +	[TCLKZEROCTL] = {
> +		.hsfreq = tclkzeroctl,
> +		.len = ARRAY_SIZE(tclkzeroctl),
> +		.start_index = 2,
> +	},
> +	[TCLKPOSTCTL] = {
> +		.hsfreq = tclkpostctl,
> +		.len = ARRAY_SIZE(tclkpostctl),
> +		.start_index = 6,
> +	},
> +	[TCLKTRAILCTL] = {
> +		.hsfreq = tclktrailctl,
> +		.len = ARRAY_SIZE(tclktrailctl),
> +		.start_index = 1,
> +	},
> +	[THSPRPRCTL] = {
> +		.hsfreq = thsprprctl,
> +		.len = ARRAY_SIZE(thsprprctl),
> +		.start_index = 0,
> +	},
> +	[THSZEROCTL] = {
> +		.hsfreq = thszeroctl,
> +		.len = ARRAY_SIZE(thszeroctl),
> +		.start_index = 0,
> +	},
> +	[THSTRAILCTL] = {
> +		.hsfreq = thstrailctl,
> +		.len = ARRAY_SIZE(thstrailctl),
> +		.start_index = 3,
> +	},
> +	[TLPXCTL] = {
> +		.hsfreq = tlpxctl,
> +		.len = ARRAY_SIZE(tlpxctl),
> +		.start_index = 0,
> +	},
> +	[THSEXITCTL] = {
> +		.hsfreq = thsexitctl,
> +		.len = ARRAY_SIZE(thsexitctl),
> +		.start_index = 1,
> +	},
> +};
> +
> +static u16 rzv2h_dphy_find_ulpsexit(unsigned long freq) {
> +	static const unsigned long hsfreq[] = {
> +		1953125UL,
> +		3906250UL,
> +		7812500UL,
> +		15625000UL,
> +	};
> +	static const u16 ulpsexit[] = {49, 98, 195, 391};
> +	unsigned int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(hsfreq); i++) {
> +		if (freq <= hsfreq[i])
> +			break;
> +	}
> +
> +	if (i == ARRAY_SIZE(hsfreq))
> +		i--;
> +
> +	return ulpsexit[i];
> +}
> +
> +static u16 rzv2h_dphy_find_timings_val(unsigned long freq, u8 index) {
> +	const struct rzv2h_mipi_dsi_timings *timings;
> +	u16 i;
> +
> +	timings = &rzv2h_dsi_timings_tables[index];
> +	for (i = 0; i < timings->len; i++) {
> +		unsigned long hsfreq = timings->hsfreq[i] * 10 * MEGA;
> +
> +		if (freq <= hsfreq)
> +			break;
> +	}
> +
> +	if (i == timings->len)
> +		i--;
> +
> +	return timings->start_index + i;
> +};
> +
>  static void rzg2l_mipi_dsi_phy_write(struct rzg2l_mipi_dsi *dsi, u32 reg, u32 data)  {
>  	iowrite32(data, dsi->mmio + dsi->info->phy_reg_offset + reg); @@ -308,6 +479,160 @@ static int
> rzg2l_dphy_conf_clks(struct rzg2l_mipi_dsi *dsi, unsigned long mode_f
>  	return 0;
>  }
> 
> +static unsigned int rzv2h_dphy_mode_clk_check(struct rzg2l_mipi_dsi *dsi,
> +					      unsigned long mode_freq)
> +{
> +	struct rzv2h_plldsi_parameters cpg_dsi_parameters;
> +	struct rzv2h_plldsi_parameters dsi_parameters;
> +	u64 hsfreq_millihz, mode_freq_hz, mode_freq_millihz;
> +	unsigned int bpp, i;
> +
> +	bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
> +
> +	for (i = 0; i < 10; i += 1) {
> +		unsigned long hsfreq;
> +		bool parameters_found;
> +
> +		mode_freq_hz = mul_u32_u32(mode_freq, KILO) + i;
> +		mode_freq_millihz = mode_freq_hz * MILLI;
> +		parameters_found = rzv2h_dsi_get_pll_parameters_values(dsi->info->cpg_dsi_limits,
> +								       &cpg_dsi_parameters,
> +								       mode_freq_millihz);
> +		if (!parameters_found)
> +			continue;
> +
> +		hsfreq_millihz = DIV_ROUND_CLOSEST_ULL(cpg_dsi_parameters.freq_millihz * bpp,
> +						       dsi->lanes);
> +		parameters_found = rzv2h_dsi_get_pll_parameters_values(&rzv2h_plldsi_div_limits,
> +								       &dsi_parameters,
> +								       hsfreq_millihz);
> +		if (!parameters_found)
> +			continue;
> +
> +		if (abs(dsi_parameters.error_millihz) >= 500)
> +			continue;
> +
> +		hsfreq = DIV_ROUND_CLOSEST_ULL(hsfreq_millihz, MILLI);
> +		if (hsfreq >= RZV2H_MIPI_DPHY_FOUT_MIN_IN_MHZ &&
> +		    hsfreq <= RZV2H_MIPI_DPHY_FOUT_MAX_IN_MHZ) {
> +			memcpy(&dsi->dsi_parameters, &dsi_parameters, sizeof(dsi->dsi_parameters));
> +			dsi->mode_calc.mode_freq_khz = mode_freq;
> +			dsi->mode_calc.mode_freq_hz = mode_freq_hz;
> +			return MODE_OK;
> +		}
> +	}
> +
> +	return MODE_CLOCK_RANGE;
> +}
> +
> +static int rzv2h_dphy_conf_clks(struct rzg2l_mipi_dsi *dsi, unsigned long mode_freq,
> +				u64 *hsfreq_millihz)
> +{
> +	struct rzv2h_plldsi_parameters *dsi_parameters = &dsi->dsi_parameters;
> +	unsigned long status;
> +
> +	if (dsi->mode_calc.mode_freq_khz != mode_freq) {
> +		status = rzv2h_dphy_mode_clk_check(dsi, mode_freq);
> +		if (status != MODE_OK) {
> +			dev_err(dsi->dev, "No PLL parameters found for mode clk %lu\n",
> +				mode_freq);
> +			return -EINVAL;
> +		}
> +	}
> +
> +	clk_set_rate(dsi->vclk, dsi->mode_calc.mode_freq_hz);

Not sure, Can we use the DSI divider required based on the data rate (vclk, bpp and numlanes) here

and then the set parent clk of PLLDSI as well here (dsi->vclk * the divider value) ??

24MHZ->PLL DSI->DSI DIVIDER->VCLOCK

Maybe then the clock framework has all the information for setting PLL_DSI and DSI_DIVIDER clks??

Cheers,
Biju


> +	*hsfreq_millihz = dsi_parameters->freq_millihz;
> +
> +	return 0;
> +}
> +
> +static int rzv2h_mipi_dsi_dphy_init(struct rzg2l_mipi_dsi *dsi,
> +				    u64 hsfreq_millihz)
> +{
> +	struct rzv2h_plldsi_parameters *dsi_parameters = &dsi->dsi_parameters;
> +	unsigned long lpclk_rate = clk_get_rate(dsi->lpclk);
> +	u32 phytclksetr, phythssetr, phytlpxsetr, phycr;
> +	struct rzg2l_mipi_dsi_timings dphy_timings;
> +	u16 ulpsexit;
> +	u64 hsfreq;
> +
> +	hsfreq = DIV_ROUND_CLOSEST_ULL(hsfreq_millihz, MILLI);
> +
> +	if (dsi_parameters->freq_millihz == hsfreq_millihz)
> +		goto parameters_found;
> +
> +	if (rzv2h_dsi_get_pll_parameters_values(&rzv2h_plldsi_div_limits,
> +						dsi_parameters, hsfreq_millihz))
> +		goto parameters_found;
> +
> +	dev_err(dsi->dev, "No PLL parameters found for HSFREQ %lluHz\n", hsfreq);
> +	return -EINVAL;
> +
> +parameters_found:
> +	dphy_timings.tclk_trail =
> +		rzv2h_dphy_find_timings_val(hsfreq, TCLKTRAILCTL);
> +	dphy_timings.tclk_post =
> +		rzv2h_dphy_find_timings_val(hsfreq, TCLKPOSTCTL);
> +	dphy_timings.tclk_zero =
> +		rzv2h_dphy_find_timings_val(hsfreq, TCLKZEROCTL);
> +	dphy_timings.tclk_prepare =
> +		rzv2h_dphy_find_timings_val(hsfreq, TCLKPRPRCTL);
> +	dphy_timings.ths_exit =
> +		rzv2h_dphy_find_timings_val(hsfreq, THSEXITCTL);
> +	dphy_timings.ths_trail =
> +		rzv2h_dphy_find_timings_val(hsfreq, THSTRAILCTL);
> +	dphy_timings.ths_zero =
> +		rzv2h_dphy_find_timings_val(hsfreq, THSZEROCTL);
> +	dphy_timings.ths_prepare =
> +		rzv2h_dphy_find_timings_val(hsfreq, THSPRPRCTL);
> +	dphy_timings.tlpx =
> +		rzv2h_dphy_find_timings_val(hsfreq, TLPXCTL);
> +	ulpsexit = rzv2h_dphy_find_ulpsexit(lpclk_rate);
> +
> +	phytclksetr = FIELD_PREP(PHYTCLKSETR_TCLKTRAILCTL, dphy_timings.tclk_trail) |
> +		      FIELD_PREP(PHYTCLKSETR_TCLKPOSTCTL, dphy_timings.tclk_post) |
> +		      FIELD_PREP(PHYTCLKSETR_TCLKZEROCTL, dphy_timings.tclk_zero) |
> +		      FIELD_PREP(PHYTCLKSETR_TCLKPRPRCTL, dphy_timings.tclk_prepare);
> +	phythssetr = FIELD_PREP(PHYTHSSETR_THSEXITCTL, dphy_timings.ths_exit) |
> +		     FIELD_PREP(PHYTHSSETR_THSTRAILCTL, dphy_timings.ths_trail) |
> +		     FIELD_PREP(PHYTHSSETR_THSZEROCTL, dphy_timings.ths_zero) |
> +		     FIELD_PREP(PHYTHSSETR_THSPRPRCTL, dphy_timings.ths_prepare);
> +	phytlpxsetr = rzg2l_mipi_dsi_phy_read(dsi, PHYTLPXSETR) & ~PHYTLPXSETR_TLPXCTL;
> +	phytlpxsetr |= FIELD_PREP(PHYTLPXSETR_TLPXCTL, dphy_timings.tlpx);
> +	phycr = rzg2l_mipi_dsi_phy_read(dsi, PHYCR) & ~GENMASK(9, 0);
> +	phycr |= FIELD_PREP(PHYCR_ULPSEXIT, ulpsexit);
> +
> +	/* Setting all D-PHY Timings Registers */
> +	rzg2l_mipi_dsi_phy_write(dsi, PHYTCLKSETR, phytclksetr);
> +	rzg2l_mipi_dsi_phy_write(dsi, PHYTHSSETR, phythssetr);
> +	rzg2l_mipi_dsi_phy_write(dsi, PHYTLPXSETR, phytlpxsetr);
> +	rzg2l_mipi_dsi_phy_write(dsi, PHYCR, phycr);
> +
> +	rzg2l_mipi_dsi_phy_write(dsi, PLLCLKSET0R,
> +				 FIELD_PREP(PLLCLKSET0R_PLL_S, dsi_parameters->s) |
> +				 FIELD_PREP(PLLCLKSET0R_PLL_P, dsi_parameters->p) |
> +				 FIELD_PREP(PLLCLKSET0R_PLL_M, dsi_parameters->m));
> +	rzg2l_mipi_dsi_phy_write(dsi, PLLCLKSET1R,
> +				 FIELD_PREP(PLLCLKSET1R_PLL_K, dsi_parameters->k));
> +	fsleep(20);
> +
> +	rzg2l_mipi_dsi_phy_write(dsi, PLLENR, PLLENR_PLLEN);
> +	fsleep(500);
> +
> +	return 0;
> +}
> +
> +static void rzv2h_mipi_dsi_dphy_startup_late_init(struct rzg2l_mipi_dsi
> +*dsi) {
> +	fsleep(220);
> +	rzg2l_mipi_dsi_phy_write(dsi, PHYRSTR, PHYRSTR_PHYMRSTN); }
> +
> +static void rzv2h_mipi_dsi_dphy_exit(struct rzg2l_mipi_dsi *dsi) {
> +	rzg2l_mipi_dsi_phy_write(dsi, PLLENR, 0); }
> +
>  static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi,
>  				  const struct drm_display_mode *mode)  { @@ -410,6 +735,9 @@ static void
> rzg2l_mipi_dsi_set_display_timing(struct rzg2l_mipi_dsi *dsi,
>  	case 18:
>  		vich1ppsetr = VICH1PPSETR_DT_RGB18;
>  		break;
> +	case 16:
> +		vich1ppsetr = VICH1PPSETR_DT_RGB16;
> +		break;
>  	}
> 
>  	if ((dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) && @@ -862,6 +1190,22 @@ static void
> rzg2l_mipi_dsi_remove(struct platform_device *pdev)
>  	pm_runtime_disable(&pdev->dev);
>  }
> 
> +RZV2H_CPG_PLL_DSI_LIMITS(rzv2h_cpg_pll_dsi_limits);
> +
> +static const struct rzg2l_mipi_dsi_hw_info rzv2h_mipi_dsi_info = {
> +	.dphy_init = rzv2h_mipi_dsi_dphy_init,
> +	.dphy_startup_late_init = rzv2h_mipi_dsi_dphy_startup_late_init,
> +	.dphy_exit = rzv2h_mipi_dsi_dphy_exit,
> +	.dphy_mode_clk_check = rzv2h_dphy_mode_clk_check,
> +	.dphy_conf_clks = rzv2h_dphy_conf_clks,
> +	.cpg_dsi_limits = &rzv2h_cpg_pll_dsi_limits,
> +	.phy_reg_offset = 0x10000,
> +	.link_reg_offset = 0,
> +	.min_dclk = 5440,
> +	.max_dclk = 187500,
> +	.features = RZ_MIPI_DSI_FEATURE_16BPP, };
> +
>  static const struct rzg2l_mipi_dsi_hw_info rzg2l_mipi_dsi_info = {
>  	.dphy_init = rzg2l_mipi_dsi_dphy_init,
>  	.dphy_exit = rzg2l_mipi_dsi_dphy_exit, @@ -872,6 +1216,7 @@ static const struct
> rzg2l_mipi_dsi_hw_info rzg2l_mipi_dsi_info = {  };
> 
>  static const struct of_device_id rzg2l_mipi_dsi_of_table[] = {
> +	{ .compatible = "renesas,r9a09g057-mipi-dsi", .data =
> +&rzv2h_mipi_dsi_info, },
>  	{ .compatible = "renesas,rzg2l-mipi-dsi", .data = &rzg2l_mipi_dsi_info, },
>  	{ /* sentinel */ }
>  };
> diff --git a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h b/drivers/gpu/drm/renesas/rz-
> du/rzg2l_mipi_dsi_regs.h
> index 16efe4dc59f4..87963871cacd 100644
> --- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h
> +++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h
> @@ -40,6 +40,39 @@
>  #define DSIDPHYTIM3_THS_TRAIL(x)	((x) << 8)
>  #define DSIDPHYTIM3_THS_ZERO(x)		((x) << 0)
> 
> +/* RZ/V2H DPHY Registers */
> +#define PLLENR				0x000
> +#define PLLENR_PLLEN			BIT(0)
> +
> +#define PHYRSTR				0x004
> +#define PHYRSTR_PHYMRSTN		BIT(0)
> +
> +#define PLLCLKSET0R			0x010
> +#define PLLCLKSET0R_PLL_S		GENMASK(2, 0)
> +#define PLLCLKSET0R_PLL_P		GENMASK(13, 8)
> +#define PLLCLKSET0R_PLL_M		GENMASK(25, 16)
> +
> +#define PLLCLKSET1R			0x014
> +#define PLLCLKSET1R_PLL_K		GENMASK(15, 0)
> +
> +#define PHYTCLKSETR			0x020
> +#define PHYTCLKSETR_TCLKTRAILCTL        GENMASK(7, 0)
> +#define PHYTCLKSETR_TCLKPOSTCTL         GENMASK(15, 8)
> +#define PHYTCLKSETR_TCLKZEROCTL         GENMASK(23, 16)
> +#define PHYTCLKSETR_TCLKPRPRCTL         GENMASK(31, 24)
> +
> +#define PHYTHSSETR			0x024
> +#define PHYTHSSETR_THSEXITCTL           GENMASK(7, 0)
> +#define PHYTHSSETR_THSTRAILCTL          GENMASK(15, 8)
> +#define PHYTHSSETR_THSZEROCTL           GENMASK(23, 16)
> +#define PHYTHSSETR_THSPRPRCTL           GENMASK(31, 24)
> +
> +#define PHYTLPXSETR			0x028
> +#define PHYTLPXSETR_TLPXCTL             GENMASK(7, 0)
> +
> +#define PHYCR				0x030
> +#define PHYCR_ULPSEXIT                  GENMASK(9, 0)
> +
>  /* --------------------------------------------------------*/
> 
>  /* Link Status Register */
> @@ -116,6 +149,7 @@
> 
>  /* Video-Input Channel 1 Pixel Packet Set Register */
>  #define VICH1PPSETR			0x420
> +#define VICH1PPSETR_DT_RGB16		(0x0e << 16)
>  #define VICH1PPSETR_DT_RGB18		(0x1e << 16)
>  #define VICH1PPSETR_DT_RGB18_LS		(0x2e << 16)
>  #define VICH1PPSETR_DT_RGB24		(0x3e << 16)
> --
> 2.49.0


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

* Re: [PATCH v6 1/4] clk: renesas: rzv2h-cpg: Add support for DSI clocks
  2025-06-13  5:57   ` Biju Das
@ 2025-06-16 10:44     ` Lad, Prabhakar
  2025-06-18 13:25       ` Biju Das
  0 siblings, 1 reply; 18+ messages in thread
From: Lad, Prabhakar @ 2025-06-16 10:44 UTC (permalink / raw)
  To: Biju Das
  Cc: Geert Uytterhoeven, Andrzej Hajda, Neil Armstrong, Robert Foss,
	laurent.pinchart, Jonas Karlman, Jernej Skrabec,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Michael Turquette, Stephen Boyd, Magnus Damm,
	dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-renesas-soc@vger.kernel.org,
	linux-clk@vger.kernel.org, Fabrizio Castro, Prabhakar Mahadev Lad

Hi Biju,

Thank you for the review.

On Fri, Jun 13, 2025 at 6:57 AM Biju Das <biju.das.jz@bp.renesas.com> wrote:
>
> Hi Prabhakar,
>
> > -----Original Message-----
> > From: Prabhakar <prabhakar.csengg@gmail.com>
> > Sent: 30 May 2025 18:19
> .castro.jz@renesas.com>; Prabhakar Mahadev Lad <prabhakar.mahadev-
> > lad.rj@bp.renesas.com>
> > Subject: [PATCH v6 1/4] clk: renesas: rzv2h-cpg: Add support for DSI clocks
> >
> > From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> >
> > Add support for PLLDSI and PLLDSI divider clocks.
> >
> > Introduce the `renesas-rzv2h-dsi.h` header to centralize and share PLLDSI-related data structures,
> > limits, and algorithms between the RZ/V2H CPG and DSI drivers.
> >
> > The DSI PLL is functionally similar to the CPG's PLLDSI, but has slightly different parameter limits
> > and omits the programmable divider present in CPG. To ensure precise frequency calculations-especially
> > for milliHz-level accuracy needed by the DSI driver-the shared algorithm allows both drivers to
> > compute PLL parameters consistently using the same logic and input clock.
> >
> > Co-developed-by: Fabrizio Castro <fabrizio.castro.jz@renesas.com>
> > Signed-off-by: Fabrizio Castro <fabrizio.castro.jz@renesas.com>
> > Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> > ---
> > v5->v6:
> > - Renamed CPG_PLL_STBY_SSCGEN_WEN to CPG_PLL_STBY_SSC_EN_WEN
> > - Updated CPG_PLL_CLK1_DIV_K, CPG_PLL_CLK1_DIV_M, and
> >   CPG_PLL_CLK1_DIV_P macros to use GENMASK
> > - Updated req->rate in rzv2h_cpg_plldsi_div_determine_rate()
> > - Dropped the cast in rzv2h_cpg_plldsi_div_set_rate()
> > - Dropped rzv2h_cpg_plldsi_round_rate() and implemented
> >   rzv2h_cpg_plldsi_determine_rate() instead
> > - Made use of FIELD_PREP()
> > - Moved CPG_CSDIV1 macro in patch 2/4
> > - Dropped two_pow_s in rzv2h_dsi_get_pll_parameters_values()
> > - Used mul_u32_u32() while calculating output_m and output_k_range
> > - Used div_s64() instead of div64_s64() while calculating
> >   pll_k
> > - Used mul_u32_u32() while calculating fvco and fvco checks
> > - Rounded the final output using DIV_U64_ROUND_CLOSEST()
> >
> > v4->v5:
> > - No changes
> >
> > v3->v4:
> > - Corrected parameter name in rzv2h_dsi_get_pll_parameters_values()
> >   description freq_millihz
> >
> > v2->v3:
> > - Update the commit message to clarify the purpose of `renesas-rzv2h-dsi.h`
> >   header
> > - Used mul_u32_u32() in rzv2h_cpg_plldsi_div_determine_rate()
> > - Replaced *_mhz to *_millihz for clarity
> > - Updated u64->u32 for fvco limits
> > - Initialized the members in declaration order for
> >   RZV2H_CPG_PLL_DSI_LIMITS() macro
> > - Used clk_div_mask() in rzv2h_cpg_plldsi_div_recalc_rate()
> > - Replaced `unsigned long long` with u64
> > - Dropped rzv2h_cpg_plldsi_clk_recalc_rate() and reused
> >   rzv2h_cpg_pll_clk_recalc_rate() instead
> > - In rzv2h_cpg_plldsi_div_set_rate() followed the same style
> >   of RMW-operation as done in the other functions
> > - Renamed rzv2h_cpg_plldsi_set_rate() to rzv2h_cpg_pll_set_rate()
> > - Dropped rzv2h_cpg_plldsi_clk_register() and reused
> >   rzv2h_cpg_pll_clk_register() instead
> > - Added a gaurd in renesas-rzv2h-dsi.h header
> >
> > v1->v2:
> > - No changes
> > ---
> >  drivers/clk/renesas/rzv2h-cpg.c       | 278 +++++++++++++++++++++++++-
> >  drivers/clk/renesas/rzv2h-cpg.h       |  13 ++
> >  include/linux/clk/renesas-rzv2h-dsi.h | 210 +++++++++++++++++++
> >  3 files changed, 492 insertions(+), 9 deletions(-)  create mode 100644 include/linux/clk/renesas-
> > rzv2h-dsi.h
> >
> > diff --git a/drivers/clk/renesas/rzv2h-cpg.c b/drivers/clk/renesas/rzv2h-cpg.c index
> > 761da3bf77ce..d590f9f47371 100644
> > --- a/drivers/clk/renesas/rzv2h-cpg.c
> > +++ b/drivers/clk/renesas/rzv2h-cpg.c
> > @@ -14,9 +14,13 @@
> >  #include <linux/bitfield.h>
> >  #include <linux/clk.h>
> >  #include <linux/clk-provider.h>
> > +#include <linux/clk/renesas-rzv2h-dsi.h>
> >  #include <linux/delay.h>
> >  #include <linux/init.h>
> >  #include <linux/iopoll.h>
> > +#include <linux/math.h>
> > +#include <linux/math64.h>
> > +#include <linux/minmax.h>
> >  #include <linux/mod_devicetable.h>
> >  #include <linux/module.h>
> >  #include <linux/of.h>
> > @@ -26,6 +30,7 @@
> >  #include <linux/refcount.h>
> >  #include <linux/reset-controller.h>
> >  #include <linux/string_choices.h>
> > +#include <linux/units.h>
> >
> >  #include <dt-bindings/clock/renesas-cpg-mssr.h>
> >
> > @@ -48,12 +53,13 @@
> >  #define CPG_PLL_STBY(x)              ((x))
> >  #define CPG_PLL_STBY_RESETB  BIT(0)
> >  #define CPG_PLL_STBY_RESETB_WEN      BIT(16)
> > +#define CPG_PLL_STBY_SSC_EN_WEN BIT(18)
> >  #define CPG_PLL_CLK1(x)              ((x) + 0x004)
> > -#define CPG_PLL_CLK1_KDIV(x) ((s16)FIELD_GET(GENMASK(31, 16), (x)))
> > -#define CPG_PLL_CLK1_MDIV(x) FIELD_GET(GENMASK(15, 6), (x))
> > -#define CPG_PLL_CLK1_PDIV(x) FIELD_GET(GENMASK(5, 0), (x))
> > +#define CPG_PLL_CLK1_KDIV    GENMASK(31, 16)
> > +#define CPG_PLL_CLK1_MDIV    GENMASK(15, 6)
> > +#define CPG_PLL_CLK1_PDIV    GENMASK(5, 0)
> >  #define CPG_PLL_CLK2(x)              ((x) + 0x008)
> > -#define CPG_PLL_CLK2_SDIV(x) FIELD_GET(GENMASK(2, 0), (x))
> > +#define CPG_PLL_CLK2_SDIV    GENMASK(2, 0)
> >  #define CPG_PLL_MON(x)               ((x) + 0x010)
> >  #define CPG_PLL_MON_RESETB   BIT(0)
> >  #define CPG_PLL_MON_LOCK     BIT(4)
> > @@ -79,6 +85,8 @@
> >   * @last_dt_core_clk: ID of the last Core Clock exported to DT
> >   * @mstop_count: Array of mstop values
> >   * @rcdev: Reset controller entity
> > + * @dsi_limits: PLL DSI parameters limits
> > + * @plldsi_div_parameters: PLL DSI and divider parameters configuration
> >   */
> >  struct rzv2h_cpg_priv {
> >       struct device *dev;
> > @@ -95,6 +103,9 @@ struct rzv2h_cpg_priv {
> >       atomic_t *mstop_count;
> >
> >       struct reset_controller_dev rcdev;
> > +
> > +     const struct rzv2h_pll_div_limits *dsi_limits;
> > +     struct rzv2h_plldsi_parameters plldsi_div_parameters;
> >  };
> >
> >  #define rcdev_to_priv(x)     container_of(x, struct rzv2h_cpg_priv, rcdev)
> > @@ -150,6 +161,24 @@ struct ddiv_clk {
> >
> >  #define to_ddiv_clock(_div) container_of(_div, struct ddiv_clk, div)
> >
> > +/**
> > + * struct rzv2h_plldsi_div_clk - PLL DSI DDIV clock
> > + *
> > + * @dtable: divider table
> > + * @priv: CPG private data
> > + * @hw: divider clk
> > + * @ddiv: divider configuration
> > + */
> > +struct rzv2h_plldsi_div_clk {
> > +     const struct clk_div_table *dtable;
> > +     struct rzv2h_cpg_priv *priv;
> > +     struct clk_hw hw;
> > +     struct ddiv ddiv;
> > +};
> > +
> > +#define to_plldsi_div_clk(_hw) \
> > +     container_of(_hw, struct rzv2h_plldsi_div_clk, hw)
> > +
> >  static int rzv2h_cpg_pll_clk_is_enabled(struct clk_hw *hw)  {
> >       struct pll_clk *pll_clk = to_pll(hw);
> > @@ -198,6 +227,214 @@ static int rzv2h_cpg_pll_clk_enable(struct clk_hw *hw)
> >       return ret;
> >  }
> >
> > +static unsigned long rzv2h_cpg_plldsi_div_recalc_rate(struct clk_hw *hw,
> > +                                                   unsigned long parent_rate)
> > +{
> > +     struct rzv2h_plldsi_div_clk *dsi_div = to_plldsi_div_clk(hw);
> > +     struct rzv2h_cpg_priv *priv = dsi_div->priv;
> > +     struct ddiv ddiv = dsi_div->ddiv;
> > +     u32 div;
> > +
> > +     div = readl(priv->base + ddiv.offset);
> > +     div >>= ddiv.shift;
> > +     div &= clk_div_mask(ddiv.width);
> > +     div = dsi_div->dtable[div].div;
> > +
> > +     return DIV_ROUND_CLOSEST_ULL(parent_rate, div); }
> > +
> > +static int rzv2h_cpg_plldsi_div_determine_rate(struct clk_hw *hw,
> > +                                            struct clk_rate_request *req) {
> > +     struct rzv2h_plldsi_div_clk *dsi_div = to_plldsi_div_clk(hw);
> > +     struct rzv2h_cpg_priv *priv = dsi_div->priv;
> > +     struct rzv2h_plldsi_parameters *dsi_dividers = &priv->plldsi_div_parameters;
> > +     u64 rate_millihz;
> > +
> > +     /*
> > +      * Adjust the requested clock rate (`req->rate`) to ensure it falls within
> > +      * the supported range of 5.44 MHz to 187.5 MHz.
> > +      */
> > +     req->rate = clamp(req->rate, 5440000UL, 187500000UL);
> > +
> > +     rate_millihz = mul_u32_u32(req->rate, MILLI);
> > +     if (rate_millihz == dsi_dividers->error_millihz + dsi_dividers->freq_millihz)
> > +             goto exit_determine_rate;
> > +
> > +     if (!rzv2h_dsi_get_pll_parameters_values(priv->dsi_limits,
> > +                                              dsi_dividers, rate_millihz)) {
> > +             dev_err(priv->dev,
> > +                     "failed to determine rate for req->rate: %lu\n",
> > +                     req->rate);
> > +             return -EINVAL;
> > +     }
>
>
> > +
> > +exit_determine_rate:
> > +     req->best_parent_rate = req->rate * dsi_dividers->csdiv;
>
> I believe this has to go after below assignment.
>
Good catch, agreed.

> As parent_rate = rate * calculated DSI divider value.
>
> req->rate = DIV_ROUND_CLOSEST_ULL(dsi_dividers->freq_millihz, MILLI);
> req->best_parent_rate = req->rate * dsi_dividers->csdiv;
>
>
>
> > +     req->rate = DIV_ROUND_CLOSEST_ULL(dsi_dividers->freq_millihz, MILLI);
> > +
> > +     return 0;
> > +};
> > +
> > +static int rzv2h_cpg_plldsi_div_set_rate(struct clk_hw *hw,
> > +                                      unsigned long rate,
> > +                                      unsigned long parent_rate)
> > +{
> > +     struct rzv2h_plldsi_div_clk *dsi_div = to_plldsi_div_clk(hw);
> > +     struct rzv2h_cpg_priv *priv = dsi_div->priv;
> > +     struct rzv2h_plldsi_parameters *dsi_dividers = &priv->plldsi_div_parameters;
> > +     struct ddiv ddiv = dsi_div->ddiv;
> > +     const struct clk_div_table *clkt;
> > +     bool div_found = false;
> > +     u32 val, shift, div;
> > +
> > +     div = dsi_dividers->csdiv;
> > +     for (clkt = dsi_div->dtable; clkt->div; clkt++) {
> > +             if (clkt->div == div) {
> > +                     div_found = true;
> > +                     break;
> > +             }
> > +     }
> > +
> > +     if (!div_found)
> > +             return -EINVAL;
>
> This check can be done in determine rate and cache the divider??
>
Ok, I'll drop this check as the divider is already cached. The for
loop above is to determine the val which is used below to program the
registers.

> > +
> > +     shift = ddiv.shift;
> > +     val = readl(priv->base + ddiv.offset) | DDIV_DIVCTL_WEN(shift);
> > +     val &= ~(clk_div_mask(ddiv.width) << shift);
> > +     val |= clkt->val << shift;
> > +     writel(val, priv->base + ddiv.offset);
> > +
> > +     return 0;
> > +};
> > +
> > +static const struct clk_ops rzv2h_cpg_plldsi_div_ops = {
> > +     .recalc_rate = rzv2h_cpg_plldsi_div_recalc_rate,
> > +     .determine_rate = rzv2h_cpg_plldsi_div_determine_rate,
> > +     .set_rate = rzv2h_cpg_plldsi_div_set_rate, };
> > +
> > +static struct clk * __init
> > +rzv2h_cpg_plldsi_div_clk_register(const struct cpg_core_clk *core,
> > +                               struct rzv2h_cpg_priv *priv)
> > +{
> > +     struct rzv2h_plldsi_div_clk *clk_hw_data;
> > +     struct clk **clks = priv->clks;
> > +     struct clk_init_data init;
> > +     const struct clk *parent;
> > +     const char *parent_name;
> > +     struct clk_hw *clk_hw;
> > +     int ret;
> > +
> > +     parent = clks[core->parent];
> > +     if (IS_ERR(parent))
> > +             return ERR_CAST(parent);
> > +
> > +     clk_hw_data = devm_kzalloc(priv->dev, sizeof(*clk_hw_data), GFP_KERNEL);
> > +     if (!clk_hw_data)
> > +             return ERR_PTR(-ENOMEM);
> > +
> > +     clk_hw_data->priv = priv;
> > +     clk_hw_data->ddiv = core->cfg.ddiv;
> > +     clk_hw_data->dtable = core->dtable;
> > +
> > +     parent_name = __clk_get_name(parent);
> > +     init.name = core->name;
> > +     init.ops = &rzv2h_cpg_plldsi_div_ops;
> > +     init.flags = core->flag;
> > +     init.parent_names = &parent_name;
> > +     init.num_parents = 1;
> > +
> > +     clk_hw = &clk_hw_data->hw;
> > +     clk_hw->init = &init;
> > +
> > +     ret = devm_clk_hw_register(priv->dev, clk_hw);
> > +     if (ret)
> > +             return ERR_PTR(ret);
> > +
> > +     return clk_hw->clk;
> > +}
> > +
> > +static int rzv2h_cpg_plldsi_determine_rate(struct clk_hw *hw,
> > +                                        struct clk_rate_request *req)
> > +{
> > +     struct rzv2h_pll_div_limits dsi_limits;
> > +     struct rzv2h_plldsi_parameters dsi_dividers;
> > +     struct pll_clk *pll_clk = to_pll(hw);
> > +     struct rzv2h_cpg_priv *priv = pll_clk->priv;
> > +     u64 rate_millihz;
> > +
> > +     memcpy(&dsi_limits, priv->dsi_limits, sizeof(dsi_limits));
> > +     dsi_limits.csdiv.min = 1;
> > +     dsi_limits.csdiv.max = 1;
> > +
> > +     req->rate = clamp(req->rate, 25000000UL, 375000000UL);
>
> I guess this clamping is not required as the child already has clamping
> and max DSI divider is fixed.
>
> rate(Max) = 187500 * 1000 * divider = 187.5 MHz(clamped value) * dsi divider
>
Agreed, I will drop the clamp.

> > +
> > +     rate_millihz = mul_u32_u32(req->rate, MILLI);
> > +     if (!rzv2h_dsi_get_pll_parameters_values(priv->dsi_limits,
> > +                                              &dsi_dividers, rate_millihz)) {
> > +             dev_err(priv->dev,
> > +                     "failed to determine rate for req->rate: %lu\n",
> > +                     req->rate);
> > +             return -EINVAL;
> > +     }
> > +
> > +     req->best_parent_rate = req->rate * dsi_dividers.csdiv;
>
> This is wrong as it will lead to high value for  parent as the rate is fixed 24MHz.
>
> 24MHz-> PLL_DSI(This clock) -> DSI DIVIDER-> DoT clock
>
Agreed we cannot adjust the best_parent_rate here.

Cheers,
Prabhakar

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

* Re: [PATCH v6 4/4] drm: renesas: rz-du: mipi_dsi: Add support for RZ/V2H(P) SoC
  2025-06-13  6:17   ` Biju Das
@ 2025-06-16 10:48     ` Lad, Prabhakar
  2025-06-16 10:54       ` Biju Das
  0 siblings, 1 reply; 18+ messages in thread
From: Lad, Prabhakar @ 2025-06-16 10:48 UTC (permalink / raw)
  To: Biju Das
  Cc: Geert Uytterhoeven, Andrzej Hajda, Neil Armstrong, Robert Foss,
	laurent.pinchart, Jonas Karlman, Jernej Skrabec,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Michael Turquette, Stephen Boyd, Magnus Damm,
	dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-renesas-soc@vger.kernel.org,
	linux-clk@vger.kernel.org, Fabrizio Castro, Prabhakar Mahadev Lad

Hi Biju,

Thank you for the review.

On Fri, Jun 13, 2025 at 7:17 AM Biju Das <biju.das.jz@bp.renesas.com> wrote:
>
> Hi Prabhakar,
>
> > -----Original Message-----
> > From: Prabhakar <prabhakar.csengg@gmail.com>
> > Sent: 30 May 2025 18:19
> > Subject: [PATCH v6 4/4] drm: renesas: rz-du: mipi_dsi: Add support for RZ/V2H(P) SoC
> >
> > From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> >
> > Add DSI support for Renesas RZ/V2H(P) SoC.
> >
> > Co-developed-by: Fabrizio Castro <fabrizio.castro.jz@renesas.com>
> > Signed-off-by: Fabrizio Castro <fabrizio.castro.jz@renesas.com>
> > Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> > ---
> > v5->v6:
> > - Made use of GENMASK() macro for PLLCLKSET0R_PLL_*,
> >   PHYTCLKSETR_* and PHYTHSSETR_* macros.
> > - Replaced 10000000UL with 10 * MEGA
> > - Renamed mode_freq_hz to mode_freq_khz in rzv2h_dsi_mode_calc
> > - Replaced `i -= 1;` with `i--;`
> > - Renamed RZV2H_MIPI_DPHY_FOUT_MIN_IN_MEGA to
> >   RZV2H_MIPI_DPHY_FOUT_MIN_IN_MHZ and
> >   RZV2H_MIPI_DPHY_FOUT_MAX_IN_MEGA to
> >   RZV2H_MIPI_DPHY_FOUT_MAX_IN_MHZ.
> >
> > v4->v5:
> > - No changes
> >
> > v3->v4
> > - In rzv2h_dphy_find_ulpsexit() made the array static const.
> >
> > v2->v3:
> > - Simplifed V2H DSI timings array to save space
> > - Switched to use fsleep() instead of udelay()
> >
> > v1->v2:
> > - Dropped unused macros
> > - Added missing LPCLK flag to rzv2h info
> > ---
> >  .../gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c    | 345 ++++++++++++++++++
> >  .../drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h   |  34 ++
> >  2 files changed, 379 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c b/drivers/gpu/drm/renesas/rz-
> > du/rzg2l_mipi_dsi.c
> > index a31f9b6aa920..ea554ced6713 100644
> > --- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
> > +++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
> > @@ -5,6 +5,7 @@
> >   * Copyright (C) 2022 Renesas Electronics Corporation
> >   */
> >  #include <linux/clk.h>
> > +#include <linux/clk/renesas-rzv2h-dsi.h>
> >  #include <linux/delay.h>
> >  #include <linux/io.h>
> >  #include <linux/iopoll.h>
<snip>
> > +
> > +static int rzv2h_dphy_conf_clks(struct rzg2l_mipi_dsi *dsi, unsigned long mode_freq,
> > +                             u64 *hsfreq_millihz)
> > +{
> > +     struct rzv2h_plldsi_parameters *dsi_parameters = &dsi->dsi_parameters;
> > +     unsigned long status;
> > +
> > +     if (dsi->mode_calc.mode_freq_khz != mode_freq) {
> > +             status = rzv2h_dphy_mode_clk_check(dsi, mode_freq);
> > +             if (status != MODE_OK) {
> > +                     dev_err(dsi->dev, "No PLL parameters found for mode clk %lu\n",
> > +                             mode_freq);
> > +                     return -EINVAL;
> > +             }
> > +     }
> > +
> > +     clk_set_rate(dsi->vclk, dsi->mode_calc.mode_freq_hz);
>
> Not sure, Can we use the DSI divider required based on the data rate (vclk, bpp and numlanes) here
>
> and then the set parent clk of PLLDSI as well here (dsi->vclk * the divider value) ??
>
> 24MHZ->PLL DSI->DSI DIVIDER->VCLOCK
>
> Maybe then the clock framework has all the information for setting PLL_DSI and DSI_DIVIDER clks??
>
Can you please elaborate here with a detailed example.

Cheers,
Prabhakar

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

* RE: [PATCH v6 4/4] drm: renesas: rz-du: mipi_dsi: Add support for RZ/V2H(P) SoC
  2025-06-16 10:48     ` Lad, Prabhakar
@ 2025-06-16 10:54       ` Biju Das
  2025-06-16 11:20         ` Lad, Prabhakar
  2025-06-24 15:16         ` Lad, Prabhakar
  0 siblings, 2 replies; 18+ messages in thread
From: Biju Das @ 2025-06-16 10:54 UTC (permalink / raw)
  To: Lad, Prabhakar
  Cc: Geert Uytterhoeven, Andrzej Hajda, Neil Armstrong, Robert Foss,
	laurent.pinchart, Jonas Karlman, Jernej Skrabec,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Michael Turquette, Stephen Boyd, Magnus Damm,
	dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-renesas-soc@vger.kernel.org,
	linux-clk@vger.kernel.org, Fabrizio Castro, Prabhakar Mahadev Lad



> -----Original Message-----
> From: Lad, Prabhakar <prabhakar.csengg@gmail.com>
> Sent: Monday, June 16, 2025 11:48 AM
> To: Biju Das <biju.das.jz@bp.renesas.com>
> Cc: Geert Uytterhoeven <geert+renesas@glider.be>; Andrzej Hajda
> <andrzej.hajda@intel.com>; Neil Armstrong <neil.armstrong@linaro.org>;
> Robert Foss <rfoss@kernel.org>; laurent.pinchart
> <laurent.pinchart@ideasonboard.com>; Jonas Karlman <jonas@kwiboo.se>;
> Jernej Skrabec <jernej.skrabec@gmail.com>; Maarten Lankhorst
> <maarten.lankhorst@linux.intel.com>; Maxime Ripard <mripard@kernel.org>;
> Thomas Zimmermann <tzimmermann@suse.de>; David Airlie <airlied@gmail.com>;
> Simona Vetter <simona@ffwll.ch>; Rob Herring <robh@kernel.org>; Krzysztof
> Kozlowski <krzk+dt@kernel.org>; Conor Dooley <conor+dt@kernel.org>;
> Michael Turquette <mturquette@baylibre.com>; Stephen Boyd
> <sboyd@kernel.org>; Magnus Damm <magnus.damm@gmail.com>; dri-
> devel@lists.freedesktop.org; devicetree@vger.kernel.org; linux-
> kernel@vger.kernel.org; linux-renesas-soc@vger.kernel.org; linux-
> clk@vger.kernel.org; Fabrizio Castro <fabrizio.castro.jz@renesas.com>;
> Prabhakar Mahadev Lad <prabhakar.mahadev-lad.rj@bp.renesas.com>
> Subject: Re: [PATCH v6 4/4] drm: renesas: rz-du: mipi_dsi: Add support for
> RZ/V2H(P) SoC
> 
> Hi Biju,
> 
> Thank you for the review.
> 
> On Fri, Jun 13, 2025 at 7:17 AM Biju Das <biju.das.jz@bp.renesas.com>
> wrote:
> >
> > Hi Prabhakar,
> >
> > > -----Original Message-----
> > > From: Prabhakar <prabhakar.csengg@gmail.com>
> > > Sent: 30 May 2025 18:19
> > > Subject: [PATCH v6 4/4] drm: renesas: rz-du: mipi_dsi: Add support
> > > for RZ/V2H(P) SoC
> > >
> > > From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> > >
> > > Add DSI support for Renesas RZ/V2H(P) SoC.
> > >
> > > Co-developed-by: Fabrizio Castro <fabrizio.castro.jz@renesas.com>
> > > Signed-off-by: Fabrizio Castro <fabrizio.castro.jz@renesas.com>
> > > Signed-off-by: Lad Prabhakar
> > > <prabhakar.mahadev-lad.rj@bp.renesas.com>
> > > ---
> > > v5->v6:
> > > - Made use of GENMASK() macro for PLLCLKSET0R_PLL_*,
> > >   PHYTCLKSETR_* and PHYTHSSETR_* macros.
> > > - Replaced 10000000UL with 10 * MEGA
> > > - Renamed mode_freq_hz to mode_freq_khz in rzv2h_dsi_mode_calc
> > > - Replaced `i -= 1;` with `i--;`
> > > - Renamed RZV2H_MIPI_DPHY_FOUT_MIN_IN_MEGA to
> > >   RZV2H_MIPI_DPHY_FOUT_MIN_IN_MHZ and
> > >   RZV2H_MIPI_DPHY_FOUT_MAX_IN_MEGA to
> > >   RZV2H_MIPI_DPHY_FOUT_MAX_IN_MHZ.
> > >
> > > v4->v5:
> > > - No changes
> > >
> > > v3->v4
> > > - In rzv2h_dphy_find_ulpsexit() made the array static const.
> > >
> > > v2->v3:
> > > - Simplifed V2H DSI timings array to save space
> > > - Switched to use fsleep() instead of udelay()
> > >
> > > v1->v2:
> > > - Dropped unused macros
> > > - Added missing LPCLK flag to rzv2h info
> > > ---
> > >  .../gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c    | 345
> ++++++++++++++++++
> > >  .../drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h   |  34 ++
> > >  2 files changed, 379 insertions(+)
> > >
> > > diff --git a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
> > > b/drivers/gpu/drm/renesas/rz- du/rzg2l_mipi_dsi.c index
> > > a31f9b6aa920..ea554ced6713 100644
> > > --- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
> > > +++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
> > > @@ -5,6 +5,7 @@
> > >   * Copyright (C) 2022 Renesas Electronics Corporation
> > >   */
> > >  #include <linux/clk.h>
> > > +#include <linux/clk/renesas-rzv2h-dsi.h>
> > >  #include <linux/delay.h>
> > >  #include <linux/io.h>
> > >  #include <linux/iopoll.h>
> <snip>
> > > +
> > > +static int rzv2h_dphy_conf_clks(struct rzg2l_mipi_dsi *dsi, unsigned
> long mode_freq,
> > > +                             u64 *hsfreq_millihz) {
> > > +     struct rzv2h_plldsi_parameters *dsi_parameters = &dsi-
> >dsi_parameters;
> > > +     unsigned long status;
> > > +
> > > +     if (dsi->mode_calc.mode_freq_khz != mode_freq) {
> > > +             status = rzv2h_dphy_mode_clk_check(dsi, mode_freq);
> > > +             if (status != MODE_OK) {
> > > +                     dev_err(dsi->dev, "No PLL parameters found for
> mode clk %lu\n",
> > > +                             mode_freq);
> > > +                     return -EINVAL;
> > > +             }
> > > +     }
> > > +
> > > +     clk_set_rate(dsi->vclk, dsi->mode_calc.mode_freq_hz);
> >
> > Not sure, Can we use the DSI divider required based on the data rate
> > (vclk, bpp and numlanes) here
> >
> > and then the set parent clk of PLLDSI as well here (dsi->vclk * the
> divider value) ??
> >
> > 24MHZ->PLL DSI->DSI DIVIDER->VCLOCK
> >
> > Maybe then the clock framework has all the information for setting
> PLL_DSI and DSI_DIVIDER clks??
> >
> Can you please elaborate here with a detailed example.

There will be determine_clk followed by set_clock for setting new rate for PLL DSI(dsi->vclk * the divider value)
For eg:  vclk_max = 187.5 MHz, DSI Divider required = 16
Then set PLL_DSI = 187.5 * 16 MHz using clk_set.

Cheers,
Biju


> 
> Cheers,
> Prabhakar

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

* Re: [PATCH v6 4/4] drm: renesas: rz-du: mipi_dsi: Add support for RZ/V2H(P) SoC
  2025-06-16 10:54       ` Biju Das
@ 2025-06-16 11:20         ` Lad, Prabhakar
  2025-06-18 14:19           ` Biju Das
  2025-06-24 15:16         ` Lad, Prabhakar
  1 sibling, 1 reply; 18+ messages in thread
From: Lad, Prabhakar @ 2025-06-16 11:20 UTC (permalink / raw)
  To: Biju Das
  Cc: Geert Uytterhoeven, Andrzej Hajda, Neil Armstrong, Robert Foss,
	laurent.pinchart, Jonas Karlman, Jernej Skrabec,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Michael Turquette, Stephen Boyd, Magnus Damm,
	dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-renesas-soc@vger.kernel.org,
	linux-clk@vger.kernel.org, Fabrizio Castro, Prabhakar Mahadev Lad

Hi Biju,

On Mon, Jun 16, 2025 at 11:54 AM Biju Das <biju.das.jz@bp.renesas.com> wrote:
>
>
>
> > -----Original Message-----
> > From: Lad, Prabhakar <prabhakar.csengg@gmail.com>
> > Sent: Monday, June 16, 2025 11:48 AM
> > To: Biju Das <biju.das.jz@bp.renesas.com>
> > Cc: Geert Uytterhoeven <geert+renesas@glider.be>; Andrzej Hajda
> > <andrzej.hajda@intel.com>; Neil Armstrong <neil.armstrong@linaro.org>;
> > Robert Foss <rfoss@kernel.org>; laurent.pinchart
> > <laurent.pinchart@ideasonboard.com>; Jonas Karlman <jonas@kwiboo.se>;
> > Jernej Skrabec <jernej.skrabec@gmail.com>; Maarten Lankhorst
> > <maarten.lankhorst@linux.intel.com>; Maxime Ripard <mripard@kernel.org>;
> > Thomas Zimmermann <tzimmermann@suse.de>; David Airlie <airlied@gmail.com>;
> > Simona Vetter <simona@ffwll.ch>; Rob Herring <robh@kernel.org>; Krzysztof
> > Kozlowski <krzk+dt@kernel.org>; Conor Dooley <conor+dt@kernel.org>;
> > Michael Turquette <mturquette@baylibre.com>; Stephen Boyd
> > <sboyd@kernel.org>; Magnus Damm <magnus.damm@gmail.com>; dri-
> > devel@lists.freedesktop.org; devicetree@vger.kernel.org; linux-
> > kernel@vger.kernel.org; linux-renesas-soc@vger.kernel.org; linux-
> > clk@vger.kernel.org; Fabrizio Castro <fabrizio.castro.jz@renesas.com>;
> > Prabhakar Mahadev Lad <prabhakar.mahadev-lad.rj@bp.renesas.com>
> > Subject: Re: [PATCH v6 4/4] drm: renesas: rz-du: mipi_dsi: Add support for
> > RZ/V2H(P) SoC
> >
> > Hi Biju,
> >
> > Thank you for the review.
> >
> > On Fri, Jun 13, 2025 at 7:17 AM Biju Das <biju.das.jz@bp.renesas.com>
> > wrote:
> > >
> > > Hi Prabhakar,
> > >
> > > > -----Original Message-----
> > > > From: Prabhakar <prabhakar.csengg@gmail.com>
> > > > Sent: 30 May 2025 18:19
> > > > Subject: [PATCH v6 4/4] drm: renesas: rz-du: mipi_dsi: Add support
> > > > for RZ/V2H(P) SoC
> > > >
> > > > From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> > > >
> > > > Add DSI support for Renesas RZ/V2H(P) SoC.
> > > >
> > > > Co-developed-by: Fabrizio Castro <fabrizio.castro.jz@renesas.com>
> > > > Signed-off-by: Fabrizio Castro <fabrizio.castro.jz@renesas.com>
> > > > Signed-off-by: Lad Prabhakar
> > > > <prabhakar.mahadev-lad.rj@bp.renesas.com>
> > > > ---
> > > > v5->v6:
> > > > - Made use of GENMASK() macro for PLLCLKSET0R_PLL_*,
> > > >   PHYTCLKSETR_* and PHYTHSSETR_* macros.
> > > > - Replaced 10000000UL with 10 * MEGA
> > > > - Renamed mode_freq_hz to mode_freq_khz in rzv2h_dsi_mode_calc
> > > > - Replaced `i -= 1;` with `i--;`
> > > > - Renamed RZV2H_MIPI_DPHY_FOUT_MIN_IN_MEGA to
> > > >   RZV2H_MIPI_DPHY_FOUT_MIN_IN_MHZ and
> > > >   RZV2H_MIPI_DPHY_FOUT_MAX_IN_MEGA to
> > > >   RZV2H_MIPI_DPHY_FOUT_MAX_IN_MHZ.
> > > >
> > > > v4->v5:
> > > > - No changes
> > > >
> > > > v3->v4
> > > > - In rzv2h_dphy_find_ulpsexit() made the array static const.
> > > >
> > > > v2->v3:
> > > > - Simplifed V2H DSI timings array to save space
> > > > - Switched to use fsleep() instead of udelay()
> > > >
> > > > v1->v2:
> > > > - Dropped unused macros
> > > > - Added missing LPCLK flag to rzv2h info
> > > > ---
> > > >  .../gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c    | 345
> > ++++++++++++++++++
> > > >  .../drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h   |  34 ++
> > > >  2 files changed, 379 insertions(+)
> > > >
> > > > diff --git a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
> > > > b/drivers/gpu/drm/renesas/rz- du/rzg2l_mipi_dsi.c index
> > > > a31f9b6aa920..ea554ced6713 100644
> > > > --- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
> > > > +++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
> > > > @@ -5,6 +5,7 @@
> > > >   * Copyright (C) 2022 Renesas Electronics Corporation
> > > >   */
> > > >  #include <linux/clk.h>
> > > > +#include <linux/clk/renesas-rzv2h-dsi.h>
> > > >  #include <linux/delay.h>
> > > >  #include <linux/io.h>
> > > >  #include <linux/iopoll.h>
> > <snip>
> > > > +
> > > > +static int rzv2h_dphy_conf_clks(struct rzg2l_mipi_dsi *dsi, unsigned
> > long mode_freq,
> > > > +                             u64 *hsfreq_millihz) {
> > > > +     struct rzv2h_plldsi_parameters *dsi_parameters = &dsi-
> > >dsi_parameters;
> > > > +     unsigned long status;
> > > > +
> > > > +     if (dsi->mode_calc.mode_freq_khz != mode_freq) {
> > > > +             status = rzv2h_dphy_mode_clk_check(dsi, mode_freq);
> > > > +             if (status != MODE_OK) {
> > > > +                     dev_err(dsi->dev, "No PLL parameters found for
> > mode clk %lu\n",
> > > > +                             mode_freq);
> > > > +                     return -EINVAL;
> > > > +             }
> > > > +     }
> > > > +
> > > > +     clk_set_rate(dsi->vclk, dsi->mode_calc.mode_freq_hz);
> > >
> > > Not sure, Can we use the DSI divider required based on the data rate
> > > (vclk, bpp and numlanes) here
> > >
> > > and then the set parent clk of PLLDSI as well here (dsi->vclk * the
> > divider value) ??
> > >
> > > 24MHZ->PLL DSI->DSI DIVIDER->VCLOCK
> > >
> > > Maybe then the clock framework has all the information for setting
> > PLL_DSI and DSI_DIVIDER clks??
> > >
> > Can you please elaborate here with a detailed example.
>
> There will be determine_clk followed by set_clock for setting new rate for PLL DSI(dsi->vclk * the divider value)
> For eg:  vclk_max = 187.5 MHz, DSI Divider required = 16
> Then set PLL_DSI = 187.5 * 16 MHz using clk_set.
>
You mean to use `clk_set_rate(dsi->vclk, (clk_get_rate(dsi->vclk) *
dsi_divider));` ?

Cheers,
Prabhakar

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

* RE: [PATCH v6 1/4] clk: renesas: rzv2h-cpg: Add support for DSI clocks
  2025-06-16 10:44     ` Lad, Prabhakar
@ 2025-06-18 13:25       ` Biju Das
  2025-06-19  5:05         ` Biju Das
  0 siblings, 1 reply; 18+ messages in thread
From: Biju Das @ 2025-06-18 13:25 UTC (permalink / raw)
  To: Lad, Prabhakar
  Cc: Geert Uytterhoeven, Andrzej Hajda, Neil Armstrong, Robert Foss,
	laurent.pinchart, Jonas Karlman, Jernej Skrabec,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Michael Turquette, Stephen Boyd, Magnus Damm,
	dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-renesas-soc@vger.kernel.org,
	linux-clk@vger.kernel.org, Fabrizio Castro, Prabhakar Mahadev Lad

Hi Prabhakar,

> -----Original Message-----
> From: dri-devel <dri-devel-bounces@lists.freedesktop.org> On Behalf Of Lad, Prabhakar
> Sent: 16 June 2025 11:45
> Subject: Re: [PATCH v6 1/4] clk: renesas: rzv2h-cpg: Add support for DSI clocks
> 
> Hi Biju,
> 
> Thank you for the review.
> 
> On Fri, Jun 13, 2025 at 6:57 AM Biju Das <biju.das.jz@bp.renesas.com> wrote:
> >
> > Hi Prabhakar,
> >
> > > -----Original Message-----
> > > From: Prabhakar <prabhakar.csengg@gmail.com>
> > > Sent: 30 May 2025 18:19
> > .castro.jz@renesas.com>; Prabhakar Mahadev Lad <prabhakar.mahadev-
> > > lad.rj@bp.renesas.com>
> > > Subject: [PATCH v6 1/4] clk: renesas: rzv2h-cpg: Add support for DSI
> > > clocks
> > >
> > > From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> > >
> > > Add support for PLLDSI and PLLDSI divider clocks.
> > >
> > > Introduce the `renesas-rzv2h-dsi.h` header to centralize and share
> > > PLLDSI-related data structures, limits, and algorithms between the RZ/V2H CPG and DSI drivers.
> > >
> > > The DSI PLL is functionally similar to the CPG's PLLDSI, but has
> > > slightly different parameter limits and omits the programmable
> > > divider present in CPG. To ensure precise frequency
> > > calculations-especially for milliHz-level accuracy needed by the DSI driver-the shared algorithm
> allows both drivers to compute PLL parameters consistently using the same logic and input clock.
> > >
> > > Co-developed-by: Fabrizio Castro <fabrizio.castro.jz@renesas.com>
> > > Signed-off-by: Fabrizio Castro <fabrizio.castro.jz@renesas.com>
> > > Signed-off-by: Lad Prabhakar
> > > <prabhakar.mahadev-lad.rj@bp.renesas.com>
> > > ---
> > > v5->v6:
> > > - Renamed CPG_PLL_STBY_SSCGEN_WEN to CPG_PLL_STBY_SSC_EN_WEN
> > > - Updated CPG_PLL_CLK1_DIV_K, CPG_PLL_CLK1_DIV_M, and
> > >   CPG_PLL_CLK1_DIV_P macros to use GENMASK
> > > - Updated req->rate in rzv2h_cpg_plldsi_div_determine_rate()
> > > - Dropped the cast in rzv2h_cpg_plldsi_div_set_rate()
> > > - Dropped rzv2h_cpg_plldsi_round_rate() and implemented
> > >   rzv2h_cpg_plldsi_determine_rate() instead
> > > - Made use of FIELD_PREP()
> > > - Moved CPG_CSDIV1 macro in patch 2/4
> > > - Dropped two_pow_s in rzv2h_dsi_get_pll_parameters_values()
> > > - Used mul_u32_u32() while calculating output_m and output_k_range
> > > - Used div_s64() instead of div64_s64() while calculating
> > >   pll_k
> > > - Used mul_u32_u32() while calculating fvco and fvco checks
> > > - Rounded the final output using DIV_U64_ROUND_CLOSEST()
> > >
> > > v4->v5:
> > > - No changes
> > >
> > > v3->v4:
> > > - Corrected parameter name in rzv2h_dsi_get_pll_parameters_values()
> > >   description freq_millihz
> > >
> > > v2->v3:
> > > - Update the commit message to clarify the purpose of `renesas-rzv2h-dsi.h`
> > >   header
> > > - Used mul_u32_u32() in rzv2h_cpg_plldsi_div_determine_rate()
> > > - Replaced *_mhz to *_millihz for clarity
> > > - Updated u64->u32 for fvco limits
> > > - Initialized the members in declaration order for
> > >   RZV2H_CPG_PLL_DSI_LIMITS() macro
> > > - Used clk_div_mask() in rzv2h_cpg_plldsi_div_recalc_rate()
> > > - Replaced `unsigned long long` with u64
> > > - Dropped rzv2h_cpg_plldsi_clk_recalc_rate() and reused
> > >   rzv2h_cpg_pll_clk_recalc_rate() instead
> > > - In rzv2h_cpg_plldsi_div_set_rate() followed the same style
> > >   of RMW-operation as done in the other functions
> > > - Renamed rzv2h_cpg_plldsi_set_rate() to rzv2h_cpg_pll_set_rate()
> > > - Dropped rzv2h_cpg_plldsi_clk_register() and reused
> > >   rzv2h_cpg_pll_clk_register() instead
> > > - Added a gaurd in renesas-rzv2h-dsi.h header
> > >
> > > v1->v2:
> > > - No changes
> > > ---
> > >  drivers/clk/renesas/rzv2h-cpg.c       | 278 +++++++++++++++++++++++++-
> > >  drivers/clk/renesas/rzv2h-cpg.h       |  13 ++
> > >  include/linux/clk/renesas-rzv2h-dsi.h | 210 +++++++++++++++++++
> > >  3 files changed, 492 insertions(+), 9 deletions(-)  create mode
> > > 100644 include/linux/clk/renesas- rzv2h-dsi.h
> > >
> > > diff --git a/drivers/clk/renesas/rzv2h-cpg.c
> > > b/drivers/clk/renesas/rzv2h-cpg.c index
> > > 761da3bf77ce..d590f9f47371 100644
> > > --- a/drivers/clk/renesas/rzv2h-cpg.c
> > > +++ b/drivers/clk/renesas/rzv2h-cpg.c
> > > @@ -14,9 +14,13 @@
> > >  #include <linux/bitfield.h>
> > >  #include <linux/clk.h>
> > >  #include <linux/clk-provider.h>
> > > +#include <linux/clk/renesas-rzv2h-dsi.h>
> > >  #include <linux/delay.h>
> > >  #include <linux/init.h>
> > >  #include <linux/iopoll.h>
> > > +#include <linux/math.h>
> >
> >
> >
> > > +     req->rate = DIV_ROUND_CLOSEST_ULL(dsi_dividers->freq_millihz,
> > > + MILLI);
> > > +
> > > +     return 0;
> > > +};
> > > +
> > > +static int rzv2h_cpg_plldsi_div_set_rate(struct clk_hw *hw,
> > > +                                      unsigned long rate,
> > > +                                      unsigned long parent_rate) {
> > > +     struct rzv2h_plldsi_div_clk *dsi_div = to_plldsi_div_clk(hw);
> > > +     struct rzv2h_cpg_priv *priv = dsi_div->priv;
> > > +     struct rzv2h_plldsi_parameters *dsi_dividers = &priv->plldsi_div_parameters;
> > > +     struct ddiv ddiv = dsi_div->ddiv;
> > > +     const struct clk_div_table *clkt;
> > > +     bool div_found = false;
> > > +     u32 val, shift, div;
> > > +
> > > +     div = dsi_dividers->csdiv;
> > > +     for (clkt = dsi_div->dtable; clkt->div; clkt++) {
> > > +             if (clkt->div == div) {
> > > +                     div_found = true;
> > > +                     break;
> > > +             }
> > > +     }
> > > +
> > > +     if (!div_found)
> > > +             return -EINVAL;
> >
> > This check can be done in determine rate and cache the divider??
> >
> Ok, I'll drop this check as the divider is already cached. The for loop above is to determine the val
> which is used below to program the registers.

If you are caching actual divider value, then the check is not required here.
Otherwise the above code is fine.

Assume the csdiv you found, have no corresponding match in the table.

Cheers,
Biju

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

* RE: [PATCH v6 4/4] drm: renesas: rz-du: mipi_dsi: Add support for RZ/V2H(P) SoC
  2025-06-16 11:20         ` Lad, Prabhakar
@ 2025-06-18 14:19           ` Biju Das
  0 siblings, 0 replies; 18+ messages in thread
From: Biju Das @ 2025-06-18 14:19 UTC (permalink / raw)
  To: Lad, Prabhakar
  Cc: Geert Uytterhoeven, Andrzej Hajda, Neil Armstrong, Robert Foss,
	laurent.pinchart, Jonas Karlman, Jernej Skrabec,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Michael Turquette, Stephen Boyd, Magnus Damm,
	dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-renesas-soc@vger.kernel.org,
	linux-clk@vger.kernel.org, Fabrizio Castro, Prabhakar Mahadev Lad

Hi Prabhakar,

> -----Original Message-----
> From: dri-devel <dri-devel-bounces@lists.freedesktop.org> On Behalf Of Lad, Prabhakar
> Sent: 16 June 2025 12:21
> Subject: Re: [PATCH v6 4/4] drm: renesas: rz-du: mipi_dsi: Add support for RZ/V2H(P) SoC
> 
> Hi Biju,
> 
> On Mon, Jun 16, 2025 at 11:54 AM Biju Das <biju.das.jz@bp.renesas.com> wrote:
> >
> >
> >
> > > -----Original Message-----
> > > From: Lad, Prabhakar <prabhakar.csengg@gmail.com>
> > > Sent: Monday, June 16, 2025 11:48 AM
> > > To: Biju Das <biju.das.jz@bp.renesas.com>
> > > Cc: Geert Uytterhoeven <geert+renesas@glider.be>; Andrzej Hajda
> > > <andrzej.hajda@intel.com>; Neil Armstrong
> > > <neil.armstrong@linaro.org>; Robert Foss <rfoss@kernel.org>;
> > > laurent.pinchart <laurent.pinchart@ideasonboard.com>; Jonas Karlman
> > > <jonas@kwiboo.se>; Jernej Skrabec <jernej.skrabec@gmail.com>;
> > > Maarten Lankhorst <maarten.lankhorst@linux.intel.com>; Maxime Ripard
> > > <mripard@kernel.org>; Thomas Zimmermann <tzimmermann@suse.de>; David
> > > Airlie <airlied@gmail.com>; Simona Vetter <simona@ffwll.ch>; Rob
> > > Herring <robh@kernel.org>; Krzysztof Kozlowski <krzk+dt@kernel.org>;
> > > Conor Dooley <conor+dt@kernel.org>; Michael Turquette
> > > <mturquette@baylibre.com>; Stephen Boyd <sboyd@kernel.org>; Magnus
> > > Damm <magnus.damm@gmail.com>; dri- devel@lists.freedesktop.org;
> > > devicetree@vger.kernel.org; linux- kernel@vger.kernel.org;
> > > linux-renesas-soc@vger.kernel.org; linux- clk@vger.kernel.org;
> > > Fabrizio Castro <fabrizio.castro.jz@renesas.com>; Prabhakar Mahadev
> > > Lad <prabhakar.mahadev-lad.rj@bp.renesas.com>
> > > Subject: Re: [PATCH v6 4/4] drm: renesas: rz-du: mipi_dsi: Add
> > > support for
> > > RZ/V2H(P) SoC
> > >
> > > Hi Biju,
> > >
> > > Thank you for the review.
> > >
> > > On Fri, Jun 13, 2025 at 7:17 AM Biju Das
> > > <biju.das.jz@bp.renesas.com>
> > > wrote:
> > > >
> > > > Hi Prabhakar,
> > > >
> > > > > -----Original Message-----
> > > > > From: Prabhakar <prabhakar.csengg@gmail.com>
> > > > > Sent: 30 May 2025 18:19
> > > > > Subject: [PATCH v6 4/4] drm: renesas: rz-du: mipi_dsi: Add
> > > > > support for RZ/V2H(P) SoC
> > > > >
> > > > > From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> > > > >
> > > > > Add DSI support for Renesas RZ/V2H(P) SoC.
> > > > >
> > > > > Co-developed-by: Fabrizio Castro
> > > > > <fabrizio.castro.jz@renesas.com>
> > > > > Signed-off-by: Fabrizio Castro <fabrizio.castro.jz@renesas.com>
> > > > > Signed-off-by: Lad Prabhakar
> > > > > <prabhakar.mahadev-lad.rj@bp.renesas.com>
> > > > > ---
> > > > > v5->v6:
> > > > > - Made use of GENMASK() macro for PLLCLKSET0R_PLL_*,
> > > > >   PHYTCLKSETR_* and PHYTHSSETR_* macros.
> > > > > - Replaced 10000000UL with 10 * MEGA
> > > > > - Renamed mode_freq_hz to mode_freq_khz in rzv2h_dsi_mode_calc
> > > > > - Replaced `i -= 1;` with `i--;`
> > > > > - Renamed RZV2H_MIPI_DPHY_FOUT_MIN_IN_MEGA to
> > > > >   RZV2H_MIPI_DPHY_FOUT_MIN_IN_MHZ and
> > > > >   RZV2H_MIPI_DPHY_FOUT_MAX_IN_MEGA to
> > > > >   RZV2H_MIPI_DPHY_FOUT_MAX_IN_MHZ.
> > > > >
> > > > > v4->v5:
> > > > > - No changes
> > > > >
> > > > > v3->v4
> > > > > - In rzv2h_dphy_find_ulpsexit() made the array static const.
> > > > >
> > > > > v2->v3:
> > > > > - Simplifed V2H DSI timings array to save space
> > > > > - Switched to use fsleep() instead of udelay()
> > > > >
> > > > > v1->v2:
> > > > > - Dropped unused macros
> > > > > - Added missing LPCLK flag to rzv2h info
> > > > > ---
> > > > >  .../gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c    | 345
> > > ++++++++++++++++++
> > > > >  .../drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h   |  34 ++
> > > > >  2 files changed, 379 insertions(+)
> > > > >
> > > > > diff --git a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
> > > > > b/drivers/gpu/drm/renesas/rz- du/rzg2l_mipi_dsi.c index
> > > > > a31f9b6aa920..ea554ced6713 100644
> > > > > --- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
> > > > > +++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
> > > > > @@ -5,6 +5,7 @@
> > > > >   * Copyright (C) 2022 Renesas Electronics Corporation
> > > > >   */
> > > > >  #include <linux/clk.h>
> > > > > +#include <linux/clk/renesas-rzv2h-dsi.h>
> > > > >  #include <linux/delay.h>
> > > > >  #include <linux/io.h>
> > > > >  #include <linux/iopoll.h>
> > > <snip>
> > > > > +
> > > > > +static int rzv2h_dphy_conf_clks(struct rzg2l_mipi_dsi *dsi,
> > > > > +unsigned
> > > long mode_freq,
> > > > > +                             u64 *hsfreq_millihz) {
> > > > > +     struct rzv2h_plldsi_parameters *dsi_parameters = &dsi-
> > > >dsi_parameters;
> > > > > +     unsigned long status;
> > > > > +
> > > > > +     if (dsi->mode_calc.mode_freq_khz != mode_freq) {
> > > > > +             status = rzv2h_dphy_mode_clk_check(dsi, mode_freq);
> > > > > +             if (status != MODE_OK) {
> > > > > +                     dev_err(dsi->dev, "No PLL parameters found
> > > > > + for
> > > mode clk %lu\n",
> > > > > +                             mode_freq);
> > > > > +                     return -EINVAL;
> > > > > +             }
> > > > > +     }
> > > > > +
> > > > > +     clk_set_rate(dsi->vclk, dsi->mode_calc.mode_freq_hz);
> > > >
> > > > Not sure, Can we use the DSI divider required based on the data
> > > > rate (vclk, bpp and numlanes) here
> > > >
> > > > and then the set parent clk of PLLDSI as well here (dsi->vclk *
> > > > the
> > > divider value) ??
> > > >
> > > > 24MHZ->PLL DSI->DSI DIVIDER->VCLOCK
> > > >
> > > > Maybe then the clock framework has all the information for setting
> > > PLL_DSI and DSI_DIVIDER clks??
> > > >
> > > Can you please elaborate here with a detailed example.
> >
> > There will be determine_clk followed by set_clock for setting new rate
> > for PLL DSI(dsi->vclk * the divider value) For eg:  vclk_max = 187.5
> > MHz, DSI Divider required = 16 Then set PLL_DSI = 187.5 * 16 MHz using clk_set.
> >
> You mean to use `clk_set_rate(dsi->vclk, (clk_get_rate(dsi->vclk) * dsi_divider));` ?

What I meant is
dsi_div_clk = clk_get_parent(dsi->vclk);
pll_dsi_clk = clk_get_parent(dsi_div_clk);

clk_set_rate(pll_dsi_clk, dsi->mode_calc.mode_freq_hz * dsi_divider));`
clk_set_rate(dsi->vclk, dsi->mode_calc.mode_freq_hz);

With this you will get, divider/pll  required in dsi_divider_clk and pll_dsi_clk??

Cheers,
Biju

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

* RE: [PATCH v6 1/4] clk: renesas: rzv2h-cpg: Add support for DSI clocks
  2025-06-18 13:25       ` Biju Das
@ 2025-06-19  5:05         ` Biju Das
  2025-06-24 15:21           ` Lad, Prabhakar
  0 siblings, 1 reply; 18+ messages in thread
From: Biju Das @ 2025-06-19  5:05 UTC (permalink / raw)
  To: Lad, Prabhakar
  Cc: Geert Uytterhoeven, Andrzej Hajda, Neil Armstrong, Robert Foss,
	laurent.pinchart, Jonas Karlman, Jernej Skrabec,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Michael Turquette, Stephen Boyd, Magnus Damm,
	dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-renesas-soc@vger.kernel.org,
	linux-clk@vger.kernel.org, Fabrizio Castro, Prabhakar Mahadev Lad

Hi Prabhakar,

> -----Original Message-----
> From: Biju Das
> Sent: 18 June 2025 14:26
> Subject: RE: [PATCH v6 1/4] clk: renesas: rzv2h-cpg: Add support for DSI clocks
> 
> Hi Prabhakar,
> 
> > -----Original Message-----
> > From: dri-devel <dri-devel-bounces@lists.freedesktop.org> On Behalf Of
> > Lad, Prabhakar
> > Sent: 16 June 2025 11:45
> > Subject: Re: [PATCH v6 1/4] clk: renesas: rzv2h-cpg: Add support for
> > DSI clocks
> >
> > Hi Biju,
> >
> > Thank you for the review.
> >
> > On Fri, Jun 13, 2025 at 6:57 AM Biju Das <biju.das.jz@bp.renesas.com> wrote:
> > >
> > > Hi Prabhakar,
> > >
> > > > -----Original Message-----
> > > > From: Prabhakar <prabhakar.csengg@gmail.com>
> > > > Sent: 30 May 2025 18:19
> > > .castro.jz@renesas.com>; Prabhakar Mahadev Lad <prabhakar.mahadev-
> > > > lad.rj@bp.renesas.com>
> > > > Subject: [PATCH v6 1/4] clk: renesas: rzv2h-cpg: Add support for
> > > > DSI clocks
> > > >
> > > > From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> > > >
> > > > Add support for PLLDSI and PLLDSI divider clocks.
> > > >
> > > > Introduce the `renesas-rzv2h-dsi.h` header to centralize and share
> > > > PLLDSI-related data structures, limits, and algorithms between the RZ/V2H CPG and DSI drivers.
> > > >
> > > > The DSI PLL is functionally similar to the CPG's PLLDSI, but has
> > > > slightly different parameter limits and omits the programmable
> > > > divider present in CPG. To ensure precise frequency
> > > > calculations-especially for milliHz-level accuracy needed by the
> > > > DSI driver-the shared algorithm
> > allows both drivers to compute PLL parameters consistently using the same logic and input clock.
> > > >
> > > > Co-developed-by: Fabrizio Castro <fabrizio.castro.jz@renesas.com>
> > > > Signed-off-by: Fabrizio Castro <fabrizio.castro.jz@renesas.com>
> > > > Signed-off-by: Lad Prabhakar
> > > > <prabhakar.mahadev-lad.rj@bp.renesas.com>
> > > > ---
> > > > v5->v6:
> > > > - Renamed CPG_PLL_STBY_SSCGEN_WEN to CPG_PLL_STBY_SSC_EN_WEN
> > > > - Updated CPG_PLL_CLK1_DIV_K, CPG_PLL_CLK1_DIV_M, and
> > > >   CPG_PLL_CLK1_DIV_P macros to use GENMASK
> > > > - Updated req->rate in rzv2h_cpg_plldsi_div_determine_rate()
> > > > - Dropped the cast in rzv2h_cpg_plldsi_div_set_rate()
> > > > - Dropped rzv2h_cpg_plldsi_round_rate() and implemented
> > > >   rzv2h_cpg_plldsi_determine_rate() instead
> > > > - Made use of FIELD_PREP()
> > > > - Moved CPG_CSDIV1 macro in patch 2/4
> > > > - Dropped two_pow_s in rzv2h_dsi_get_pll_parameters_values()
> > > > - Used mul_u32_u32() while calculating output_m and output_k_range
> > > > - Used div_s64() instead of div64_s64() while calculating
> > > >   pll_k
> > > > - Used mul_u32_u32() while calculating fvco and fvco checks
> > > > - Rounded the final output using DIV_U64_ROUND_CLOSEST()
> > > >
> > > > v4->v5:
> > > > - No changes
> > > >
> > > > v3->v4:
> > > > - Corrected parameter name in rzv2h_dsi_get_pll_parameters_values()
> > > >   description freq_millihz
> > > >
> > > > v2->v3:
> > > > - Update the commit message to clarify the purpose of `renesas-rzv2h-dsi.h`
> > > >   header
> > > > - Used mul_u32_u32() in rzv2h_cpg_plldsi_div_determine_rate()
> > > > - Replaced *_mhz to *_millihz for clarity
> > > > - Updated u64->u32 for fvco limits
> > > > - Initialized the members in declaration order for
> > > >   RZV2H_CPG_PLL_DSI_LIMITS() macro
> > > > - Used clk_div_mask() in rzv2h_cpg_plldsi_div_recalc_rate()
> > > > - Replaced `unsigned long long` with u64
> > > > - Dropped rzv2h_cpg_plldsi_clk_recalc_rate() and reused
> > > >   rzv2h_cpg_pll_clk_recalc_rate() instead
> > > > - In rzv2h_cpg_plldsi_div_set_rate() followed the same style
> > > >   of RMW-operation as done in the other functions
> > > > - Renamed rzv2h_cpg_plldsi_set_rate() to rzv2h_cpg_pll_set_rate()
> > > > - Dropped rzv2h_cpg_plldsi_clk_register() and reused
> > > >   rzv2h_cpg_pll_clk_register() instead
> > > > - Added a gaurd in renesas-rzv2h-dsi.h header
> > > >
> > > > v1->v2:
> > > > - No changes
> > > > ---
> > > >  drivers/clk/renesas/rzv2h-cpg.c       | 278 +++++++++++++++++++++++++-
> > > >  drivers/clk/renesas/rzv2h-cpg.h       |  13 ++
> > > >  include/linux/clk/renesas-rzv2h-dsi.h | 210 +++++++++++++++++++
> > > >  3 files changed, 492 insertions(+), 9 deletions(-)  create mode
> > > > 100644 include/linux/clk/renesas- rzv2h-dsi.h
> > > >
> > > > diff --git a/drivers/clk/renesas/rzv2h-cpg.c
> > > > b/drivers/clk/renesas/rzv2h-cpg.c index
> > > > 761da3bf77ce..d590f9f47371 100644
> > > > --- a/drivers/clk/renesas/rzv2h-cpg.c
> > > > +++ b/drivers/clk/renesas/rzv2h-cpg.c
> > > > @@ -14,9 +14,13 @@
> > > >  #include <linux/bitfield.h>
> > > >  #include <linux/clk.h>
> > > >  #include <linux/clk-provider.h>
> > > > +#include <linux/clk/renesas-rzv2h-dsi.h>
> > > >  #include <linux/delay.h>
> > > >  #include <linux/init.h>
> > > >  #include <linux/iopoll.h>
> > > > +#include <linux/math.h>
> > >
> > >
> > >
> > > > +     req->rate =
> > > > + DIV_ROUND_CLOSEST_ULL(dsi_dividers->freq_millihz,
> > > > + MILLI);
> > > > +
> > > > +     return 0;
> > > > +};
> > > > +
> > > > +static int rzv2h_cpg_plldsi_div_set_rate(struct clk_hw *hw,
> > > > +                                      unsigned long rate,
> > > > +                                      unsigned long parent_rate) {
> > > > +     struct rzv2h_plldsi_div_clk *dsi_div = to_plldsi_div_clk(hw);
> > > > +     struct rzv2h_cpg_priv *priv = dsi_div->priv;
> > > > +     struct rzv2h_plldsi_parameters *dsi_dividers = &priv->plldsi_div_parameters;
> > > > +     struct ddiv ddiv = dsi_div->ddiv;
> > > > +     const struct clk_div_table *clkt;
> > > > +     bool div_found = false;
> > > > +     u32 val, shift, div;
> > > > +
> > > > +     div = dsi_dividers->csdiv;
> > > > +     for (clkt = dsi_div->dtable; clkt->div; clkt++) {
> > > > +             if (clkt->div == div) {
> > > > +                     div_found = true;
> > > > +                     break;
> > > > +             }
> > > > +     }
> > > > +
> > > > +     if (!div_found)
> > > > +             return -EINVAL;
> > >
> > > This check can be done in determine rate and cache the divider??
> > >
> > Ok, I'll drop this check as the divider is already cached. The for
> > loop above is to determine the val which is used below to program the registers.
> 
> If you are caching actual divider value, then the check is not required here.
> Otherwise the above code is fine.
> 
> Assume the csdiv you found, have no corresponding match in the table.


1) By looking at RZ/G3E, can we make this code more scalable?

RZ/G3E has 2 PLL-DSI's
PLL-DSI1 supports DUAL LVDS, Single LVDS and DSI
PLL-DSI2 supports single LVDS,  DPI and DSI

In total there will be 4 limit tables (DSI, single LVDS, Dual LVDS and DPI)

Based on the display output, each PLL needs to pick the appropriate limit table
to compute PLL parameters.

2) Can we drop DSI divider limits from the limit table and use the values from dsi divider table
   itself which is passed in DEF_PLLDSI_DIV?

Note:

LVDS does not use DSI dividers as it is connected to a Mux and always has fixed Divider 7.

DPI uses the DSI divider without any constraints like DSI

Video clock and DSI HS Byte clock must follow the relationship.
Video clock Frequency [Hz] × Video Pixel Bit Depth [bit]
<= DSI HS Byte clock Frequency [Hz] × 8 [bit] × Number of DSI HS Data Lane


Cheers,
Biju




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

* Re: [PATCH v6 4/4] drm: renesas: rz-du: mipi_dsi: Add support for RZ/V2H(P) SoC
  2025-06-16 10:54       ` Biju Das
  2025-06-16 11:20         ` Lad, Prabhakar
@ 2025-06-24 15:16         ` Lad, Prabhakar
  2025-06-25 11:42           ` Biju Das
  1 sibling, 1 reply; 18+ messages in thread
From: Lad, Prabhakar @ 2025-06-24 15:16 UTC (permalink / raw)
  To: Biju Das
  Cc: Geert Uytterhoeven, Andrzej Hajda, Neil Armstrong, Robert Foss,
	laurent.pinchart, Jonas Karlman, Jernej Skrabec,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Michael Turquette, Stephen Boyd, Magnus Damm,
	dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-renesas-soc@vger.kernel.org,
	linux-clk@vger.kernel.org, Fabrizio Castro, Prabhakar Mahadev Lad

On Mon, Jun 16, 2025 at 11:54 AM Biju Das <biju.das.jz@bp.renesas.com> wrote:
>
>
>
> > -----Original Message-----
> > From: Lad, Prabhakar <prabhakar.csengg@gmail.com>
> > Sent: Monday, June 16, 2025 11:48 AM
> > To: Biju Das <biju.das.jz@bp.renesas.com>
> > Cc: Geert Uytterhoeven <geert+renesas@glider.be>; Andrzej Hajda
> > <andrzej.hajda@intel.com>; Neil Armstrong <neil.armstrong@linaro.org>;
> > Robert Foss <rfoss@kernel.org>; laurent.pinchart
> > <laurent.pinchart@ideasonboard.com>; Jonas Karlman <jonas@kwiboo.se>;
> > Jernej Skrabec <jernej.skrabec@gmail.com>; Maarten Lankhorst
> > <maarten.lankhorst@linux.intel.com>; Maxime Ripard <mripard@kernel.org>;
> > Thomas Zimmermann <tzimmermann@suse.de>; David Airlie <airlied@gmail.com>;
> > Simona Vetter <simona@ffwll.ch>; Rob Herring <robh@kernel.org>; Krzysztof
> > Kozlowski <krzk+dt@kernel.org>; Conor Dooley <conor+dt@kernel.org>;
> > Michael Turquette <mturquette@baylibre.com>; Stephen Boyd
> > <sboyd@kernel.org>; Magnus Damm <magnus.damm@gmail.com>; dri-
> > devel@lists.freedesktop.org; devicetree@vger.kernel.org; linux-
> > kernel@vger.kernel.org; linux-renesas-soc@vger.kernel.org; linux-
> > clk@vger.kernel.org; Fabrizio Castro <fabrizio.castro.jz@renesas.com>;
> > Prabhakar Mahadev Lad <prabhakar.mahadev-lad.rj@bp.renesas.com>
> > Subject: Re: [PATCH v6 4/4] drm: renesas: rz-du: mipi_dsi: Add support for
> > RZ/V2H(P) SoC
> >
> > Hi Biju,
> >
> > Thank you for the review.
> >
> > On Fri, Jun 13, 2025 at 7:17 AM Biju Das <biju.das.jz@bp.renesas.com>
> > wrote:
> > >
> > > Hi Prabhakar,
> > >
> > > > -----Original Message-----
> > > > From: Prabhakar <prabhakar.csengg@gmail.com>
> > > > Sent: 30 May 2025 18:19
> > > > Subject: [PATCH v6 4/4] drm: renesas: rz-du: mipi_dsi: Add support
> > > > for RZ/V2H(P) SoC
> > > >
> > > > From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> > > >
> > > > Add DSI support for Renesas RZ/V2H(P) SoC.
> > > >
> > > > Co-developed-by: Fabrizio Castro <fabrizio.castro.jz@renesas.com>
> > > > Signed-off-by: Fabrizio Castro <fabrizio.castro.jz@renesas.com>
> > > > Signed-off-by: Lad Prabhakar
> > > > <prabhakar.mahadev-lad.rj@bp.renesas.com>
> > > > ---
> > > > v5->v6:
> > > > - Made use of GENMASK() macro for PLLCLKSET0R_PLL_*,
> > > >   PHYTCLKSETR_* and PHYTHSSETR_* macros.
> > > > - Replaced 10000000UL with 10 * MEGA
> > > > - Renamed mode_freq_hz to mode_freq_khz in rzv2h_dsi_mode_calc
> > > > - Replaced `i -= 1;` with `i--;`
> > > > - Renamed RZV2H_MIPI_DPHY_FOUT_MIN_IN_MEGA to
> > > >   RZV2H_MIPI_DPHY_FOUT_MIN_IN_MHZ and
> > > >   RZV2H_MIPI_DPHY_FOUT_MAX_IN_MEGA to
> > > >   RZV2H_MIPI_DPHY_FOUT_MAX_IN_MHZ.
> > > >
> > > > v4->v5:
> > > > - No changes
> > > >
> > > > v3->v4
> > > > - In rzv2h_dphy_find_ulpsexit() made the array static const.
> > > >
> > > > v2->v3:
> > > > - Simplifed V2H DSI timings array to save space
> > > > - Switched to use fsleep() instead of udelay()
> > > >
> > > > v1->v2:
> > > > - Dropped unused macros
> > > > - Added missing LPCLK flag to rzv2h info
> > > > ---
> > > >  .../gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c    | 345
> > ++++++++++++++++++
> > > >  .../drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h   |  34 ++
> > > >  2 files changed, 379 insertions(+)
> > > >
> > > > diff --git a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
> > > > b/drivers/gpu/drm/renesas/rz- du/rzg2l_mipi_dsi.c index
> > > > a31f9b6aa920..ea554ced6713 100644
> > > > --- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
> > > > +++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
> > > > @@ -5,6 +5,7 @@
> > > >   * Copyright (C) 2022 Renesas Electronics Corporation
> > > >   */
> > > >  #include <linux/clk.h>
> > > > +#include <linux/clk/renesas-rzv2h-dsi.h>
> > > >  #include <linux/delay.h>
> > > >  #include <linux/io.h>
> > > >  #include <linux/iopoll.h>
> > <snip>
> > > > +
> > > > +static int rzv2h_dphy_conf_clks(struct rzg2l_mipi_dsi *dsi, unsigned
> > long mode_freq,
> > > > +                             u64 *hsfreq_millihz) {
> > > > +     struct rzv2h_plldsi_parameters *dsi_parameters = &dsi-
> > >dsi_parameters;
> > > > +     unsigned long status;
> > > > +
> > > > +     if (dsi->mode_calc.mode_freq_khz != mode_freq) {
> > > > +             status = rzv2h_dphy_mode_clk_check(dsi, mode_freq);
> > > > +             if (status != MODE_OK) {
> > > > +                     dev_err(dsi->dev, "No PLL parameters found for
> > mode clk %lu\n",
> > > > +                             mode_freq);
> > > > +                     return -EINVAL;
> > > > +             }
> > > > +     }
> > > > +
> > > > +     clk_set_rate(dsi->vclk, dsi->mode_calc.mode_freq_hz);
> > >
> > > Not sure, Can we use the DSI divider required based on the data rate
> > > (vclk, bpp and numlanes) here
> > >
> > > and then the set parent clk of PLLDSI as well here (dsi->vclk * the
> > divider value) ??
> > >
> > > 24MHZ->PLL DSI->DSI DIVIDER->VCLOCK
> > >
> > > Maybe then the clock framework has all the information for setting
> > PLL_DSI and DSI_DIVIDER clks??
> > >
> > Can you please elaborate here with a detailed example.
>
> There will be determine_clk followed by set_clock for setting new rate for PLL DSI(dsi->vclk * the divider value)
> For eg:  vclk_max = 187.5 MHz, DSI Divider required = 16
> Then set PLL_DSI = 187.5 * 16 MHz using clk_set.
>
This will trigger the algorithm twice, so I'll go with the current
approach which is optimal.

Cheers,
Prabhakar

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

* Re: [PATCH v6 1/4] clk: renesas: rzv2h-cpg: Add support for DSI clocks
  2025-06-19  5:05         ` Biju Das
@ 2025-06-24 15:21           ` Lad, Prabhakar
  0 siblings, 0 replies; 18+ messages in thread
From: Lad, Prabhakar @ 2025-06-24 15:21 UTC (permalink / raw)
  To: Biju Das
  Cc: Geert Uytterhoeven, Andrzej Hajda, Neil Armstrong, Robert Foss,
	laurent.pinchart, Jonas Karlman, Jernej Skrabec,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Michael Turquette, Stephen Boyd, Magnus Damm,
	dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-renesas-soc@vger.kernel.org,
	linux-clk@vger.kernel.org, Fabrizio Castro, Prabhakar Mahadev Lad

Hi Biju,

On Thu, Jun 19, 2025 at 6:05 AM Biju Das <biju.das.jz@bp.renesas.com> wrote:
>
> Hi Prabhakar,
>
> > -----Original Message-----
> > From: Biju Das
> > Sent: 18 June 2025 14:26
> > Subject: RE: [PATCH v6 1/4] clk: renesas: rzv2h-cpg: Add support for DSI clocks
> >
> > Hi Prabhakar,
> >
> > > -----Original Message-----
> > > From: dri-devel <dri-devel-bounces@lists.freedesktop.org> On Behalf Of
> > > Lad, Prabhakar
> > > Sent: 16 June 2025 11:45
> > > Subject: Re: [PATCH v6 1/4] clk: renesas: rzv2h-cpg: Add support for
> > > DSI clocks
> > >
> > > Hi Biju,
> > >
> > > Thank you for the review.
> > >
> > > On Fri, Jun 13, 2025 at 6:57 AM Biju Das <biju.das.jz@bp.renesas.com> wrote:
> > > >
> > > > Hi Prabhakar,
> > > >
> > > > > -----Original Message-----
> > > > > From: Prabhakar <prabhakar.csengg@gmail.com>
> > > > > Sent: 30 May 2025 18:19
> > > > .castro.jz@renesas.com>; Prabhakar Mahadev Lad <prabhakar.mahadev-
> > > > > lad.rj@bp.renesas.com>
> > > > > Subject: [PATCH v6 1/4] clk: renesas: rzv2h-cpg: Add support for
> > > > > DSI clocks
> > > > >
> > > > > From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> > > > >
> > > > > Add support for PLLDSI and PLLDSI divider clocks.
> > > > >
> > > > > Introduce the `renesas-rzv2h-dsi.h` header to centralize and share
> > > > > PLLDSI-related data structures, limits, and algorithms between the RZ/V2H CPG and DSI drivers.
> > > > >
> > > > > The DSI PLL is functionally similar to the CPG's PLLDSI, but has
> > > > > slightly different parameter limits and omits the programmable
> > > > > divider present in CPG. To ensure precise frequency
> > > > > calculations-especially for milliHz-level accuracy needed by the
> > > > > DSI driver-the shared algorithm
> > > allows both drivers to compute PLL parameters consistently using the same logic and input clock.
> > > > >
> > > > > Co-developed-by: Fabrizio Castro <fabrizio.castro.jz@renesas.com>
> > > > > Signed-off-by: Fabrizio Castro <fabrizio.castro.jz@renesas.com>
> > > > > Signed-off-by: Lad Prabhakar
> > > > > <prabhakar.mahadev-lad.rj@bp.renesas.com>
> > > > > ---
> > > > > v5->v6:
> > > > > - Renamed CPG_PLL_STBY_SSCGEN_WEN to CPG_PLL_STBY_SSC_EN_WEN
> > > > > - Updated CPG_PLL_CLK1_DIV_K, CPG_PLL_CLK1_DIV_M, and
> > > > >   CPG_PLL_CLK1_DIV_P macros to use GENMASK
> > > > > - Updated req->rate in rzv2h_cpg_plldsi_div_determine_rate()
> > > > > - Dropped the cast in rzv2h_cpg_plldsi_div_set_rate()
> > > > > - Dropped rzv2h_cpg_plldsi_round_rate() and implemented
> > > > >   rzv2h_cpg_plldsi_determine_rate() instead
> > > > > - Made use of FIELD_PREP()
> > > > > - Moved CPG_CSDIV1 macro in patch 2/4
> > > > > - Dropped two_pow_s in rzv2h_dsi_get_pll_parameters_values()
> > > > > - Used mul_u32_u32() while calculating output_m and output_k_range
> > > > > - Used div_s64() instead of div64_s64() while calculating
> > > > >   pll_k
> > > > > - Used mul_u32_u32() while calculating fvco and fvco checks
> > > > > - Rounded the final output using DIV_U64_ROUND_CLOSEST()
> > > > >
> > > > > v4->v5:
> > > > > - No changes
> > > > >
> > > > > v3->v4:
> > > > > - Corrected parameter name in rzv2h_dsi_get_pll_parameters_values()
> > > > >   description freq_millihz
> > > > >
> > > > > v2->v3:
> > > > > - Update the commit message to clarify the purpose of `renesas-rzv2h-dsi.h`
> > > > >   header
> > > > > - Used mul_u32_u32() in rzv2h_cpg_plldsi_div_determine_rate()
> > > > > - Replaced *_mhz to *_millihz for clarity
> > > > > - Updated u64->u32 for fvco limits
> > > > > - Initialized the members in declaration order for
> > > > >   RZV2H_CPG_PLL_DSI_LIMITS() macro
> > > > > - Used clk_div_mask() in rzv2h_cpg_plldsi_div_recalc_rate()
> > > > > - Replaced `unsigned long long` with u64
> > > > > - Dropped rzv2h_cpg_plldsi_clk_recalc_rate() and reused
> > > > >   rzv2h_cpg_pll_clk_recalc_rate() instead
> > > > > - In rzv2h_cpg_plldsi_div_set_rate() followed the same style
> > > > >   of RMW-operation as done in the other functions
> > > > > - Renamed rzv2h_cpg_plldsi_set_rate() to rzv2h_cpg_pll_set_rate()
> > > > > - Dropped rzv2h_cpg_plldsi_clk_register() and reused
> > > > >   rzv2h_cpg_pll_clk_register() instead
> > > > > - Added a gaurd in renesas-rzv2h-dsi.h header
> > > > >
> > > > > v1->v2:
> > > > > - No changes
> > > > > ---
> > > > >  drivers/clk/renesas/rzv2h-cpg.c       | 278 +++++++++++++++++++++++++-
> > > > >  drivers/clk/renesas/rzv2h-cpg.h       |  13 ++
> > > > >  include/linux/clk/renesas-rzv2h-dsi.h | 210 +++++++++++++++++++
> > > > >  3 files changed, 492 insertions(+), 9 deletions(-)  create mode
> > > > > 100644 include/linux/clk/renesas- rzv2h-dsi.h
> > > > >
> > > > > diff --git a/drivers/clk/renesas/rzv2h-cpg.c
> > > > > b/drivers/clk/renesas/rzv2h-cpg.c index
> > > > > 761da3bf77ce..d590f9f47371 100644
> > > > > --- a/drivers/clk/renesas/rzv2h-cpg.c
> > > > > +++ b/drivers/clk/renesas/rzv2h-cpg.c
> > > > > @@ -14,9 +14,13 @@
> > > > >  #include <linux/bitfield.h>
> > > > >  #include <linux/clk.h>
> > > > >  #include <linux/clk-provider.h>
> > > > > +#include <linux/clk/renesas-rzv2h-dsi.h>
> > > > >  #include <linux/delay.h>
> > > > >  #include <linux/init.h>
> > > > >  #include <linux/iopoll.h>
> > > > > +#include <linux/math.h>
> > > >
> > > >
> > > >
> > > > > +     req->rate =
> > > > > + DIV_ROUND_CLOSEST_ULL(dsi_dividers->freq_millihz,
> > > > > + MILLI);
> > > > > +
> > > > > +     return 0;
> > > > > +};
> > > > > +
> > > > > +static int rzv2h_cpg_plldsi_div_set_rate(struct clk_hw *hw,
> > > > > +                                      unsigned long rate,
> > > > > +                                      unsigned long parent_rate) {
> > > > > +     struct rzv2h_plldsi_div_clk *dsi_div = to_plldsi_div_clk(hw);
> > > > > +     struct rzv2h_cpg_priv *priv = dsi_div->priv;
> > > > > +     struct rzv2h_plldsi_parameters *dsi_dividers = &priv->plldsi_div_parameters;
> > > > > +     struct ddiv ddiv = dsi_div->ddiv;
> > > > > +     const struct clk_div_table *clkt;
> > > > > +     bool div_found = false;
> > > > > +     u32 val, shift, div;
> > > > > +
> > > > > +     div = dsi_dividers->csdiv;
> > > > > +     for (clkt = dsi_div->dtable; clkt->div; clkt++) {
> > > > > +             if (clkt->div == div) {
> > > > > +                     div_found = true;
> > > > > +                     break;
> > > > > +             }
> > > > > +     }
> > > > > +
> > > > > +     if (!div_found)
> > > > > +             return -EINVAL;
> > > >
> > > > This check can be done in determine rate and cache the divider??
> > > >
> > > Ok, I'll drop this check as the divider is already cached. The for
> > > loop above is to determine the val which is used below to program the registers.
> >
> > If you are caching actual divider value, then the check is not required here.
> > Otherwise the above code is fine.
> >
> > Assume the csdiv you found, have no corresponding match in the table.
>
>
> 1) By looking at RZ/G3E, can we make this code more scalable?
>
> RZ/G3E has 2 PLL-DSI's
> PLL-DSI1 supports DUAL LVDS, Single LVDS and DSI
> PLL-DSI2 supports single LVDS,  DPI and DSI
>
Sure, I'll make it more scalable.

> In total there will be 4 limit tables (DSI, single LVDS, Dual LVDS and DPI)
>
> Based on the display output, each PLL needs to pick the appropriate limit table
> to compute PLL parameters.
>
> 2) Can we drop DSI divider limits from the limit table and use the values from dsi divider table
>    itself which is passed in DEF_PLLDSI_DIV?
>
Sure, I will do that.

Cheers,
Prabhakar

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

* RE: [PATCH v6 4/4] drm: renesas: rz-du: mipi_dsi: Add support for RZ/V2H(P) SoC
  2025-06-24 15:16         ` Lad, Prabhakar
@ 2025-06-25 11:42           ` Biju Das
  0 siblings, 0 replies; 18+ messages in thread
From: Biju Das @ 2025-06-25 11:42 UTC (permalink / raw)
  To: Lad, Prabhakar
  Cc: Geert Uytterhoeven, Andrzej Hajda, Neil Armstrong, Robert Foss,
	laurent.pinchart, Jonas Karlman, Jernej Skrabec,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Michael Turquette, Stephen Boyd, Magnus Damm,
	dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-renesas-soc@vger.kernel.org,
	linux-clk@vger.kernel.org, Fabrizio Castro, Prabhakar Mahadev Lad

Hi Prabhakar,

> -----Original Message-----
> From: Lad, Prabhakar <prabhakar.csengg@gmail.com>
> Sent: 24 June 2025 16:16
> >
> > There will be determine_clk followed by set_clock for setting new rate
> > for PLL DSI(dsi->vclk * the divider value) For eg:  vclk_max = 187.5
> > MHz, DSI Divider required = 16 Then set PLL_DSI = 187.5 * 16 MHz using clk_set.
> >
> This will trigger the algorithm twice, so I'll go with the current approach which is optimal.

OK.

Cheers,
Biju

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

* RE: [PATCH v6 3/4] dt-bindings: display: bridge: renesas,dsi: Add support for RZ/V2H(P) SoC
  2025-05-30 17:18 ` [PATCH v6 3/4] dt-bindings: display: bridge: renesas,dsi: Add support for RZ/V2H(P) SoC Prabhakar
@ 2025-06-26  6:10   ` Biju Das
  0 siblings, 0 replies; 18+ messages in thread
From: Biju Das @ 2025-06-26  6:10 UTC (permalink / raw)
  To: Prabhakar, Geert Uytterhoeven, Andrzej Hajda, Neil Armstrong,
	Robert Foss, laurent.pinchart, Jonas Karlman, Jernej Skrabec,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Michael Turquette, Stephen Boyd, Magnus Damm
  Cc: dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-renesas-soc@vger.kernel.org,
	linux-clk@vger.kernel.org, Fabrizio Castro, Prabhakar Mahadev Lad,
	Krzysztof Kozlowski

Hi Prabhakar,

Thanks for the patch.

> -----Original Message-----
> From: Prabhakar <prabhakar.csengg@gmail.com>
> Sent: 30 May 2025 18:19
>
> Subject: [PATCH v6 3/4] dt-bindings: display: bridge: renesas,dsi: Add support for RZ/V2H(P) SoC
> 
> From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> 
> The MIPI DSI interface on the RZ/V2H(P) SoC is nearly identical to that of the RZ/G2L SoC. While the
> LINK registers are the same for both SoCs, the D-PHY registers differ. Additionally, the number of
> resets for DSI on
> RZ/V2H(P) is two compared to three on the RZ/G2L.
> 
> To accommodate these differences, a SoC-specific `renesas,r9a09g057-mipi-dsi` compatible string has
> been added for the
> RZ/V2H(P) SoC.
> 
> Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
> Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
> ---
> v5->v6:
> - Preserved the sort order (by part number).
> - Added reviewed tag from Geert.
> 
> v4->v5:
> - No changes
> 
> v3->v4:
> - No changes
> 
> v2->v3:
> - Collected reviewed tag from Krzysztof
> 
> v1->v2:
> - Kept the sort order for schema validation
> - Added  `port@1: false` for RZ/V2H(P) SoC
> ---
>  .../bindings/display/bridge/renesas,dsi.yaml  | 116 +++++++++++++-----
>  1 file changed, 87 insertions(+), 29 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/display/bridge/renesas,dsi.yaml
> b/Documentation/devicetree/bindings/display/bridge/renesas,dsi.yaml
> index e08c24633926..8c7e2b17ba79 100644
> --- a/Documentation/devicetree/bindings/display/bridge/renesas,dsi.yaml
> +++ b/Documentation/devicetree/bindings/display/bridge/renesas,dsi.yaml
> @@ -14,16 +14,17 @@ description: |
>    RZ/G2L alike family of SoC's. The encoder can operate in DSI mode, with
>    up to four data lanes.
> 
> -allOf:
> -  - $ref: /schemas/display/dsi-controller.yaml#
> -
>  properties:
>    compatible:
> -    items:
> +    oneOf:
> +      - items:
> +          - enum:
> +              - renesas,r9a07g044-mipi-dsi # RZ/G2{L,LC}
> +              - renesas,r9a07g054-mipi-dsi # RZ/V2L
> +          - const: renesas,rzg2l-mipi-dsi
> +
>        - enum:
> -          - renesas,r9a07g044-mipi-dsi # RZ/G2{L,LC}
> -          - renesas,r9a07g054-mipi-dsi # RZ/V2L
> -      - const: renesas,rzg2l-mipi-dsi
> +          - renesas,r9a09g057-mipi-dsi # RZ/V2H(P)
> 
>    reg:
>      maxItems: 1
> @@ -49,34 +50,56 @@ properties:
>        - const: debug
> 
>    clocks:
> -    items:
> -      - description: DSI D-PHY PLL multiplied clock
> -      - description: DSI D-PHY system clock
> -      - description: DSI AXI bus clock
> -      - description: DSI Register access clock
> -      - description: DSI Video clock
> -      - description: DSI D-PHY Escape mode transmit clock
> +    oneOf:
> +      - items:
> +          - description: DSI D-PHY PLL multiplied clock
> +          - description: DSI D-PHY system clock
> +          - description: DSI AXI bus clock
> +          - description: DSI Register access clock
> +          - description: DSI Video clock
> +          - description: DSI D-PHY Escape mode transmit clock
> +      - items:
> +          - description: DSI D-PHY PLL multiplied clock

This is PLL_Reference_CLK(24 MHz) compared to the DSI D-PHY PLL multiplied clock in RZ/G2L(~3000MHz).

> +          - description: DSI AXI bus clock
> +          - description: DSI Register access clock
> +          - description: DSI Video clock
> +          - description: DSI D-PHY Escape mode transmit clock
> 
>    clock-names:
> -    items:
> -      - const: pllclk
> -      - const: sysclk
> -      - const: aclk
> -      - const: pclk
> -      - const: vclk
> -      - const: lpclk
> +    oneOf:
> +      - items:
> +          - const: pllclk
> +          - const: sysclk
> +          - const: aclk
> +          - const: pclk
> +          - const: vclk
> +          - const: lpclk
> +      - items:
> +          - const: pllclk

pll_ref_clk ??

Cheers,
Biju

> +          - const: aclk
> +          - const: pclk
> +          - const: vclk
> +          - const: lpclk
> 
>    resets:
> -    items:
> -      - description: MIPI_DSI_CMN_RSTB
> -      - description: MIPI_DSI_ARESET_N
> -      - description: MIPI_DSI_PRESET_N
> +    oneOf:
> +      - items:
> +          - description: MIPI_DSI_CMN_RSTB
> +          - description: MIPI_DSI_ARESET_N
> +          - description: MIPI_DSI_PRESET_N
> +      - items:
> +          - description: MIPI_DSI_ARESET_N
> +          - description: MIPI_DSI_PRESET_N
> 
>    reset-names:
> -    items:
> -      - const: rst
> -      - const: arst
> -      - const: prst
> +    oneOf:
> +      - items:
> +          - const: rst
> +          - const: arst
> +          - const: prst
> +      - items:
> +          - const: arst
> +          - const: prst
> 
>    power-domains:
>      maxItems: 1
> @@ -130,6 +153,41 @@ required:
> 
>  additionalProperties: false
> 
> +allOf:
> +  - $ref: ../dsi-controller.yaml#
> +
> +  - if:
> +      properties:
> +        compatible:
> +          contains:
> +            const: renesas,r9a09g057-mipi-dsi
> +    then:
> +      properties:
> +        clocks:
> +          maxItems: 5
> +
> +        clock-names:
> +          maxItems: 5
> +
> +        resets:
> +          maxItems: 2
> +
> +        reset-names:
> +          maxItems: 2
> +    else:
> +      properties:
> +        clocks:
> +          minItems: 6
> +
> +        clock-names:
> +          minItems: 6
> +
> +        resets:
> +          minItems: 3
> +
> +        reset-names:
> +          minItems: 3
> +
>  examples:
>    - |
>      #include <dt-bindings/clock/r9a07g044-cpg.h>
> --
> 2.49.0


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

end of thread, other threads:[~2025-06-26  6:10 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-05-30 17:18 [PATCH v6 0/4] Add support for DU/DSI clocks and DSI driver support for the Renesas RZ/V2H(P) SoC Prabhakar
2025-05-30 17:18 ` [PATCH v6 1/4] clk: renesas: rzv2h-cpg: Add support for DSI clocks Prabhakar
2025-06-13  5:57   ` Biju Das
2025-06-16 10:44     ` Lad, Prabhakar
2025-06-18 13:25       ` Biju Das
2025-06-19  5:05         ` Biju Das
2025-06-24 15:21           ` Lad, Prabhakar
2025-05-30 17:18 ` [PATCH v6 2/4] clk: renesas: r9a09g057: Add clock and reset entries for DSI and LCDC Prabhakar
2025-05-30 17:18 ` [PATCH v6 3/4] dt-bindings: display: bridge: renesas,dsi: Add support for RZ/V2H(P) SoC Prabhakar
2025-06-26  6:10   ` Biju Das
2025-05-30 17:18 ` [PATCH v6 4/4] drm: renesas: rz-du: mipi_dsi: " Prabhakar
2025-06-13  6:17   ` Biju Das
2025-06-16 10:48     ` Lad, Prabhakar
2025-06-16 10:54       ` Biju Das
2025-06-16 11:20         ` Lad, Prabhakar
2025-06-18 14:19           ` Biju Das
2025-06-24 15:16         ` Lad, Prabhakar
2025-06-25 11:42           ` Biju Das

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).