public inbox for cip-dev@lists.cip-project.org
 help / color / mirror / Atom feed
* [PATCH 5.10.y-cip 00/10] Add additional support for MIPI-DSI for RZ/G2L
@ 2026-04-15 18:17 Chris Brandt
  2026-04-15 18:18 ` [PATCH 5.10.y-cip 01/10] drm: renesas: rz-du: Add atomic_pre_enable Chris Brandt
                   ` (10 more replies)
  0 siblings, 11 replies; 13+ messages in thread
From: Chris Brandt @ 2026-04-15 18:17 UTC (permalink / raw)
  To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek

There is important functionality missing from the MIPI-DSI display driver and also the clock
driver for generating the correct pixel clock frequencies.

Since everything is now accepted in mainline, this is the backport of those patches.

The patches were tested on a RZ/G2L board that has a connector for a MIPI-DSI panel.
Additionally, the RZ/G2L SMARC board with a MIPI-to-HDMI bridge chip was re-tested.


Chris



Chris Brandt (5):
  drm: renesas: rz-du: Add atomic_pre_enable
  drm: renesas: rz-du: mipi_dsi: Set DSI divider
  clk: renesas: rzg2l: Fix intin variable size
  clk: renesas: rzg2l: Select correct div round macro
  clk: renesas: rzg2l: Remove DSI clock rate restrictions

Geert Uytterhoeven (2):
  clk: renesas: Use IS_ERR() for pointers that cannot be NULL
  clk: renesas: Add missing log message terminators

Hugo Villeneuve (2):
  drm: renesas: rz-du: Implement MIPI DSI host transfers
  drm: renesas: rz-du: mipi_dsi: fix kernel panic when rebooting for
    some panels

Pali Rohár (1):
  math64: New DIV_U64_ROUND_CLOSEST helper

 drivers/clk/renesas/clk-vbattb.c              |   4 +-
 drivers/clk/renesas/renesas-cpg-mssr.c        |   4 +-
 drivers/clk/renesas/rzg2l-cpg.c               | 182 +++++++++++---
 .../gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c    | 223 +++++++++++++++++-
 .../drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h   |  54 +++++
 include/linux/clk/renesas.h                   |  12 +
 include/linux/math64.h                        |  13 +
 7 files changed, 450 insertions(+), 42 deletions(-)

--
2.52.0



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

* [PATCH 5.10.y-cip 01/10] drm: renesas: rz-du: Add atomic_pre_enable
  2026-04-15 18:17 [PATCH 5.10.y-cip 00/10] Add additional support for MIPI-DSI for RZ/G2L Chris Brandt
@ 2026-04-15 18:18 ` Chris Brandt
  2026-04-15 18:18 ` [PATCH 5.10.y-cip 02/10] drm: renesas: rz-du: Implement MIPI DSI host transfers Chris Brandt
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Chris Brandt @ 2026-04-15 18:18 UTC (permalink / raw)
  To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek

commit 5ce16c169a4cb8ffceabfd48853d0bf605ce785a upstream.

When drm_panel.prepare_prev_first is set to true in a panel driver, the
panel expects the MIPI DSI hardware to be already configured before the
panel's prepare function is called because it might need to send DCS
commands.

Signed-off-by: Chris Brandt <chris.brandt@renesas.com>
Tested-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
Reviewed-by: Biju Das <biju.das.jz@bp.renesas.com>
Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
Link: https://lore.kernel.org/r/20250521210335.3149065-1-chris.brandt@renesas.com
Signed-off-by: Chris Brandt <chris.brandt@renesas.com>
---
 drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

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 22bf4f27f7e0..49daefa94220 100644
--- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
+++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
@@ -541,8 +541,8 @@ static int rzg2l_mipi_dsi_attach(struct drm_bridge *bridge,
 				 flags);
 }

-static void rzg2l_mipi_dsi_atomic_enable(struct drm_bridge *bridge,
-					 struct drm_bridge_state *old_bridge_state)
+static void rzg2l_mipi_dsi_atomic_pre_enable(struct drm_bridge *bridge,
+					     struct drm_bridge_state *old_bridge_state)
 {
 	struct drm_atomic_state *state = old_bridge_state->base.state;
 	struct rzg2l_mipi_dsi *dsi = bridge_to_rzg2l_mipi_dsi(bridge);
@@ -560,6 +560,13 @@ static void rzg2l_mipi_dsi_atomic_enable(struct drm_bridge *bridge,
 		return;

 	rzg2l_mipi_dsi_set_display_timing(dsi, mode);
+}
+
+static void rzg2l_mipi_dsi_atomic_enable(struct drm_bridge *bridge,
+					 struct drm_bridge_state *old_bridge_state)
+{
+	struct rzg2l_mipi_dsi *dsi = bridge_to_rzg2l_mipi_dsi(bridge);
+	int ret;

 	ret = rzg2l_mipi_dsi_start_hs_clock(dsi);
 	if (ret < 0)
@@ -603,6 +610,7 @@ static const struct drm_bridge_funcs rzg2l_mipi_dsi_bridge_ops = {
 	.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
 	.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
 	.atomic_reset = drm_atomic_helper_bridge_reset,
+	.atomic_pre_enable = rzg2l_mipi_dsi_atomic_pre_enable,
 	.atomic_enable = rzg2l_mipi_dsi_atomic_enable,
 	.atomic_disable = rzg2l_mipi_dsi_atomic_disable,
 	.mode_valid = rzg2l_mipi_dsi_bridge_mode_valid,
--
2.52.0



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

* [PATCH 5.10.y-cip 02/10] drm: renesas: rz-du: Implement MIPI DSI host transfers
  2026-04-15 18:17 [PATCH 5.10.y-cip 00/10] Add additional support for MIPI-DSI for RZ/G2L Chris Brandt
  2026-04-15 18:18 ` [PATCH 5.10.y-cip 01/10] drm: renesas: rz-du: Add atomic_pre_enable Chris Brandt
@ 2026-04-15 18:18 ` Chris Brandt
  2026-04-15 18:18 ` [PATCH 5.10.y-cip 03/10] drm: renesas: rz-du: mipi_dsi: fix kernel panic when rebooting for some panels Chris Brandt
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Chris Brandt @ 2026-04-15 18:18 UTC (permalink / raw)
  To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek

From: Hugo Villeneuve <hvilleneuve@dimonoff.com>

commit 6f392f37165008cfb3f89d723aa019e372ee79b9 upstream.

Add support for sending MIPI DSI command packets from the host to a
peripheral. This is required for panels that need configuration before
they accept video data.

Also for long reads to work properly, set DCS maximum return packet size
to the value of the DMA buffer size.

Based on Renesas Linux kernel v5.10 repos [1].
Link: https://github.com/renesas-rz/rz_linux-cip.git

Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
Tested-by: Chris Brandt <Chris.Brandt@renesas.com>
Reviewed-by: Biju Das <biju.das.jz@bp.renesas.com>
Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
Link: https://lore.kernel.org/r/20250604145306.1170676-2-hugo@hugovil.com
Signed-off-by: Chris Brandt <chris.brandt@renesas.com>
---
 .../gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c    | 186 ++++++++++++++++++
 .../drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h   |  54 +++++
 2 files changed, 240 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 49daefa94220..2c1e4fdb2d92 100644
--- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
+++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
@@ -4,8 +4,11 @@
  *
  * Copyright (C) 2022 Renesas Electronics Corporation
  */
+
+#include <linux/bitfield.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
+#include <linux/dma-mapping.h>
 #include <linux/io.h>
 #include <linux/iopoll.h>
 #include <linux/module.h>
@@ -24,9 +27,12 @@
 #include <drm/drm_of.h>
 #include <drm/drm_panel.h>
 #include <drm/drm_probe_helper.h>
+#include <video/mipi_display.h>

 #include "rzg2l_mipi_dsi_regs.h"

+#define RZG2L_DCS_BUF_SIZE	128 /* Maximum DCS buffer size in external memory. */
+
 struct rzg2l_mipi_dsi {
 	struct device *dev;
 	void __iomem *mmio;
@@ -45,6 +51,10 @@ struct rzg2l_mipi_dsi {
 	unsigned int num_data_lanes;
 	unsigned int lanes;
 	unsigned long mode_flags;
+
+	/* DCS buffer pointers when using external memory. */
+	dma_addr_t dcs_buf_phys;
+	u8 *dcs_buf_virt;
 };

 static inline struct rzg2l_mipi_dsi *
@@ -268,6 +278,7 @@ static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi,
 	u32 clkbfht;
 	u32 clkstpt;
 	u32 golpbkt;
+	u32 dsisetr;
 	int ret;

 	/*
@@ -329,6 +340,15 @@ static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi,
 	lptrnstsetr = LPTRNSTSETR_GOLPBKT(golpbkt);
 	rzg2l_mipi_dsi_link_write(dsi, LPTRNSTSETR, lptrnstsetr);

+	/*
+	 * Increase MRPSZ as the default value of 1 will result in long read
+	 * commands payload not being saved to memory.
+	 */
+	dsisetr = rzg2l_mipi_dsi_link_read(dsi, DSISETR);
+	dsisetr &= ~DSISETR_MRPSZ;
+	dsisetr |= FIELD_PREP(DSISETR_MRPSZ, RZG2L_DCS_BUF_SIZE);
+	rzg2l_mipi_dsi_link_write(dsi, DSISETR, dsisetr);
+
 	return 0;

 err_phy:
@@ -658,9 +678,168 @@ static int rzg2l_mipi_dsi_host_detach(struct mipi_dsi_host *host,
 	return 0;
 }

+static ssize_t rzg2l_mipi_dsi_read_response(struct rzg2l_mipi_dsi *dsi,
+					    const struct mipi_dsi_msg *msg)
+{
+	u8 *msg_rx = msg->rx_buf;
+	u8 datatype;
+	u32 result;
+	u16 size;
+
+	result = rzg2l_mipi_dsi_link_read(dsi, RXRSS0R);
+	if (result & RXRSS0R_RXPKTDFAIL) {
+		dev_err(dsi->dev, "packet rx data did not save correctly\n");
+		return -EPROTO;
+	}
+
+	if (result & RXRSS0R_RXFAIL) {
+		dev_err(dsi->dev, "packet rx failure\n");
+		return -EPROTO;
+	}
+
+	if (!(result & RXRSS0R_RXSUC))
+		return -EPROTO;
+
+	datatype = FIELD_GET(RXRSS0R_DT, result);
+
+	switch (datatype) {
+	case 0:
+		dev_dbg(dsi->dev, "ACK\n");
+		return 0;
+	case MIPI_DSI_RX_END_OF_TRANSMISSION:
+		dev_dbg(dsi->dev, "EoTp\n");
+		return 0;
+	case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT:
+		dev_dbg(dsi->dev, "Acknowledge and error report: $%02x%02x\n",
+			(u8)FIELD_GET(RXRSS0R_DATA1, result),
+			(u8)FIELD_GET(RXRSS0R_DATA0, result));
+		return 0;
+	case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE:
+	case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE:
+		msg_rx[0] = FIELD_GET(RXRSS0R_DATA0, result);
+		return 1;
+	case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE:
+	case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE:
+		msg_rx[0] = FIELD_GET(RXRSS0R_DATA0, result);
+		msg_rx[1] = FIELD_GET(RXRSS0R_DATA1, result);
+		return 2;
+	case MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE:
+	case MIPI_DSI_RX_DCS_LONG_READ_RESPONSE:
+		size = FIELD_GET(RXRSS0R_WC, result);
+
+		if (size > msg->rx_len) {
+			dev_err(dsi->dev, "rx buffer too small");
+			return -ENOSPC;
+		}
+
+		memcpy(msg_rx, dsi->dcs_buf_virt, size);
+		return size;
+	default:
+		dev_err(dsi->dev, "unhandled response type: %02x\n", datatype);
+		return -EPROTO;
+	}
+}
+
+static ssize_t rzg2l_mipi_dsi_host_transfer(struct mipi_dsi_host *host,
+					    const struct mipi_dsi_msg *msg)
+{
+	struct rzg2l_mipi_dsi *dsi = host_to_rzg2l_mipi_dsi(host);
+	struct mipi_dsi_packet packet;
+	bool need_bta;
+	u32 value;
+	int ret;
+
+	ret = mipi_dsi_create_packet(&packet, msg);
+	if (ret < 0)
+		return ret;
+
+	/* Terminate operation after this descriptor is finished */
+	value = SQCH0DSC0AR_NXACT_TERM;
+
+	if (msg->flags & MIPI_DSI_MSG_REQ_ACK) {
+		need_bta = true; /* Message with explicitly requested ACK */
+		value |= FIELD_PREP(SQCH0DSC0AR_BTA, SQCH0DSC0AR_BTA_NON_READ);
+	} else if (msg->rx_buf && msg->rx_len > 0) {
+		need_bta = true; /* Read request */
+		value |= FIELD_PREP(SQCH0DSC0AR_BTA, SQCH0DSC0AR_BTA_READ);
+	} else {
+		need_bta = false;
+		value |= FIELD_PREP(SQCH0DSC0AR_BTA, SQCH0DSC0AR_BTA_NONE);
+	}
+
+	/* Set transmission speed */
+	if (msg->flags & MIPI_DSI_MSG_USE_LPM)
+		value |= SQCH0DSC0AR_SPD_LOW;
+	else
+		value |= SQCH0DSC0AR_SPD_HIGH;
+
+	/* Write TX packet header */
+	value |= FIELD_PREP(SQCH0DSC0AR_DT, packet.header[0]) |
+		FIELD_PREP(SQCH0DSC0AR_DATA0, packet.header[1]) |
+		FIELD_PREP(SQCH0DSC0AR_DATA1, packet.header[2]);
+
+	if (mipi_dsi_packet_format_is_long(msg->type)) {
+		value |= SQCH0DSC0AR_FMT_LONG;
+
+		if (packet.payload_length > RZG2L_DCS_BUF_SIZE) {
+			dev_err(dsi->dev, "Packet Tx payload size (%d) too large",
+				(unsigned int)packet.payload_length);
+			return -ENOSPC;
+		}
+
+		/* Copy TX packet payload data to memory space */
+		memcpy(dsi->dcs_buf_virt, packet.payload, packet.payload_length);
+	} else {
+		value |= SQCH0DSC0AR_FMT_SHORT;
+	}
+
+	rzg2l_mipi_dsi_link_write(dsi, SQCH0DSC0AR, value);
+
+	/*
+	 * Write: specify payload data source location, only used for
+	 *        long packet.
+	 * Read:  specify payload data storage location of response
+	 *        packet. Note: a read packet is always a short packet.
+	 *        If the response packet is a short packet or a long packet
+	 *        with WC = 0 (no payload), DTSEL is meaningless.
+	 */
+	rzg2l_mipi_dsi_link_write(dsi, SQCH0DSC0BR, SQCH0DSC0BR_DTSEL_MEM_SPACE);
+
+	/*
+	 * Set SQCHxSR.AACTFIN bit when descriptor actions are finished.
+	 * Read: set Rx result save slot number to 0 (ACTCODE).
+	 */
+	rzg2l_mipi_dsi_link_write(dsi, SQCH0DSC0CR, SQCH0DSC0CR_FINACT);
+
+	/* Set rx/tx payload data address, only relevant for long packet. */
+	rzg2l_mipi_dsi_link_write(dsi, SQCH0DSC0DR, (u32)dsi->dcs_buf_phys);
+
+	/* Start sequence 0 operation */
+	value = rzg2l_mipi_dsi_link_read(dsi, SQCH0SET0R);
+	value |= SQCH0SET0R_START;
+	rzg2l_mipi_dsi_link_write(dsi, SQCH0SET0R, value);
+
+	/* Wait for operation to finish */
+	ret = read_poll_timeout(rzg2l_mipi_dsi_link_read,
+				value, value & SQCH0SR_ADESFIN,
+				2000, 20000, false, dsi, SQCH0SR);
+	if (ret == 0) {
+		/* Success: clear status bit */
+		rzg2l_mipi_dsi_link_write(dsi, SQCH0SCR, SQCH0SCR_ADESFIN);
+
+		if (need_bta)
+			ret = rzg2l_mipi_dsi_read_response(dsi, msg);
+		else
+			ret = packet.payload_length;
+	}
+
+	return ret;
+}
+
 static const struct mipi_dsi_host_ops rzg2l_mipi_dsi_host_ops = {
 	.attach = rzg2l_mipi_dsi_host_attach,
 	.detach = rzg2l_mipi_dsi_host_detach,
+	.transfer = rzg2l_mipi_dsi_host_transfer,
 };

 /* -----------------------------------------------------------------------------
@@ -780,6 +959,11 @@ static int rzg2l_mipi_dsi_probe(struct platform_device *pdev)

 	drm_bridge_add(&dsi->bridge);

+	dsi->dcs_buf_virt = dma_alloc_coherent(dsi->host.dev, RZG2L_DCS_BUF_SIZE,
+					       &dsi->dcs_buf_phys, GFP_KERNEL);
+	if (!dsi->dcs_buf_virt)
+		return -ENOMEM;
+
 	return 0;

 err_phy:
@@ -794,6 +978,8 @@ static int rzg2l_mipi_dsi_remove(struct platform_device *pdev)
 {
 	struct rzg2l_mipi_dsi *dsi = platform_get_drvdata(pdev);

+	dma_free_coherent(dsi->host.dev, RZG2L_DCS_BUF_SIZE, dsi->dcs_buf_virt,
+			  dsi->dcs_buf_phys);
 	mipi_dsi_host_unregister(&dsi->host);
 	pm_runtime_disable(&pdev->dev);

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 1dbc16ec64a4..26d8a37ee635 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
@@ -81,6 +81,20 @@
 #define RSTSR_SWRSTLP			(1 << 1)
 #define RSTSR_SWRSTHS			(1 << 0)

+/* DSI Set Register */
+#define DSISETR				0x120
+#define DSISETR_MRPSZ			GENMASK(15, 0)
+
+/* Rx Result Save Slot 0 Register */
+#define RXRSS0R				0x240
+#define RXRSS0R_RXPKTDFAIL		BIT(28)
+#define RXRSS0R_RXFAIL			BIT(27)
+#define RXRSS0R_RXSUC			BIT(25)
+#define RXRSS0R_DT			GENMASK(21, 16)
+#define RXRSS0R_DATA1			GENMASK(15, 8)
+#define RXRSS0R_DATA0			GENMASK(7, 0)
+#define RXRSS0R_WC			GENMASK(15, 0) /* Word count for long packet. */
+
 /* Clock Lane Stop Time Set Register */
 #define CLSTPTSETR			0x314
 #define CLSTPTSETR_CLKKPT(x)		((x) << 24)
@@ -148,4 +162,44 @@
 #define VICH1HPSETR_HFP(x)		(((x) & 0x1fff) << 16)
 #define VICH1HPSETR_HBP(x)		(((x) & 0x1fff) << 0)

+/* Sequence Channel 0 Set 0 Register */
+#define SQCH0SET0R			0x5c0
+#define SQCH0SET0R_START		BIT(0)
+
+/* Sequence Channel 0 Status Register */
+#define SQCH0SR				0x5d0
+#define SQCH0SR_ADESFIN			BIT(8)
+
+/* Sequence Channel 0 Status Clear Register */
+#define SQCH0SCR			0x5d4
+#define SQCH0SCR_ADESFIN		BIT(8)
+
+/* Sequence Channel 0 Descriptor 0-A Register */
+#define SQCH0DSC0AR			0x780
+#define SQCH0DSC0AR_NXACT_TERM		0	/* Bit 28 */
+#define SQCH0DSC0AR_BTA			GENMASK(27, 26)
+#define SQCH0DSC0AR_BTA_NONE		0
+#define SQCH0DSC0AR_BTA_NON_READ	1
+#define SQCH0DSC0AR_BTA_READ		2
+#define SQCH0DSC0AR_BTA_ONLY		3
+#define SQCH0DSC0AR_SPD_HIGH		0
+#define SQCH0DSC0AR_SPD_LOW		BIT(25)
+#define SQCH0DSC0AR_FMT_SHORT		0
+#define SQCH0DSC0AR_FMT_LONG		BIT(24)
+#define SQCH0DSC0AR_DT			GENMASK(21, 16)
+#define SQCH0DSC0AR_DATA1		GENMASK(15, 8)
+#define SQCH0DSC0AR_DATA0		GENMASK(7, 0)
+
+/* Sequence Channel 0 Descriptor 0-B Register */
+#define SQCH0DSC0BR			0x784
+#define SQCH0DSC0BR_DTSEL_MEM_SPACE	BIT(24)	/* Use external memory */
+
+/* Sequence Channel 0 Descriptor 0-C Register */
+#define SQCH0DSC0CR			0x788
+#define SQCH0DSC0CR_FINACT		BIT(0)
+#define SQCH0DSC0CR_AUXOP		BIT(22)
+
+/* Sequence Channel 0 Descriptor 0-D Register */
+#define SQCH0DSC0DR			0x78c
+
 #endif /* __RZG2L_MIPI_DSI_REGS_H__ */
--
2.52.0



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

* [PATCH 5.10.y-cip 03/10] drm: renesas: rz-du: mipi_dsi: fix kernel panic when rebooting for some panels
  2026-04-15 18:17 [PATCH 5.10.y-cip 00/10] Add additional support for MIPI-DSI for RZ/G2L Chris Brandt
  2026-04-15 18:18 ` [PATCH 5.10.y-cip 01/10] drm: renesas: rz-du: Add atomic_pre_enable Chris Brandt
  2026-04-15 18:18 ` [PATCH 5.10.y-cip 02/10] drm: renesas: rz-du: Implement MIPI DSI host transfers Chris Brandt
@ 2026-04-15 18:18 ` Chris Brandt
  2026-04-15 18:18 ` [PATCH 5.10.y-cip 04/10] drm: renesas: rz-du: mipi_dsi: Set DSI divider Chris Brandt
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Chris Brandt @ 2026-04-15 18:18 UTC (permalink / raw)
  To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek

From: Hugo Villeneuve <hvilleneuve@dimonoff.com>

commit 64aa8b3a60a825134f7d866adf05c024bbe0c24c upstream.

Since commit 56de5e305d4b ("clk: renesas: r9a07g044: Add MSTOP for RZ/G2L")
we may get the following kernel panic, for some panels, when rebooting:

  systemd-shutdown[1]: Rebooting.
  Call trace:
   ...
   do_serror+0x28/0x68
   el1h_64_error_handler+0x34/0x50
   el1h_64_error+0x6c/0x70
   rzg2l_mipi_dsi_host_transfer+0x114/0x458 (P)
   mipi_dsi_device_transfer+0x44/0x58
   mipi_dsi_dcs_set_display_off_multi+0x9c/0xc4
   ili9881c_unprepare+0x38/0x88
   drm_panel_unprepare+0xbc/0x108

This happens for panels that need to send MIPI-DSI commands in their
unprepare() callback. Since the MIPI-DSI interface is stopped at that
point, rzg2l_mipi_dsi_host_transfer() triggers the kernel panic.

Fix by moving rzg2l_mipi_dsi_stop() to new callback function
rzg2l_mipi_dsi_atomic_post_disable().

With this change we now have the correct power-down/stop sequence:

  systemd-shutdown[1]: Rebooting.
  rzg2l-mipi-dsi 10850000.dsi: rzg2l_mipi_dsi_atomic_disable(): entry
  ili9881c-dsi 10850000.dsi.0: ili9881c_unprepare(): entry
  rzg2l-mipi-dsi 10850000.dsi: rzg2l_mipi_dsi_atomic_post_disable(): entry
  reboot: Restarting system

Suggested-by: Biju Das <biju.das.jz@bp.renesas.com>
Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
Tested-by: Biju Das <biju.das.jz@bp.renesas.com>
Link: https://patch.msgid.link/20260112154333.655352-1-hugo@hugovil.com
Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
Signed-off-by: Chris Brandt <chris.brandt@renesas.com>
---
 drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c | 8 ++++++++
 1 file changed, 8 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 2c1e4fdb2d92..ddb18767754c 100644
--- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
+++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
@@ -611,6 +611,13 @@ static void rzg2l_mipi_dsi_atomic_disable(struct drm_bridge *bridge,

 	rzg2l_mipi_dsi_stop_video(dsi);
 	rzg2l_mipi_dsi_stop_hs_clock(dsi);
+}
+
+static void rzg2l_mipi_dsi_atomic_post_disable(struct drm_bridge *bridge,
+					       struct drm_bridge_state *old_bridge_state)
+{
+	struct rzg2l_mipi_dsi *dsi = bridge_to_rzg2l_mipi_dsi(bridge);
+
 	rzg2l_mipi_dsi_stop(dsi);
 }

@@ -633,6 +640,7 @@ static const struct drm_bridge_funcs rzg2l_mipi_dsi_bridge_ops = {
 	.atomic_pre_enable = rzg2l_mipi_dsi_atomic_pre_enable,
 	.atomic_enable = rzg2l_mipi_dsi_atomic_enable,
 	.atomic_disable = rzg2l_mipi_dsi_atomic_disable,
+	.atomic_post_disable = rzg2l_mipi_dsi_atomic_post_disable,
 	.mode_valid = rzg2l_mipi_dsi_bridge_mode_valid,
 };

--
2.52.0



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

* [PATCH 5.10.y-cip 04/10] drm: renesas: rz-du: mipi_dsi: Set DSI divider
  2026-04-15 18:17 [PATCH 5.10.y-cip 00/10] Add additional support for MIPI-DSI for RZ/G2L Chris Brandt
                   ` (2 preceding siblings ...)
  2026-04-15 18:18 ` [PATCH 5.10.y-cip 03/10] drm: renesas: rz-du: mipi_dsi: fix kernel panic when rebooting for some panels Chris Brandt
@ 2026-04-15 18:18 ` Chris Brandt
  2026-04-15 18:18 ` [PATCH 5.10.y-cip 05/10] clk: renesas: Use IS_ERR() for pointers that cannot be NULL Chris Brandt
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Chris Brandt @ 2026-04-15 18:18 UTC (permalink / raw)
  To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek

commit fb797a70108f3fda83fde6dea30bee4be7d5df8b upstream.

Before the MIPI DSI clock source can be configured, the target divide
ratio needs to be set.

Signed-off-by: Chris Brandt <chris.brandt@renesas.com>
Reviewed-by: Biju Das <biju.das.jz@bp.renesas.com>
Tested-by: Biju Das <biju.das.jz@bp.renesas.com>
Fixes: 5a4326f2e3b1 ("clk: renesas: rzg2l: Remove DSI clock rate restrictions")
Link: https://patch.msgid.link/20260227015216.2721504-1-chris.brandt@renesas.com
Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
Signed-off-by: Chris Brandt <chris.brandt@renesas.com>
---
 drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

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 ddb18767754c..415143bb00be 100644
--- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
+++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
@@ -7,6 +7,7 @@

 #include <linux/bitfield.h>
 #include <linux/clk.h>
+#include <linux/clk/renesas.h>
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
 #include <linux/io.h>
@@ -652,6 +653,7 @@ static int rzg2l_mipi_dsi_host_attach(struct mipi_dsi_host *host,
 				      struct mipi_dsi_device *device)
 {
 	struct rzg2l_mipi_dsi *dsi = host_to_rzg2l_mipi_dsi(host);
+	int bpp;

 	if (device->lanes > dsi->num_data_lanes) {
 		dev_err(dsi->dev,
@@ -660,7 +662,8 @@ static int rzg2l_mipi_dsi_host_attach(struct mipi_dsi_host *host,
 		return -EINVAL;
 	}

-	switch (mipi_dsi_pixel_format_to_bpp(device->format)) {
+	bpp = mipi_dsi_pixel_format_to_bpp(device->format);
+	switch (bpp) {
 	case 24:
 	case 18:
 		break;
@@ -673,6 +676,18 @@ static int rzg2l_mipi_dsi_host_attach(struct mipi_dsi_host *host,
 	dsi->format = device->format;
 	dsi->mode_flags = device->mode_flags;

+	/*
+	 * Report the required division ratio setting for the MIPI clock dividers.
+	 *
+	 * vclk * bpp = hsclk * 8 * num_lanes
+	 *
+	 * vclk * DSI_AB_divider = hsclk * 16
+	 *
+	 *   which simplifies to...
+	 * DSI_AB_divider = bpp * 2 / num_lanes
+	 */
+	rzg2l_cpg_dsi_div_set_divider(bpp * 2 / dsi->lanes, PLL5_TARGET_DSI);
+
 	return 0;
 }

--
2.52.0



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

* [PATCH 5.10.y-cip 05/10] clk: renesas: Use IS_ERR() for pointers that cannot be NULL
  2026-04-15 18:17 [PATCH 5.10.y-cip 00/10] Add additional support for MIPI-DSI for RZ/G2L Chris Brandt
                   ` (3 preceding siblings ...)
  2026-04-15 18:18 ` [PATCH 5.10.y-cip 04/10] drm: renesas: rz-du: mipi_dsi: Set DSI divider Chris Brandt
@ 2026-04-15 18:18 ` Chris Brandt
  2026-04-16 21:08   ` Pavel Machek
  2026-04-15 18:18 ` [PATCH 5.10.y-cip 06/10] clk: renesas: rzg2l: Fix intin variable size Chris Brandt
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 13+ messages in thread
From: Chris Brandt @ 2026-04-15 18:18 UTC (permalink / raw)
  To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek

From: Geert Uytterhoeven <geert+renesas@glider.be>

commit 6a636d203cc8d29ae73116bbca8b0ea2c7a90d7f upstream.

The use of IS_ERR_OR_NULL() suggests that "clk" can be a NULL pointer.
Hence smatch assumes so, and issues a "passing zero to 'PTR_ERR'"
warning.

At these checkpoints, "clk" always contains either a valid pointer, or
an error pointer (none of the functions called return NULL pointers).
Hence replace IS_ERR_OR_NULL() by IS_ERR().

Reported-by: kernel test robot <lkp@intel.com>
Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
Closes: https://lore.kernel.org/r/202408032025.ve2JMaoV-lkp@intel.com/
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Reviewed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Link: https://patch.msgid.link/81260328acb5c78e915ab04afad3901a31c16128.1758793709.git.geert+renesas@glider.be
Signed-off-by: Chris Brandt <chris.brandt@renesas.com>
---
 drivers/clk/renesas/renesas-cpg-mssr.c | 2 +-
 drivers/clk/renesas/rzg2l-cpg.c        | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c
index a5a68e1e7549..e373ae4360a2 100644
--- a/drivers/clk/renesas/renesas-cpg-mssr.c
+++ b/drivers/clk/renesas/renesas-cpg-mssr.c
@@ -388,7 +388,7 @@ static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core,
 		break;
 	}

-	if (IS_ERR_OR_NULL(clk))
+	if (IS_ERR(clk))
 		goto fail;

 	dev_dbg(dev, "Core clock %pC at %lu Hz\n", clk, clk_get_rate(clk));
diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c
index a237150e5932..0c0d9d76c4d6 100644
--- a/drivers/clk/renesas/rzg2l-cpg.c
+++ b/drivers/clk/renesas/rzg2l-cpg.c
@@ -1183,7 +1183,7 @@ rzg2l_cpg_register_core_clk(const struct cpg_core_clk *core,
 		goto fail;
 	}

-	if (IS_ERR_OR_NULL(clk))
+	if (IS_ERR(clk))
 		goto fail;

 	dev_dbg(dev, "Core clock %pC at %lu Hz\n", clk, clk_get_rate(clk));
--
2.52.0



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

* [PATCH 5.10.y-cip 06/10] clk: renesas: rzg2l: Fix intin variable size
  2026-04-15 18:17 [PATCH 5.10.y-cip 00/10] Add additional support for MIPI-DSI for RZ/G2L Chris Brandt
                   ` (4 preceding siblings ...)
  2026-04-15 18:18 ` [PATCH 5.10.y-cip 05/10] clk: renesas: Use IS_ERR() for pointers that cannot be NULL Chris Brandt
@ 2026-04-15 18:18 ` Chris Brandt
  2026-04-15 18:18 ` [PATCH 5.10.y-cip 07/10] math64: New DIV_U64_ROUND_CLOSEST helper Chris Brandt
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Chris Brandt @ 2026-04-15 18:18 UTC (permalink / raw)
  To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek

[ Upstream commit a00655d98cd885472c311f01dff3e668d1288d0a ]

INTIN is a 12-bit register value, so u8 is too small.

Fixes: 1561380ee72f ("clk: renesas: rzg2l: Add FOUTPOSTDIV clk support")
Cc: stable@vger.kernel.org
Reported-by: Hugo Villeneuve <hugo@hugovil.com>
Closes: https://lore.kernel.org/20251107113058.f334957151d1a8dd94dd740b@hugovil.com
Signed-off-by: Chris Brandt <chris.brandt@renesas.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://patch.msgid.link/20251114193711.3277912-1-chris.brandt@renesas.com
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Chris Brandt <chris.brandt@renesas.com>
---
 drivers/clk/renesas/rzg2l-cpg.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c
index 0c0d9d76c4d6..c45c22190fcd 100644
--- a/drivers/clk/renesas/rzg2l-cpg.c
+++ b/drivers/clk/renesas/rzg2l-cpg.c
@@ -121,8 +121,8 @@ struct div_hw_data {

 struct rzg2l_pll5_param {
 	u32 pl5_fracin;
+	u16 pl5_intin;
 	u8 pl5_refdiv;
-	u8 pl5_intin;
 	u8 pl5_postdiv1;
 	u8 pl5_postdiv2;
 	u8 pl5_spread;
--
2.52.0



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

* [PATCH 5.10.y-cip 07/10] math64: New DIV_U64_ROUND_CLOSEST helper
  2026-04-15 18:17 [PATCH 5.10.y-cip 00/10] Add additional support for MIPI-DSI for RZ/G2L Chris Brandt
                   ` (5 preceding siblings ...)
  2026-04-15 18:18 ` [PATCH 5.10.y-cip 06/10] clk: renesas: rzg2l: Fix intin variable size Chris Brandt
@ 2026-04-15 18:18 ` Chris Brandt
  2026-04-15 18:18 ` [PATCH 5.10.y-cip 08/10] clk: renesas: rzg2l: Select correct div round macro Chris Brandt
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Chris Brandt @ 2026-04-15 18:18 UTC (permalink / raw)
  To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek

From: Pali Rohár <pali@kernel.org>

commit 2c861b73a23b1237bdd054b6023bb27f6747c2b9 upstream.

Provide DIV_U64_ROUND_CLOSEST helper which uses div_u64 to perform
division rounded to the closest integer using unsigned 64bit
dividend and unsigned 32bit divisor.

Reviewed-by: Marek Behún <kabel@kernel.org>
Signed-off-by: Pali Rohár <pali@kernel.org>
Signed-off-by: Marek Behún <kabel@kernel.org>
Link: https://lore.kernel.org/r/20220219152818.4319-2-kabel@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Chris Brandt <chris.brandt@renesas.com>
---
 include/linux/math64.h | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/include/linux/math64.h b/include/linux/math64.h
index 66deb1fdc2ef..1cc61d748e1f 100644
--- a/include/linux/math64.h
+++ b/include/linux/math64.h
@@ -281,6 +281,19 @@ u64 mul_u64_u64_div_u64(u64 a, u64 mul, u64 div);
 #define DIV64_U64_ROUND_CLOSEST(dividend, divisor)	\
 	({ u64 _tmp = (divisor); div64_u64((dividend) + _tmp / 2, _tmp); })

+/*
+ * DIV_U64_ROUND_CLOSEST - unsigned 64bit divide with 32bit divisor rounded to nearest integer
+ * @dividend: unsigned 64bit dividend
+ * @divisor: unsigned 32bit divisor
+ *
+ * Divide unsigned 64bit dividend by unsigned 32bit divisor
+ * and round to closest integer.
+ *
+ * Return: dividend / divisor rounded to nearest integer
+ */
+#define DIV_U64_ROUND_CLOSEST(dividend, divisor)	\
+	({ u32 _tmp = (divisor); div_u64((u64)(dividend) + _tmp / 2, _tmp); })
+
 /*
  * DIV_S64_ROUND_CLOSEST - signed 64bit divide with 32bit divisor rounded to nearest integer
  * @dividend: signed 64bit dividend
--
2.52.0



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

* [PATCH 5.10.y-cip 08/10] clk: renesas: rzg2l: Select correct div round macro
  2026-04-15 18:17 [PATCH 5.10.y-cip 00/10] Add additional support for MIPI-DSI for RZ/G2L Chris Brandt
                   ` (6 preceding siblings ...)
  2026-04-15 18:18 ` [PATCH 5.10.y-cip 07/10] math64: New DIV_U64_ROUND_CLOSEST helper Chris Brandt
@ 2026-04-15 18:18 ` Chris Brandt
  2026-04-15 18:18 ` [PATCH 5.10.y-cip 09/10] clk: renesas: rzg2l: Remove DSI clock rate restrictions Chris Brandt
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Chris Brandt @ 2026-04-15 18:18 UTC (permalink / raw)
  To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek

[ Upstream commit f9451374dcfdfe669ee55b58ee6c11e8638980e4 ]

Variable foutvco_rate is an unsigned long, not an unsigned long long.

Cc: stable@kernel.org
Reported-by: Geert Uytterhoeven <geert+renesas@glider.be>
Closes: https://lore.kernel.org/CAMuHMdVf7dSeqAhtyxDCFuCheQRzwS-8996Rr2Ntui21uiBgdA@mail.gmail.com
Fixes: dabf72b85f29 ("clk: renesas: rzg2l: Fix FOUTPOSTDIV clk")
Signed-off-by: Chris Brandt <chris.brandt@renesas.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://patch.msgid.link/20251114194529.3304361-1-chris.brandt@renesas.com
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Chris Brandt <chris.brandt@renesas.com>
---
 drivers/clk/renesas/rzg2l-cpg.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c
index c45c22190fcd..d83755e273d9 100644
--- a/drivers/clk/renesas/rzg2l-cpg.c
+++ b/drivers/clk/renesas/rzg2l-cpg.c
@@ -575,8 +575,8 @@ rzg2l_cpg_get_foutpostdiv_rate(struct rzg2l_pll5_param *params,
 	foutvco_rate = div_u64(mul_u32_u32(EXTAL_FREQ_IN_MEGA_HZ * MEGA,
 					   (params->pl5_intin << 24) + params->pl5_fracin),
 			       params->pl5_refdiv) >> 24;
-	foutpostdiv_rate = DIV_ROUND_CLOSEST_ULL(foutvco_rate,
-						 params->pl5_postdiv1 * params->pl5_postdiv2);
+	foutpostdiv_rate = DIV_ROUND_CLOSEST(foutvco_rate,
+					     params->pl5_postdiv1 * params->pl5_postdiv2);

 	return foutpostdiv_rate;
 }
--
2.52.0



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

* [PATCH 5.10.y-cip 09/10] clk: renesas: rzg2l: Remove DSI clock rate restrictions
  2026-04-15 18:17 [PATCH 5.10.y-cip 00/10] Add additional support for MIPI-DSI for RZ/G2L Chris Brandt
                   ` (7 preceding siblings ...)
  2026-04-15 18:18 ` [PATCH 5.10.y-cip 08/10] clk: renesas: rzg2l: Select correct div round macro Chris Brandt
@ 2026-04-15 18:18 ` Chris Brandt
  2026-04-15 18:18 ` [PATCH 5.10.y-cip 10/10] clk: renesas: Add missing log message terminators Chris Brandt
  2026-04-16 21:09 ` [cip-dev] [PATCH 5.10.y-cip 00/10] Add additional support for MIPI-DSI for RZ/G2L Pavel Machek
  10 siblings, 0 replies; 13+ messages in thread
From: Chris Brandt @ 2026-04-15 18:18 UTC (permalink / raw)
  To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek

commit 5a4326f2e3b1edfb3329c1bee59035dc9f048b59 upstream.

Convert the limited MIPI clock calculations to a full range of settings
based on math including H/W limitation validation.
Since the required DSI division setting must be specified from external
sources before calculations, expose a new API to set it.

Signed-off-by: Chris Brandt <chris.brandt@renesas.com>
Reviewed-by: Biju Das <biju.das.jz@bp.renesas.com>
Tested-by: Biju Das <biju.das.jz@bp.renesas.com>
Reviewed-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
Tested-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://patch.msgid.link/20251124131003.992554-2-chris.brandt@renesas.com
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Chris Brandt <chris.brandt@renesas.com>
---
 drivers/clk/renesas/rzg2l-cpg.c | 174 ++++++++++++++++++++++++++------
 include/linux/clk/renesas.h     |  12 +++
 2 files changed, 155 insertions(+), 31 deletions(-)

diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c
index d83755e273d9..70ddfc917a17 100644
--- a/drivers/clk/renesas/rzg2l-cpg.c
+++ b/drivers/clk/renesas/rzg2l-cpg.c
@@ -21,6 +21,7 @@
 #include <linux/device.h>
 #include <linux/init.h>
 #include <linux/iopoll.h>
+#include <linux/math64.h>
 #include <linux/mod_devicetable.h>
 #include <linux/module.h>
 #include <linux/of_address.h>
@@ -73,6 +74,17 @@
 #define MSTOP_OFF(conf)		FIELD_GET(GENMASK(31, 16), (conf))
 #define MSTOP_MASK(conf)	FIELD_GET(GENMASK(15, 0), (conf))

+#define PLL5_FOUTVCO_MIN	800000000
+#define PLL5_FOUTVCO_MAX	3000000000
+#define PLL5_POSTDIV_MIN	1
+#define PLL5_POSTDIV_MAX	7
+#define PLL5_REFDIV_MIN		1
+#define PLL5_REFDIV_MAX		2
+#define PLL5_INTIN_MIN		20
+#define PLL5_INTIN_MAX		320
+#define PLL5_HSCLK_MIN		10000000
+#define PLL5_HSCLK_MAX		187500000
+
 /**
  * struct clk_hw_data - clock hardware data
  * @hw: clock hw
@@ -128,6 +140,12 @@ struct rzg2l_pll5_param {
 	u8 pl5_spread;
 };

+/* PLL5 output will be used for DPI or MIPI-DSI */
+static int dsi_div_target = PLL5_TARGET_DPI;
+
+/* Required division ratio for MIPI D-PHY clock depending on number of lanes and bpp. */
+static u8 dsi_div_ab_desired;
+
 struct rzg2l_pll5_mux_dsi_div_param {
 	u8 clksrc;
 	u8 dsi_div_a;
@@ -169,6 +187,11 @@ struct rzg2l_cpg_priv {
 	struct rzg2l_pll5_mux_dsi_div_param mux_dsi_div_params;
 };

+static inline u8 rzg2l_cpg_div_ab(u8 a, u8 b)
+{
+	return (b + 1) << a;
+}
+
 static void rzg2l_cpg_del_clk_provider(void *data)
 {
 	of_clk_del_provider(data);
@@ -559,24 +582,121 @@ rzg2l_cpg_sd_mux_clk_register(const struct cpg_core_clk *core,
 	return clk_hw->clk;
 }

+/*
+ * VCO-->[POSTDIV1,2]--FOUTPOSTDIV--------------->|
+ *                          |                     |-->[1/(DSI DIV A * B)]--> MIPI_DSI_VCLK
+ *                          |-->[1/2]--FOUT1PH0-->|
+ *                          |
+ *                          |------->[1/16]--------------------------------> hsclk (MIPI-PHY)
+ */
 static unsigned long
-rzg2l_cpg_get_foutpostdiv_rate(struct rzg2l_pll5_param *params,
+rzg2l_cpg_get_foutpostdiv_rate(struct rzg2l_cpg_priv *priv,
+			       struct rzg2l_pll5_param *params,
 			       unsigned long rate)
 {
-	unsigned long foutpostdiv_rate, foutvco_rate;
+	const u32 extal_hz = EXTAL_FREQ_IN_MEGA_HZ * MEGA;
+	unsigned long foutpostdiv_rate;
+	unsigned int a, b, odd;
+	unsigned long hsclk;
+	u8 dsi_div_ab_calc;
+	u64 foutvco_rate;
+
+	if (dsi_div_target == PLL5_TARGET_DSI) {
+		/* Check hsclk */
+		hsclk = rate * dsi_div_ab_desired / 16;
+		if (hsclk < PLL5_HSCLK_MIN || hsclk > PLL5_HSCLK_MAX) {
+			dev_err(priv->dev, "hsclk out of range\n");
+			return 0;
+		}
+
+		/* Determine the correct clock source based on even/odd of the divider */
+		odd = dsi_div_ab_desired & 1;
+		if (odd) {
+			priv->mux_dsi_div_params.clksrc = 0;	/* FOUTPOSTDIV */
+			dsi_div_ab_calc = dsi_div_ab_desired;
+		} else {
+			priv->mux_dsi_div_params.clksrc = 1;	/*  FOUT1PH0 */
+			dsi_div_ab_calc = dsi_div_ab_desired / 2;
+		}
+
+		/* Calculate the DIV_DSI_A and DIV_DSI_B based on the desired divider */
+		for (a = 0; a < 4; a++) {
+			/* FOUT1PH0: Max output of DIV_DSI_A is 750MHz so at least 1/2 to be safe */
+			if (!odd && a == 0)
+				continue;
+
+			/* FOUTPOSTDIV: DIV_DSI_A must always be 1/1 */
+			if (odd && a != 0)
+				break;
+
+			for (b = 0; b < 16; b++) {
+				/* FOUTPOSTDIV: DIV_DSI_B must always be odd divider 1/(b+1) */
+				if (odd && b & 1)
+					continue;
+
+				if (rzg2l_cpg_div_ab(a, b) == dsi_div_ab_calc) {
+					priv->mux_dsi_div_params.dsi_div_a = a;
+					priv->mux_dsi_div_params.dsi_div_b = b;
+					goto calc_pll_clk;
+				}
+			}
+		}
+
+		dev_err(priv->dev, "Failed to calculate DIV_DSI_A,B\n");
+
+		return 0;
+	} else if (dsi_div_target == PLL5_TARGET_DPI) {
+		/* Fixed settings for DPI */
+		priv->mux_dsi_div_params.clksrc = 0;
+		priv->mux_dsi_div_params.dsi_div_a = 3; /* Divided by 8 */
+		priv->mux_dsi_div_params.dsi_div_b = 0; /* Divided by 1 */
+		dsi_div_ab_desired = rzg2l_cpg_div_ab(priv->mux_dsi_div_params.dsi_div_a,
+						      priv->mux_dsi_div_params.dsi_div_b);
+	}
+
+calc_pll_clk:
+	/* PLL5 (MIPI_DSI_PLLCLK) = VCO / POSTDIV1 / POSTDIV2 */
+	for (params->pl5_postdiv1 = PLL5_POSTDIV_MIN;
+	     params->pl5_postdiv1 <= PLL5_POSTDIV_MAX;
+	     params->pl5_postdiv1++) {
+		for (params->pl5_postdiv2 = PLL5_POSTDIV_MIN;
+		     params->pl5_postdiv2 <= PLL5_POSTDIV_MAX;
+		     params->pl5_postdiv2++) {
+			foutvco_rate = rate * params->pl5_postdiv1 * params->pl5_postdiv2 *
+				       dsi_div_ab_desired;
+			if (foutvco_rate <= PLL5_FOUTVCO_MIN || foutvco_rate >= PLL5_FOUTVCO_MAX)
+				continue;
+
+			for (params->pl5_refdiv = PLL5_REFDIV_MIN;
+			     params->pl5_refdiv <= PLL5_REFDIV_MAX;
+			     params->pl5_refdiv++) {
+				u32 rem;
+
+				params->pl5_intin = div_u64_rem(foutvco_rate * params->pl5_refdiv,
+								extal_hz, &rem);
+
+				if (params->pl5_intin < PLL5_INTIN_MIN ||
+				    params->pl5_intin > PLL5_INTIN_MAX)
+					continue;
+
+				params->pl5_fracin = div_u64((u64)rem << 24, extal_hz);
+
+				goto clk_valid;
+			}
+		}
+	}

-	params->pl5_intin = rate / MEGA;
-	params->pl5_fracin = div_u64(((u64)rate % MEGA) << 24, MEGA);
-	params->pl5_refdiv = 2;
-	params->pl5_postdiv1 = 1;
-	params->pl5_postdiv2 = 1;
+	dev_err(priv->dev, "Failed to calculate PLL5 settings\n");
+	return 0;
+
+clk_valid:
 	params->pl5_spread = 0x16;

 	foutvco_rate = div_u64(mul_u32_u32(EXTAL_FREQ_IN_MEGA_HZ * MEGA,
 					   (params->pl5_intin << 24) + params->pl5_fracin),
 			       params->pl5_refdiv) >> 24;
-	foutpostdiv_rate = DIV_ROUND_CLOSEST(foutvco_rate,
-					     params->pl5_postdiv1 * params->pl5_postdiv2);
+	foutpostdiv_rate = DIV_U64_ROUND_CLOSEST(foutvco_rate,
+						 params->pl5_postdiv1 * params->pl5_postdiv2);

 	return foutpostdiv_rate;
 }
@@ -610,7 +730,7 @@ static unsigned long rzg2l_cpg_get_vclk_parent_rate(struct clk_hw *hw,
 	struct rzg2l_pll5_param params;
 	unsigned long parent_rate;

-	parent_rate = rzg2l_cpg_get_foutpostdiv_rate(&params, rate);
+	parent_rate = rzg2l_cpg_get_foutpostdiv_rate(priv, &params, rate);

 	if (priv->mux_dsi_div_params.clksrc)
 		parent_rate /= 2;
@@ -626,9 +746,19 @@ static int rzg2l_cpg_dsi_div_determine_rate(struct clk_hw *hw,

 	req->best_parent_rate = rzg2l_cpg_get_vclk_parent_rate(hw, req->rate);

+	if (!req->best_parent_rate)
+		return -EINVAL;
+
 	return 0;
 }

+void rzg2l_cpg_dsi_div_set_divider(u8 divider, int target)
+{
+	dsi_div_ab_desired = divider;
+	dsi_div_target = target;
+}
+EXPORT_SYMBOL_GPL(rzg2l_cpg_dsi_div_set_divider);
+
 static int rzg2l_cpg_dsi_div_set_rate(struct clk_hw *hw,
 				      unsigned long rate,
 				      unsigned long parent_rate)
@@ -800,22 +930,6 @@ struct sipll5 {

 #define to_sipll5(_hw)	container_of(_hw, struct sipll5, hw)

-static unsigned long rzg2l_cpg_get_vclk_rate(struct clk_hw *hw,
-					     unsigned long rate)
-{
-	struct sipll5 *sipll5 = to_sipll5(hw);
-	struct rzg2l_cpg_priv *priv = sipll5->priv;
-	unsigned long vclk;
-
-	vclk = rate / ((1 << priv->mux_dsi_div_params.dsi_div_a) *
-		       (priv->mux_dsi_div_params.dsi_div_b + 1));
-
-	if (priv->mux_dsi_div_params.clksrc)
-		vclk /= 2;
-
-	return vclk;
-}
-
 static unsigned long rzg2l_cpg_sipll5_recalc_rate(struct clk_hw *hw,
 						  unsigned long parent_rate)
 {
@@ -861,9 +975,9 @@ static int rzg2l_cpg_sipll5_set_rate(struct clk_hw *hw,
 	if (!rate)
 		return -EINVAL;

-	vclk_rate = rzg2l_cpg_get_vclk_rate(hw, rate);
+	vclk_rate = rate / dsi_div_ab_desired;
 	sipll5->foutpostdiv_rate =
-		rzg2l_cpg_get_foutpostdiv_rate(&params, vclk_rate);
+		rzg2l_cpg_get_foutpostdiv_rate(priv, &params, vclk_rate);

 	/* Put PLL5 into standby mode */
 	writel(CPG_SIPLL5_STBY_RESETB_WEN, priv->base + CPG_SIPLL5_STBY);
@@ -951,9 +1065,7 @@ rzg2l_cpg_sipll5_register(const struct cpg_core_clk *core,
 	if (ret)
 		return ERR_PTR(ret);

-	priv->mux_dsi_div_params.clksrc = 1; /* Use clk src 1 for DSI */
-	priv->mux_dsi_div_params.dsi_div_a = 1; /* Divided by 2 */
-	priv->mux_dsi_div_params.dsi_div_b = 2; /* Divided by 3 */
+	rzg2l_cpg_dsi_div_set_divider(8, PLL5_TARGET_DPI);

 	return clk_hw->clk;
 }
diff --git a/include/linux/clk/renesas.h b/include/linux/clk/renesas.h
index 0ebbe2f0b45e..96f54becfa4b 100644
--- a/include/linux/clk/renesas.h
+++ b/include/linux/clk/renesas.h
@@ -32,4 +32,16 @@ void cpg_mssr_detach_dev(struct generic_pm_domain *unused, struct device *dev);
 #define cpg_mssr_attach_dev	NULL
 #define cpg_mssr_detach_dev	NULL
 #endif
+
+enum {
+	PLL5_TARGET_DPI,
+	PLL5_TARGET_DSI
+};
+
+#ifdef CONFIG_CLK_RZG2L
+void rzg2l_cpg_dsi_div_set_divider(u8 divider, int target);
+#else
+static inline void rzg2l_cpg_dsi_div_set_divider(u8 divider, int target) { }
+#endif
+
 #endif
--
2.52.0



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

* [PATCH 5.10.y-cip 10/10] clk: renesas: Add missing log message terminators
  2026-04-15 18:17 [PATCH 5.10.y-cip 00/10] Add additional support for MIPI-DSI for RZ/G2L Chris Brandt
                   ` (8 preceding siblings ...)
  2026-04-15 18:18 ` [PATCH 5.10.y-cip 09/10] clk: renesas: rzg2l: Remove DSI clock rate restrictions Chris Brandt
@ 2026-04-15 18:18 ` Chris Brandt
  2026-04-16 21:09 ` [cip-dev] [PATCH 5.10.y-cip 00/10] Add additional support for MIPI-DSI for RZ/G2L Pavel Machek
  10 siblings, 0 replies; 13+ messages in thread
From: Chris Brandt @ 2026-04-15 18:18 UTC (permalink / raw)
  To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek

From: Geert Uytterhoeven <geert+renesas@glider.be>

commit 4fef3fd633be4a1a18c490a63f4131284f6ee0f4 upstream.

Complete printed messages should be terminated by newline characters.

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Reviewed-by: Brian Masney <bmasney@redhat.com>
Link: https://patch.msgid.link/cd0b3624066b80ed0bb00d489c99e2c1a06d755f.1768480559.git.geert+renesas@glider.be
Signed-off-by: Chris Brandt <chris.brandt@renesas.com>
---
 drivers/clk/renesas/clk-vbattb.c       | 4 ++--
 drivers/clk/renesas/renesas-cpg-mssr.c | 2 +-
 drivers/clk/renesas/rzg2l-cpg.c        | 6 +++---
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/clk/renesas/clk-vbattb.c b/drivers/clk/renesas/clk-vbattb.c
index a5f9b736ef2c..afedc099405e 100644
--- a/drivers/clk/renesas/clk-vbattb.c
+++ b/drivers/clk/renesas/clk-vbattb.c
@@ -69,11 +69,11 @@ static void vbattb_clk_action(void *data)

 	ret = reset_control_assert(rstc);
 	if (ret)
-		dev_err(dev, "Failed to de-assert reset!");
+		dev_err(dev, "Failed to de-assert reset!\n");

 	ret = pm_runtime_put_sync(dev);
 	if (ret < 0)
-		dev_err(dev, "Failed to runtime suspend!");
+		dev_err(dev, "Failed to runtime suspend!\n");

 	of_clk_del_provider(dev->of_node);
 }
diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c
index e373ae4360a2..17b7e29a900c 100644
--- a/drivers/clk/renesas/renesas-cpg-mssr.c
+++ b/drivers/clk/renesas/renesas-cpg-mssr.c
@@ -314,7 +314,7 @@ struct clk *cpg_mssr_clk_src_twocell_get(struct of_phandle_args *clkspec,
 	}

 	if (IS_ERR(clk))
-		dev_err(dev, "Cannot get %s clock %u: %ld", type, clkidx,
+		dev_err(dev, "Cannot get %s clock %u: %ld\n", type, clkidx,
 		       PTR_ERR(clk));
 	else
 		dev_dbg(dev, "clock (%u, %u) is %pC at %lu Hz\n",
diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c
index 70ddfc917a17..8cb0403b43c3 100644
--- a/drivers/clk/renesas/rzg2l-cpg.c
+++ b/drivers/clk/renesas/rzg2l-cpg.c
@@ -984,7 +984,7 @@ static int rzg2l_cpg_sipll5_set_rate(struct clk_hw *hw,
 	ret = readl_poll_timeout(priv->base + CPG_SIPLL5_MON, val,
 				 !(val & CPG_SIPLL5_MON_PLL5_LOCK), 100, 250000);
 	if (ret) {
-		dev_err(priv->dev, "failed to release pll5 lock");
+		dev_err(priv->dev, "failed to release pll5 lock\n");
 		return ret;
 	}

@@ -1011,7 +1011,7 @@ static int rzg2l_cpg_sipll5_set_rate(struct clk_hw *hw,
 	ret = readl_poll_timeout(priv->base + CPG_SIPLL5_MON, val,
 				 (val & CPG_SIPLL5_MON_PLL5_LOCK), 100, 250000);
 	if (ret) {
-		dev_err(priv->dev, "failed to lock pll5");
+		dev_err(priv->dev, "failed to lock pll5\n");
 		return ret;
 	}

@@ -1217,7 +1217,7 @@ static struct clk
 	}

 	if (IS_ERR(clk))
-		dev_err(dev, "Cannot get %s clock %u: %ld", type, clkidx,
+		dev_err(dev, "Cannot get %s clock %u: %ld\n", type, clkidx,
 			PTR_ERR(clk));
 	else
 		dev_dbg(dev, "clock (%u, %u) is %pC at %lu Hz\n",
--
2.52.0



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

* Re: [PATCH 5.10.y-cip 05/10] clk: renesas: Use IS_ERR() for pointers that cannot be NULL
  2026-04-15 18:18 ` [PATCH 5.10.y-cip 05/10] clk: renesas: Use IS_ERR() for pointers that cannot be NULL Chris Brandt
@ 2026-04-16 21:08   ` Pavel Machek
  0 siblings, 0 replies; 13+ messages in thread
From: Pavel Machek @ 2026-04-16 21:08 UTC (permalink / raw)
  To: Chris Brandt; +Cc: cip-dev, Nobuhiro Iwamatsu, Pavel Machek

[-- Attachment #1: Type: text/plain, Size: 1186 bytes --]

Hi!

> From: Geert Uytterhoeven <geert+renesas@glider.be>
> 
> commit 6a636d203cc8d29ae73116bbca8b0ea2c7a90d7f upstream.
> 
> The use of IS_ERR_OR_NULL() suggests that "clk" can be a NULL pointer.
> Hence smatch assumes so, and issues a "passing zero to 'PTR_ERR'"
> warning.
> 
> At these checkpoints, "clk" always contains either a valid pointer, or
> an error pointer (none of the functions called return NULL pointers).
> Hence replace IS_ERR_OR_NULL() by IS_ERR().
> 
> Reported-by: kernel test robot <lkp@intel.com>
> Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
> Closes: https://lore.kernel.org/r/202408032025.ve2JMaoV-lkp@intel.com/
> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
> Reviewed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> Link:
> https://patch.msgid.link/81260328acb5c78e915ab04afad3901a31c16128.1758793709.git.geert+renesas@glider.be
[<-- here -->]
> Signed-off-by: Chris Brandt <chris.brandt@renesas.com>

Apparently, this one is different from upstream. That is okay, but
note saying [dropped this because that] would be welcome before your
signoff.

Thanks and best regards,
							Pavel

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

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

* Re: [cip-dev] [PATCH 5.10.y-cip 00/10] Add additional support for MIPI-DSI for RZ/G2L
  2026-04-15 18:17 [PATCH 5.10.y-cip 00/10] Add additional support for MIPI-DSI for RZ/G2L Chris Brandt
                   ` (9 preceding siblings ...)
  2026-04-15 18:18 ` [PATCH 5.10.y-cip 10/10] clk: renesas: Add missing log message terminators Chris Brandt
@ 2026-04-16 21:09 ` Pavel Machek
  10 siblings, 0 replies; 13+ messages in thread
From: Pavel Machek @ 2026-04-16 21:09 UTC (permalink / raw)
  To: Chris.Brandt; +Cc: cip-dev, Nobuhiro Iwamatsu, Pavel Machek

[-- Attachment #1: Type: text/plain, Size: 751 bytes --]

Hi!

> There is important functionality missing from the MIPI-DSI display driver and also the clock
> driver for generating the correct pixel clock frequencies.
> 
> Since everything is now accepted in mainline, this is the backport of those patches.

So MIPI-DSI does not work at all in 5.10-cip, or it only works with
some panels and this adds support for more panels or ...?

As with 6.1 and 6.12 versions, I had some minor comments, but those
should be fixed in mainline, first, so they should not block the
merge.

Reviewed-by: Pavel Machek <pavel@nabladev.com>

I can apply the series if it passes testing and there are no other
comments.

Best regards,
                                                                Pavel

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

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

end of thread, other threads:[~2026-04-16 21:09 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-15 18:17 [PATCH 5.10.y-cip 00/10] Add additional support for MIPI-DSI for RZ/G2L Chris Brandt
2026-04-15 18:18 ` [PATCH 5.10.y-cip 01/10] drm: renesas: rz-du: Add atomic_pre_enable Chris Brandt
2026-04-15 18:18 ` [PATCH 5.10.y-cip 02/10] drm: renesas: rz-du: Implement MIPI DSI host transfers Chris Brandt
2026-04-15 18:18 ` [PATCH 5.10.y-cip 03/10] drm: renesas: rz-du: mipi_dsi: fix kernel panic when rebooting for some panels Chris Brandt
2026-04-15 18:18 ` [PATCH 5.10.y-cip 04/10] drm: renesas: rz-du: mipi_dsi: Set DSI divider Chris Brandt
2026-04-15 18:18 ` [PATCH 5.10.y-cip 05/10] clk: renesas: Use IS_ERR() for pointers that cannot be NULL Chris Brandt
2026-04-16 21:08   ` Pavel Machek
2026-04-15 18:18 ` [PATCH 5.10.y-cip 06/10] clk: renesas: rzg2l: Fix intin variable size Chris Brandt
2026-04-15 18:18 ` [PATCH 5.10.y-cip 07/10] math64: New DIV_U64_ROUND_CLOSEST helper Chris Brandt
2026-04-15 18:18 ` [PATCH 5.10.y-cip 08/10] clk: renesas: rzg2l: Select correct div round macro Chris Brandt
2026-04-15 18:18 ` [PATCH 5.10.y-cip 09/10] clk: renesas: rzg2l: Remove DSI clock rate restrictions Chris Brandt
2026-04-15 18:18 ` [PATCH 5.10.y-cip 10/10] clk: renesas: Add missing log message terminators Chris Brandt
2026-04-16 21:09 ` [cip-dev] [PATCH 5.10.y-cip 00/10] Add additional support for MIPI-DSI for RZ/G2L Pavel Machek

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