Devicetree
 help / color / mirror / Atom feed
* [PATCH v12 2/2] phy: qcom-mipi-csi2: Add a CSI2 MIPI DPHY driver
From: Bryan O'Donoghue @ 2026-07-19 13:47 UTC (permalink / raw)
  To: Vinod Koul, Kishon Vijay Abraham I, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Neil Armstrong
  Cc: Bryan O'Donoghue, Vladimir Zapolskiy, linux-arm-msm,
	linux-phy, linux-media, devicetree, linux-kernel,
	Bryan O'Donoghue
In-Reply-To: <20260719-x1e-csi2-phy-v12-0-cc7311326d1b@linaro.org>

Add a new MIPI CSI2 driver in DPHY mode initially. The entire set of
existing CAMSS CSI PHY init sequences are imported in order to save time
and effort in later patches.

The following devices are supported in this drop:
"qcom,x1e80100-csi2-phy"

In-line with other PHY drivers the process node is included in the name.
Data-lane and clock lane positioning and polarity selection via newly
amended struct phy_configure_opts_mipi_dphy{} is supported.

The Qualcomm 3PH class of PHYs can do both DPHY and CPHY mode. For now only
DPHY is supported.

In porting some of the logic over from camss-csiphy*.c to here its also
possible to rationalise some of the code.

In particular use of regulator_bulk and clk_bulk as well as dropping the
seemingly useless and unused interrupt handler.

The PHY sequences and a lot of the logic that goes with them are well
proven in CAMSS and mature so the main thing to watch out for here is how
to get the right sequencing of regulators, clocks and register-writes.

The register init sequence table is imported verbatim from the existing
CAMSS csiphy driver. A follow-up series will rework the table to extract
the repetitive per-lane pattern into a loop.

Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
---
 MAINTAINERS                                        |  10 +
 drivers/phy/qualcomm/Kconfig                       |  14 +
 drivers/phy/qualcomm/Makefile                      |   5 +
 drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c | 386 ++++++++++++++++++
 drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c     | 446 +++++++++++++++++++++
 drivers/phy/qualcomm/phy-qcom-mipi-csi2.h          |  97 +++++
 6 files changed, 958 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 15011f5752a99..a203b41475ea4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -22296,6 +22296,16 @@ S:	Maintained
 F:	Documentation/devicetree/bindings/media/qcom,*-iris.yaml
 F:	drivers/media/platform/qcom/iris/
 
+QUALCOMM MIPI CSI2 PHY DRIVER
+M:	Bryan O'Donoghue <bod@kernel.org>
+L:	linux-phy@lists.infradead.org
+L:	linux-media@vger.kernel.org
+L:	linux-arm-msm@vger.kernel.org
+S:	Maintained
+F:	Documentation/devicetree/bindings/phy/qcom,*-csi2-phy.yaml
+F:	drivers/phy/qualcomm/phy-qcom-mipi-csi2*.c
+F:	drivers/phy/qualcomm/phy-qcom-mipi-csi2*.h
+
 QUALCOMM NAND CONTROLLER DRIVER
 M:	Manivannan Sadhasivam <mani@kernel.org>
 L:	linux-mtd@lists.infradead.org
diff --git a/drivers/phy/qualcomm/Kconfig b/drivers/phy/qualcomm/Kconfig
index 60a0ead127fa9..779a3511ba852 100644
--- a/drivers/phy/qualcomm/Kconfig
+++ b/drivers/phy/qualcomm/Kconfig
@@ -28,6 +28,20 @@ config PHY_QCOM_EDP
 	  Enable this driver to support the Qualcomm eDP PHY found in various
 	  Qualcomm chipsets.
 
+config PHY_QCOM_MIPI_CSI2
+	tristate "Qualcomm MIPI CSI2 PHY driver"
+	depends on ARCH_QCOM || COMPILE_TEST
+	depends on OF
+	depends on PM
+	depends on COMMON_CLK
+	select GENERIC_PHY
+	select GENERIC_PHY_MIPI_DPHY
+	help
+	  Enable this to support the MIPI CSI2 PHY driver found in various
+	  Qualcomm chipsets. This PHY is used to connect MIPI CSI2
+	  camera sensors to the CSI Decoder in the Qualcomm Camera Subsystem
+	  CAMSS.
+
 config PHY_QCOM_IPQ4019_USB
 	tristate "Qualcomm IPQ4019 USB PHY driver"
 	depends on OF && (ARCH_QCOM || COMPILE_TEST)
diff --git a/drivers/phy/qualcomm/Makefile b/drivers/phy/qualcomm/Makefile
index b71a6a0bed3f1..382cb594b06b6 100644
--- a/drivers/phy/qualcomm/Makefile
+++ b/drivers/phy/qualcomm/Makefile
@@ -6,6 +6,11 @@ obj-$(CONFIG_PHY_QCOM_IPQ4019_USB)	+= phy-qcom-ipq4019-usb.o
 obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA)	+= phy-qcom-ipq806x-sata.o
 obj-$(CONFIG_PHY_QCOM_M31_USB)		+= phy-qcom-m31.o
 obj-$(CONFIG_PHY_QCOM_M31_EUSB)		+= phy-qcom-m31-eusb2.o
+
+phy-qcom-mipi-csi2-objs			+= phy-qcom-mipi-csi2-core.o \
+					   phy-qcom-mipi-csi2-3ph-dphy.o
+obj-$(CONFIG_PHY_QCOM_MIPI_CSI2)	+= phy-qcom-mipi-csi2.o
+
 obj-$(CONFIG_PHY_QCOM_PCIE2)		+= phy-qcom-pcie2.o
 
 obj-$(CONFIG_PHY_QCOM_QMP_COMBO)	+= phy-qcom-qmp-combo.o phy-qcom-qmp-usbc.o
diff --git a/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c
new file mode 100644
index 0000000000000..6495aed5b9a5f
--- /dev/null
+++ b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c
@@ -0,0 +1,386 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Qualcomm MSM Camera Subsystem - CSIPHY Module 3phase v1.0
+ *
+ * Copyright (c) 2011-2015, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2016-2026 Linaro Ltd.
+ */
+
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/time64.h>
+
+#include "phy-qcom-mipi-csi2.h"
+
+#define CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(offset, n)	((offset) + 0x4 * (n))
+#define CSIPHY_3PH_CMN_CSI_COMMON_CTRL0_PHY_SW_RESET	BIT(0)
+#define CSIPHY_3PH_CMN_CSI_COMMON_CTRL5_CLK_ENABLE	BIT(7)
+#define CSIPHY_3PH_CMN_CSI_COMMON_CTRL6_COMMON_PWRDN_B	BIT(0)
+#define CSIPHY_3PH_CMN_CSI_COMMON_CTRL6_SHOW_REV_ID	BIT(1)
+#define CSIPHY_3PH_CMN_CSI_COMMON_CTRL10_IRQ_CLEAR_CMD	BIT(0)
+#define CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(offset, n)	((offset) + 0xb0 + 0x4 * (n))
+
+#define CSIPHY_2PH_LN_CSI_2PHASE_CTRL9n(n)		((0x200 * (n)) + 0x24)
+
+/*
+ * 3 phase CSI has 19 common status regs with only 0-10 being used
+ * and 11-18 being reserved.
+ */
+#define CSI_COMMON_STATUS_NUM				11
+/*
+ * There are a number of common control registers
+ * The offset to clear the CSIPHY IRQ status starts @ 22
+ * So to clear CSI_COMMON_STATUS0 this is CSI_COMMON_CONTROL22, STATUS1 is
+ * CONTROL23 and so on
+ */
+#define CSI_CTRL_STATUS_INDEX				22
+
+/*
+ * There are 43 COMMON_CTRL registers with regs after # 33 being reserved
+ */
+#define CSI_CTRL_MAX					33
+
+#define CSIPHY_DEFAULT_PARAMS				0
+#define CSIPHY_SETTLE_CNT_LOWER_BYTE			2
+#define CSIPHY_SKEW_CAL					7
+
+/* 4nm 2PH v 2.1.2 2p5Gbps 4 lane DPHY mode */
+static const struct
+mipi_csi2phy_lane_regs lane_regs_x1e80100[] = {
+	/* Power up lanes 2ph mode */
+	{.reg_addr = 0x101c, .reg_data = 0x7a, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x1018, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS},
+
+	{.reg_addr = 0x0094, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x00a0, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0090, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0098, .reg_data = 0x08, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0094, .reg_data = 0x07, .delay_us = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0030, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0000, .reg_data = 0x8e, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0038, .reg_data = 0xfe, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x002c, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0034, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x001c, .reg_data = 0x0a, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0014, .reg_data = 0x60, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x003c, .reg_data = 0xb8, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0004, .reg_data = 0x0c, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0020, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0008, .reg_data = 0x10, .param_type = CSIPHY_SETTLE_CNT_LOWER_BYTE},
+	{.reg_addr = 0x0010, .reg_data = 0x52, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0094, .reg_data = 0xd7, .param_type = CSIPHY_SKEW_CAL},
+	{.reg_addr = 0x005c, .reg_data = 0x00, .param_type = CSIPHY_SKEW_CAL},
+	{.reg_addr = 0x0060, .reg_data = 0xbd, .param_type = CSIPHY_SKEW_CAL},
+	{.reg_addr = 0x0064, .reg_data = 0x7f, .param_type = CSIPHY_SKEW_CAL},
+
+	{.reg_addr = 0x0e94, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0ea0, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0e90, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0e98, .reg_data = 0x08, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0e94, .reg_data = 0x07, .delay_us =  0x01, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0e30, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0e28, .reg_data = 0x04, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0e00, .reg_data = 0x80, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0e0c, .reg_data = 0xff, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0e38, .reg_data = 0x1f, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0e2c, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0e34, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0e1c, .reg_data = 0x0a, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0e14, .reg_data = 0x60, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0e3c, .reg_data = 0xb8, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0e04, .reg_data = 0x0c, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0e20, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0e08, .reg_data = 0x10, .param_type = CSIPHY_SETTLE_CNT_LOWER_BYTE},
+	{.reg_addr = 0x0e10, .reg_data = 0x52, .param_type = CSIPHY_DEFAULT_PARAMS},
+
+	{.reg_addr = 0x0494, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x04a0, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0490, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0498, .reg_data = 0x08, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0494, .reg_data = 0x07, .delay_us =  0x01, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0430, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0400, .reg_data = 0x8e, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0438, .reg_data = 0xfe, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x042c, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0434, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x041c, .reg_data = 0x0a, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0414, .reg_data = 0x60, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x043c, .reg_data = 0xb8, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0404, .reg_data = 0x0c, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0420, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0408, .reg_data = 0x10, .param_type = CSIPHY_SETTLE_CNT_LOWER_BYTE},
+	{.reg_addr = 0x0410, .reg_data = 0x52, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0494, .reg_data = 0xd7, .param_type = CSIPHY_SKEW_CAL},
+	{.reg_addr = 0x045c, .reg_data = 0x00, .param_type = CSIPHY_SKEW_CAL},
+	{.reg_addr = 0x0460, .reg_data = 0xbd, .param_type = CSIPHY_SKEW_CAL},
+	{.reg_addr = 0x0464, .reg_data = 0x7f, .param_type = CSIPHY_SKEW_CAL},
+
+	{.reg_addr = 0x0894, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x08a0, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0890, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0898, .reg_data = 0x08, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0894, .reg_data = 0x07, .delay_us =  0x01, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0830, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0800, .reg_data = 0x8e, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0838, .reg_data = 0xfe, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x082c, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0834, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x081c, .reg_data = 0x0a, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0814, .reg_data = 0x60, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x083c, .reg_data = 0xb8, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0804, .reg_data = 0x0c, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0820, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0808, .reg_data = 0x10, .param_type = CSIPHY_SETTLE_CNT_LOWER_BYTE},
+	{.reg_addr = 0x0810, .reg_data = 0x52, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0894, .reg_data = 0xd7, .param_type = CSIPHY_SKEW_CAL},
+	{.reg_addr = 0x085c, .reg_data = 0x00, .param_type = CSIPHY_SKEW_CAL},
+	{.reg_addr = 0x0860, .reg_data = 0xbd, .param_type = CSIPHY_SKEW_CAL},
+	{.reg_addr = 0x0864, .reg_data = 0x7f, .param_type = CSIPHY_SKEW_CAL},
+
+	{.reg_addr = 0x0c94, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0ca0, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0c90, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0c98, .reg_data = 0x08, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0c94, .reg_data = 0x07, .delay_us =  0x01, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0c30, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0c00, .reg_data = 0x8e, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0c38, .reg_data = 0xfe, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0c2c, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0c34, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0c1c, .reg_data = 0x0a, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0c14, .reg_data = 0x60, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0c3c, .reg_data = 0xb8, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0c04, .reg_data = 0x0c, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0c20, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0c08, .reg_data = 0x10, .param_type = CSIPHY_SETTLE_CNT_LOWER_BYTE},
+	{.reg_addr = 0x0c10, .reg_data = 0x52, .param_type = CSIPHY_DEFAULT_PARAMS},
+	{.reg_addr = 0x0c94, .reg_data = 0xd7, .param_type = CSIPHY_SKEW_CAL},
+	{.reg_addr = 0x0c5c, .reg_data = 0x00, .param_type = CSIPHY_SKEW_CAL},
+	{.reg_addr = 0x0c60, .reg_data = 0xbd, .param_type = CSIPHY_SKEW_CAL},
+	{.reg_addr = 0x0c64, .reg_data = 0x7f, .param_type = CSIPHY_SKEW_CAL},
+};
+
+static inline const struct mipi_csi2phy_device_regs *
+csi2phy_dev_to_regs(struct mipi_csi2phy_device *csi2phy)
+{
+	return &csi2phy->soc_cfg->reg_info;
+}
+
+static void phy_qcom_mipi_csi2_hw_version_read(struct mipi_csi2phy_device *csi2phy)
+{
+	const struct mipi_csi2phy_device_regs *regs = csi2phy_dev_to_regs(csi2phy);
+	u32 tmp;
+
+	writel(CSIPHY_3PH_CMN_CSI_COMMON_CTRL6_SHOW_REV_ID, csi2phy->base +
+	       CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 6));
+
+	tmp = readl_relaxed(csi2phy->base +
+			    CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(regs->common_regs_offset, 12));
+	csi2phy->hw_version = tmp;
+
+	tmp = readl_relaxed(csi2phy->base +
+			    CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(regs->common_regs_offset, 13));
+	csi2phy->hw_version |= (tmp << 8) & 0xFF00;
+
+	tmp = readl_relaxed(csi2phy->base +
+			    CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(regs->common_regs_offset, 14));
+	csi2phy->hw_version |= (tmp << 16) & 0xFF0000;
+
+	tmp = readl_relaxed(csi2phy->base +
+			    CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(regs->common_regs_offset, 15));
+	csi2phy->hw_version |= (tmp << 24) & 0xFF000000;
+
+	dev_dbg_once(csi2phy->dev, "CSIPHY 3PH HW Version = 0x%08x\n", csi2phy->hw_version);
+}
+
+/*
+ * phy_qcom_mipi_csi2_reset - Perform software reset on CSIPHY module
+ * @phy_qcom_mipi_csi2: CSIPHY device
+ */
+static void phy_qcom_mipi_csi2_reset(struct mipi_csi2phy_device *csi2phy)
+{
+	const struct mipi_csi2phy_device_regs *regs = csi2phy_dev_to_regs(csi2phy);
+
+	writel(CSIPHY_3PH_CMN_CSI_COMMON_CTRL0_PHY_SW_RESET,
+	       csi2phy->base + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 0));
+	usleep_range(5000, 8000);
+	writel(0x0, csi2phy->base +
+	       CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 0));
+}
+
+/*
+ * phy_qcom_mipi_csi2_settle_cnt_calc - Calculate settle count value
+ *
+ * Helper function to calculate settle count value. This is
+ * based on the CSI2 T_hs_settle parameter which in turn
+ * is calculated based on the CSI2 transmitter link frequency.
+ *
+ * Return settle count value or 0 if the CSI2 link frequency
+ * is not available
+ */
+static u8 phy_qcom_mipi_csi2_settle_cnt_calc(s64 link_freq, u32 timer_clk_rate)
+{
+	u32 t_hs_prepare_max_ps;
+	u32 timer_period_ps;
+	u32 t_hs_settle_ps;
+	u8 settle_cnt;
+	u32 ui_ps;
+
+	if (link_freq <= 0)
+		return 0;
+
+	ui_ps = div64_u64(PSEC_PER_SEC, link_freq);
+	ui_ps /= 2;
+	t_hs_prepare_max_ps = 85000 + 6 * ui_ps;
+	t_hs_settle_ps = t_hs_prepare_max_ps;
+
+	timer_period_ps = div_u64(PSEC_PER_SEC, timer_clk_rate);
+
+	if ((t_hs_settle_ps / timer_period_ps) < 6)
+		return 0;
+
+	settle_cnt = t_hs_settle_ps / timer_period_ps - 6;
+
+	return settle_cnt;
+}
+
+static void
+phy_qcom_mipi_csi2_gen2_config_lanes(struct mipi_csi2phy_device *csi2phy,
+				     u8 settle_cnt)
+{
+	const struct mipi_csi2phy_device_regs *regs = csi2phy_dev_to_regs(csi2phy);
+	const struct mipi_csi2phy_lane_regs *r = regs->init_seq;
+	int i, array_size = regs->lane_array_size;
+	u32 val;
+
+	for (i = 0; i < array_size; i++, r++) {
+		switch (r->param_type) {
+		case CSIPHY_SETTLE_CNT_LOWER_BYTE:
+			val = settle_cnt & 0xff;
+			break;
+		case CSIPHY_SKEW_CAL:
+			/* TODO: support application of skew from dt flag */
+			continue;
+		default:
+			val = r->reg_data;
+			break;
+		}
+		writel(val, csi2phy->base + r->reg_addr);
+		if (r->delay_us)
+			udelay(r->delay_us);
+	}
+}
+
+static int phy_qcom_mipi_csi2_lanes_enable(struct mipi_csi2phy_device *csi2phy,
+					   struct mipi_csi2phy_stream_cfg *cfg)
+{
+	const struct mipi_csi2phy_device_regs *regs = csi2phy_dev_to_regs(csi2phy);
+	struct mipi_csi2phy_lanes_cfg *lane_cfg = &cfg->lane_cfg;
+	u8 settle_cnt;
+	u8 val;
+	int i;
+
+	settle_cnt = phy_qcom_mipi_csi2_settle_cnt_calc(cfg->link_freq, csi2phy->timer_clk_rate);
+	if (!settle_cnt)
+		return -EINVAL;
+
+	/*
+	 * CSI_COMMON_CTRL5 is a physical lane power-up bitmap:
+	 * - Bits [0,2,4,6] → D-PHY data lanes(LN0, LN2, LN4, LN6)
+	 * - Bits [1,3,5] → C-PHY trio lanes(LN1, LN3, LN5)
+	 * - Bit [7] → D-PHY clock lane(LNCK) dedicated clock enable
+	 */
+	val = BIT(lane_cfg->clk.pos);
+	for (i = 0; i < cfg->num_data_lanes; i++)
+		val |= BIT(lane_cfg->data[i].pos * 2);
+
+	writel(val, csi2phy->base +
+	       CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 5));
+
+	/* Lane configuration for polarity @ CSIPHY-base + CTRL9 */
+	for (i = 0; i < cfg->num_data_lanes; i++) {
+		if (lane_cfg->data[i].pol) {
+			u8 pos = lane_cfg->data[i].pos;
+
+			writel(BIT(2), csi2phy->base + CSIPHY_2PH_LN_CSI_2PHASE_CTRL9n(pos * 2));
+		}
+	}
+
+	if (lane_cfg->clk.pol)
+		writel(BIT(2), csi2phy->base + CSIPHY_2PH_LN_CSI_2PHASE_CTRL9n(lane_cfg->clk.pos));
+
+	val = CSIPHY_3PH_CMN_CSI_COMMON_CTRL6_COMMON_PWRDN_B;
+	writel(val, csi2phy->base +
+	       CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 6));
+
+	val = 0x02;
+	writel(val, csi2phy->base +
+	       CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 7));
+
+	val = 0x00;
+	writel(val, csi2phy->base +
+	       CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 0));
+
+	phy_qcom_mipi_csi2_gen2_config_lanes(csi2phy, settle_cnt);
+
+	/* IRQ_MASK registers - disable all interrupts */
+	for (i = CSI_COMMON_STATUS_NUM; i < CSI_CTRL_STATUS_INDEX; i++) {
+		writel(0, csi2phy->base +
+		       CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, i));
+	}
+
+	return 0;
+}
+
+static void
+phy_qcom_mipi_csi2_lanes_disable(struct mipi_csi2phy_device *csi2phy,
+				 struct mipi_csi2phy_stream_cfg *cfg)
+{
+	const struct mipi_csi2phy_device_regs *regs = csi2phy_dev_to_regs(csi2phy);
+
+	writel(0, csi2phy->base +
+	       CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 5));
+
+	writel(0, csi2phy->base +
+	       CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 6));
+}
+
+static const struct mipi_csi2phy_hw_ops phy_qcom_mipi_csi2_ops_3ph_1_0 = {
+	.hw_version_read = phy_qcom_mipi_csi2_hw_version_read,
+	.reset = phy_qcom_mipi_csi2_reset,
+	.lanes_enable = phy_qcom_mipi_csi2_lanes_enable,
+	.lanes_disable = phy_qcom_mipi_csi2_lanes_disable,
+};
+
+static const char * const x1e_clks[] = {
+	"core",
+	"timer",
+	"ahb"
+};
+
+static const char * const x1e_supplies[] = {
+	"vdda-0p9",
+	"vdda-1p2"
+};
+
+static struct mipi_csi2_genpd x1e_genpds[] = {
+	{ .name = "top", .scaled = false },
+	{ .name = "mmcx", .scaled = true },
+	{ .name = "mx", .scaled = true },
+};
+
+const struct mipi_csi2phy_soc_cfg mipi_csi2_dphy_4nm_x1e = {
+	.ops = &phy_qcom_mipi_csi2_ops_3ph_1_0,
+	.reg_info = {
+		.init_seq = lane_regs_x1e80100,
+		.lane_array_size = ARRAY_SIZE(lane_regs_x1e80100),
+		.common_regs_offset = 0x1000,
+	},
+	.supply_names = (const char **)x1e_supplies,
+	.num_supplies = ARRAY_SIZE(x1e_supplies),
+	.clk_names = (const char **)x1e_clks,
+	.num_clk = ARRAY_SIZE(x1e_clks),
+	.genpds = x1e_genpds,
+	.num_genpds = ARRAY_SIZE(x1e_genpds),
+};
diff --git a/drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c
new file mode 100644
index 0000000000000..892f802efb3ee
--- /dev/null
+++ b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c
@@ -0,0 +1,446 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2026, Linaro Ltd.
+ */
+
+#include <dt-bindings/phy/phy.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/pm_opp.h>
+#include <linux/phy/phy.h>
+#include <linux/phy/phy-mipi-dphy.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/reset.h>
+#include <linux/slab.h>
+
+#include "phy-qcom-mipi-csi2.h"
+
+static int
+phy_qcom_mipi_csi2_set_clock_rates(struct mipi_csi2phy_device *csi2phy,
+				   s64 link_freq)
+{
+	struct device *dev = csi2phy->dev;
+	unsigned long opp_rate = link_freq / 4;
+	struct dev_pm_opp *opp;
+	long timer_rate;
+	int i, pstate;
+	int ret;
+
+	opp = dev_pm_opp_find_freq_ceil(dev, &opp_rate);
+	if (IS_ERR(opp)) {
+		dev_err(csi2phy->dev, "Couldn't find ceiling for %lld Hz\n",
+			link_freq);
+		return PTR_ERR(opp);
+	}
+
+	pstate = 0;
+	for (i = 0; i < csi2phy->pd_list->num_pds; i++) {
+		unsigned int perf;
+
+		if (!csi2phy->soc_cfg->genpds[i].scaled)
+			continue;
+
+		perf = dev_pm_opp_get_required_pstate(opp, pstate);
+		pstate += 1;
+
+		ret = dev_pm_genpd_set_performance_state(csi2phy->pd_list->pd_devs[i], perf);
+		if (ret) {
+			dev_err(csi2phy->dev, "Couldn't set perf state %u\n",
+				perf);
+			dev_pm_opp_put(opp);
+			goto unset_pstate;
+		}
+	}
+	dev_pm_opp_put(opp);
+
+	ret = dev_pm_opp_set_rate(dev, opp_rate);
+	if (ret) {
+		dev_err(csi2phy->dev, "dev_pm_opp_set_rate() fail\n");
+		goto unset_opp_rate;
+	}
+
+	timer_rate = clk_round_rate(csi2phy->timer_clk, link_freq / 4);
+	if (timer_rate <= 0) {
+		ret = -ENODEV;
+		goto unset_opp_rate;
+	}
+
+	ret = clk_set_rate(csi2phy->timer_clk, timer_rate);
+	if (ret)
+		goto unset_opp_rate;
+
+	csi2phy->timer_clk_rate = timer_rate;
+
+	return 0;
+
+unset_opp_rate:
+	dev_pm_opp_set_rate(dev, 0);
+
+unset_pstate:
+	while (i--) {
+		if (!csi2phy->soc_cfg->genpds[i].scaled)
+			continue;
+
+		dev_pm_genpd_set_performance_state(csi2phy->pd_list->pd_devs[i], 0);
+	}
+
+	return ret;
+}
+
+static int phy_qcom_mipi_csi2_configure(struct phy *phy,
+					union phy_configure_opts *opts)
+{
+	struct mipi_csi2phy_device *csi2phy = phy_get_drvdata(phy);
+	struct phy_configure_opts_mipi_dphy *dphy_cfg = &opts->mipi_dphy;
+	struct mipi_csi2phy_stream_cfg *stream_cfg = &csi2phy->stream_cfg;
+	int ret;
+
+	ret = phy_mipi_dphy_config_validate(dphy_cfg);
+	if (ret)
+		return ret;
+
+	if (dphy_cfg->lanes < 1 || dphy_cfg->lanes > CSI2_MAX_DATA_LANES)
+		return -EINVAL;
+
+	stream_cfg->link_freq = dphy_cfg->hs_clk_rate;
+
+	return 0;
+}
+
+static int phy_qcom_mipi_csi2_power_on(struct phy *phy)
+{
+	struct mipi_csi2phy_device *csi2phy = phy_get_drvdata(phy);
+	const struct mipi_csi2phy_hw_ops *ops = csi2phy->soc_cfg->ops;
+	int i, ret;
+
+	ret = regulator_bulk_enable(csi2phy->soc_cfg->num_supplies,
+				    csi2phy->supplies);
+	if (ret)
+		return ret;
+
+	ret = pm_runtime_resume_and_get(csi2phy->dev);
+	if (ret < 0)
+		goto disable_regulators;
+
+	ret = phy_qcom_mipi_csi2_set_clock_rates(csi2phy, csi2phy->stream_cfg.link_freq);
+	if (ret)
+		goto poweroff_phy;
+
+	ret = clk_bulk_prepare_enable(csi2phy->soc_cfg->num_clk,
+				      csi2phy->clks);
+	if (ret) {
+		dev_err(csi2phy->dev, "failed to enable clocks, %d\n", ret);
+		goto unset_rate;
+	}
+
+	ops->reset(csi2phy);
+
+	ops->hw_version_read(csi2phy);
+
+	ret = ops->lanes_enable(csi2phy, &csi2phy->stream_cfg);
+	if (ret)
+		goto unset_clocks;
+
+	return 0;
+
+unset_clocks:
+	clk_bulk_disable_unprepare(csi2phy->soc_cfg->num_clk,
+				   csi2phy->clks);
+
+unset_rate:
+	dev_pm_opp_set_rate(csi2phy->dev, 0);
+
+	for (i = 0; i < csi2phy->pd_list->num_pds; i++) {
+		if (!csi2phy->soc_cfg->genpds[i].scaled)
+			continue;
+
+		dev_pm_genpd_set_performance_state(csi2phy->pd_list->pd_devs[i], 0);
+	}
+
+poweroff_phy:
+	pm_runtime_put_sync(csi2phy->dev);
+
+disable_regulators:
+	regulator_bulk_disable(csi2phy->soc_cfg->num_supplies,
+			       csi2phy->supplies);
+
+	return ret;
+}
+
+static int phy_qcom_mipi_csi2_power_off(struct phy *phy)
+{
+	struct mipi_csi2phy_device *csi2phy = phy_get_drvdata(phy);
+	const struct mipi_csi2phy_hw_ops *ops = csi2phy->soc_cfg->ops;
+	int i;
+
+	ops->lanes_disable(csi2phy, &csi2phy->stream_cfg);
+
+	clk_bulk_disable_unprepare(csi2phy->soc_cfg->num_clk,
+				   csi2phy->clks);
+
+	dev_pm_opp_set_rate(csi2phy->dev, 0);
+
+	for (i = 0; i < csi2phy->pd_list->num_pds; i++) {
+		if (!csi2phy->soc_cfg->genpds[i].scaled)
+			continue;
+
+		dev_pm_genpd_set_performance_state(csi2phy->pd_list->pd_devs[i], 0);
+	}
+
+	pm_runtime_put_sync(csi2phy->dev);
+
+	regulator_bulk_disable(csi2phy->soc_cfg->num_supplies,
+			       csi2phy->supplies);
+
+	return 0;
+}
+
+static const struct phy_ops phy_qcom_mipi_csi2_ops = {
+	.configure	= phy_qcom_mipi_csi2_configure,
+	.power_on	= phy_qcom_mipi_csi2_power_on,
+	.power_off	= phy_qcom_mipi_csi2_power_off,
+	.owner		= THIS_MODULE,
+};
+
+static struct phy *qcom_csi2_phy_xlate(struct device *dev,
+				       const struct of_phandle_args *args)
+{
+	struct mipi_csi2phy_device *csi2phy = dev_get_drvdata(dev);
+
+	if (args->args_count < 1 || args->args[0] != PHY_TYPE_DPHY) {
+		dev_err(csi2phy->dev, "invalid phy mode in DTB\n");
+		return ERR_PTR(-EOPNOTSUPP);
+	}
+
+	csi2phy->phy_mode = args->args[0];
+
+	return csi2phy->phy;
+}
+
+static int phy_qcom_mipi_csi2_attach_pm_domains(struct mipi_csi2phy_device *csi2phy)
+{
+	struct dev_pm_domain_attach_data pd_data = { 0 };
+	const char **pd_names;
+	int i;
+
+	pd_names = devm_kzalloc(csi2phy->dev,
+				sizeof(char *) * csi2phy->soc_cfg->num_genpds,
+				GFP_KERNEL);
+	if (!pd_names)
+		return -ENOMEM;
+
+	for (i = 0; i < csi2phy->soc_cfg->num_genpds; i++)
+		pd_names[i] = csi2phy->soc_cfg->genpds[i].name;
+
+	pd_data.pd_names = pd_names;
+	pd_data.num_pd_names = csi2phy->soc_cfg->num_genpds;
+
+	return devm_pm_domain_attach_list(csi2phy->dev, &pd_data,
+					  &csi2phy->pd_list);
+}
+
+static int phy_qcom_mipi_csi2_parse_routing(struct mipi_csi2phy_device *csi2phy)
+{
+	struct mipi_csi2phy_stream_cfg *stream_cfg = &csi2phy->stream_cfg;
+	u32 lane_polarities[CSI2_MAX_DATA_LANES + 1];
+	u32 data_lanes[CSI2_MAX_DATA_LANES];
+	struct device *dev = csi2phy->dev;
+	struct fwnode_handle *ep;
+	int num_polarities;
+	int num_data_lanes;
+	int i, ret;
+
+	ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), 0, 1, 0);
+	if (ep) {
+		fwnode_handle_put(ep);
+		dev_err(dev, "DPHY split mode is not supported\n");
+		return -EOPNOTSUPP;
+	}
+
+	ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), 0, 0, 0);
+	if (!ep) {
+		dev_err(dev, "Missing port@0\n");
+		return -ENODEV;
+	}
+
+	num_data_lanes = fwnode_property_count_u32(ep, "data-lanes");
+	if (num_data_lanes < 1 || num_data_lanes > CSI2_MAX_DATA_LANES) {
+		ret = -EINVAL;
+		dev_err(dev, "Invalid data-lanes count: %d\n", num_data_lanes);
+		goto out_put;
+	}
+	stream_cfg->num_data_lanes = num_data_lanes;
+
+	ret = fwnode_property_read_u32_array(ep, "data-lanes", data_lanes,
+					     stream_cfg->num_data_lanes);
+	if (ret) {
+		dev_err(dev, "Failed to read data-lanes: %d\n", ret);
+		goto out_put;
+	}
+
+	/* lane-polarities: optional, up to num_data_lanes + 1 entries */
+	memset(lane_polarities, 0x00, sizeof(lane_polarities));
+	num_polarities = fwnode_property_count_u32(ep, "lane-polarities");
+	if (num_polarities > 0) {
+		if (num_polarities != stream_cfg->num_data_lanes + 1) {
+			ret = -EINVAL;
+			dev_err(dev, "clock+data-lane %d/polarities %d mismatch\n",
+				stream_cfg->num_data_lanes + 1, num_polarities);
+			goto out_put;
+		}
+
+		ret = fwnode_property_read_u32_array(ep, "lane-polarities", lane_polarities,
+						     num_polarities);
+		if (ret) {
+			dev_err(dev, "Failed to read lane-polarities: %d\n", ret);
+			goto out_put;
+		}
+	}
+
+	csi2phy->stream_cfg.lane_cfg.clk.pos = CSI2_DEFAULT_CLK_LANE;
+	csi2phy->stream_cfg.lane_cfg.clk.pol = lane_polarities[0];
+
+	for (i = 0; i < csi2phy->stream_cfg.num_data_lanes; i++) {
+		if (data_lanes[i] >= CSI2_MAX_DATA_LANES) {
+			dev_err(dev, "Invalid lane %d\n", data_lanes[i]);
+			ret = -EINVAL;
+			goto out_put;
+		}
+		csi2phy->stream_cfg.lane_cfg.data[i].pos = data_lanes[i];
+		csi2phy->stream_cfg.lane_cfg.data[i].pol = lane_polarities[i + 1];
+	}
+
+	ret = 0;
+
+out_put:
+	fwnode_handle_put(ep);
+
+	return ret;
+}
+
+static int phy_qcom_mipi_csi2_probe(struct platform_device *pdev)
+{
+	unsigned int i, num_clk, num_supplies;
+	struct mipi_csi2phy_device *csi2phy;
+	struct phy_provider *phy_provider;
+	struct device *dev = &pdev->dev;
+	struct phy *generic_phy;
+	int ret;
+
+	csi2phy = devm_kzalloc(dev, sizeof(*csi2phy), GFP_KERNEL);
+	if (!csi2phy)
+		return -ENOMEM;
+
+	csi2phy->dev = dev;
+	dev_set_drvdata(dev, csi2phy);
+
+	csi2phy->soc_cfg = device_get_match_data(&pdev->dev);
+
+	if (!csi2phy->soc_cfg)
+		return -EINVAL;
+
+	num_clk = csi2phy->soc_cfg->num_clk;
+
+	ret = phy_qcom_mipi_csi2_parse_routing(csi2phy);
+	if (ret)
+		return ret;
+
+	ret = phy_qcom_mipi_csi2_attach_pm_domains(csi2phy);
+	if (ret < 0 || csi2phy->pd_list == NULL) {
+		if (ret == 0)
+			ret = -ENODEV;
+		return dev_err_probe(dev, ret, "Failed to attach power-domain list\n");
+	}
+
+	ret = devm_pm_runtime_enable(dev);
+	if (ret < 0)
+		return dev_err_probe(dev, ret, "Failed to enable pm runtime\n");
+
+	ret = devm_clk_bulk_get_all(dev, &csi2phy->clks);
+	if (ret < 0)
+		return dev_err_probe(dev, ret, "Failed to get clocks\n");
+
+	if (num_clk != ret) {
+		return dev_err_probe(dev, -ENODEV, "clock count %d expected %d\n",
+				     ret, num_clk);
+	}
+
+	for (i = 0; i < num_clk; i++) {
+		if (!strcmp(csi2phy->clks[i].id, "timer")) {
+			csi2phy->timer_clk = csi2phy->clks[i].clk;
+			break;
+		}
+	}
+	if (!csi2phy->timer_clk)
+		return dev_err_probe(dev, -ENODEV, "no timer clock\n");
+
+	ret = devm_pm_opp_set_clkname(dev, "core");
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to set opp clkname\n");
+
+	ret = devm_pm_opp_of_add_table(dev);
+	if (ret)
+		return dev_err_probe(dev, ret, "invalid OPP table in device tree\n");
+
+	num_supplies = csi2phy->soc_cfg->num_supplies;
+	csi2phy->supplies = devm_kzalloc(dev, sizeof(*csi2phy->supplies) * num_supplies,
+					 GFP_KERNEL);
+	if (!csi2phy->supplies)
+		return -ENOMEM;
+
+	for (i = 0; i < num_supplies; i++)
+		csi2phy->supplies[i].supply = csi2phy->soc_cfg->supply_names[i];
+
+	ret = devm_regulator_bulk_get(dev, num_supplies, csi2phy->supplies);
+	if (ret)
+		return dev_err_probe(dev, ret,
+				     "failed to get regulator supplies\n");
+
+	csi2phy->base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(csi2phy->base))
+		return PTR_ERR(csi2phy->base);
+
+	generic_phy = devm_phy_create(dev, NULL, &phy_qcom_mipi_csi2_ops);
+	if (IS_ERR(generic_phy)) {
+		ret = PTR_ERR(generic_phy);
+		return dev_err_probe(dev, ret, "failed to create phy\n");
+	}
+	csi2phy->phy = generic_phy;
+
+	phy_set_drvdata(generic_phy, csi2phy);
+
+	phy_provider = devm_of_phy_provider_register(dev, qcom_csi2_phy_xlate);
+	if (!IS_ERR(phy_provider))
+		dev_dbg(dev, "Registered MIPI CSI2 PHY device\n");
+
+	return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static const struct of_device_id phy_qcom_mipi_csi2_of_match_table[] = {
+	{ .compatible	= "qcom,x1e80100-csi2-phy", .data = &mipi_csi2_dphy_4nm_x1e },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, phy_qcom_mipi_csi2_of_match_table);
+
+static struct platform_driver phy_qcom_mipi_csi2_driver = {
+	.probe		= phy_qcom_mipi_csi2_probe,
+	.driver = {
+		.name	= "qcom-mipi-csi2-phy",
+		.of_match_table = phy_qcom_mipi_csi2_of_match_table,
+	},
+};
+
+module_platform_driver(phy_qcom_mipi_csi2_driver);
+
+MODULE_DESCRIPTION("Qualcomm MIPI CSI2 PHY driver");
+MODULE_AUTHOR("Bryan O'Donoghue <bod@kernel.org>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/phy/qualcomm/phy-qcom-mipi-csi2.h b/drivers/phy/qualcomm/phy-qcom-mipi-csi2.h
new file mode 100644
index 0000000000000..7e55ae0073704
--- /dev/null
+++ b/drivers/phy/qualcomm/phy-qcom-mipi-csi2.h
@@ -0,0 +1,97 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * Qualcomm MIPI CSI2 CPHY/DPHY driver
+ *
+ * Copyright (C) 2025 Linaro Ltd.
+ */
+#ifndef __PHY_QCOM_MIPI_CSI2_H__
+#define __PHY_QCOM_MIPI_CSI2_H__
+
+#include <linux/phy/phy.h>
+
+#define CSI2_MAX_DATA_LANES	4
+#define CSI2_DEFAULT_CLK_LANE	7
+
+struct mipi_csi2phy_lane {
+	u8 pos;
+	u8 pol;
+};
+
+struct mipi_csi2phy_lanes_cfg {
+	struct mipi_csi2phy_lane data[CSI2_MAX_DATA_LANES];
+	struct mipi_csi2phy_lane clk;
+};
+
+struct mipi_csi2phy_stream_cfg {
+	s64 link_freq;
+	u8 num_data_lanes;
+	struct mipi_csi2phy_lanes_cfg lane_cfg;
+};
+
+struct mipi_csi2phy_device;
+
+struct mipi_csi2phy_hw_ops {
+	void (*hw_version_read)(struct mipi_csi2phy_device *csi2phy_dev);
+	void (*reset)(struct mipi_csi2phy_device *csi2phy_dev);
+	int (*lanes_enable)(struct mipi_csi2phy_device *csi2phy_dev,
+			    struct mipi_csi2phy_stream_cfg *cfg);
+	void (*lanes_disable)(struct mipi_csi2phy_device *csi2phy_dev,
+			      struct mipi_csi2phy_stream_cfg *cfg);
+};
+
+struct mipi_csi2phy_lane_regs {
+	const s32 reg_addr;
+	const s32 reg_data;
+	const u32 delay_us;
+	const u32 param_type;
+};
+
+struct mipi_csi2phy_device_regs {
+	const struct mipi_csi2phy_lane_regs *init_seq;
+	const int lane_array_size;
+	const u32 common_regs_offset;
+};
+
+struct mipi_csi2_genpd {
+	const char *name;
+	bool scaled;
+};
+
+struct mipi_csi2phy_soc_cfg {
+	const struct mipi_csi2phy_hw_ops *ops;
+	const struct mipi_csi2phy_device_regs reg_info;
+
+	const char ** const supply_names;
+	const unsigned int num_supplies;
+
+	const char ** const clk_names;
+	const unsigned int num_clk;
+
+	const struct mipi_csi2_genpd *genpds;
+	const unsigned int num_genpds;
+};
+
+struct mipi_csi2phy_device {
+	struct device *dev;
+	u8 phy_mode;
+
+	struct phy *phy;
+	void __iomem *base;
+
+	struct clk_bulk_data *clks;
+	struct clk *timer_clk;
+	u32 timer_clk_rate;
+
+	struct regulator_bulk_data *supplies;
+	struct dev_pm_domain_list *pd_list;
+
+	const struct mipi_csi2phy_soc_cfg *soc_cfg;
+	struct mipi_csi2phy_stream_cfg stream_cfg;
+
+	u32 hw_version;
+};
+
+extern const struct mipi_csi2phy_soc_cfg mipi_csi2_dphy_4nm_x1e;
+
+#endif /* __PHY_QCOM_MIPI_CSI2_H__ */

-- 
2.54.0


^ permalink raw reply related

* Re: [PATCH v12 2/2] phy: qcom-mipi-csi2: Add a CSI2 MIPI DPHY driver
From: sashiko-bot @ 2026-07-19 13:59 UTC (permalink / raw)
  To: Bryan O'Donoghue
  Cc: robh, media-ci, vkoul, conor+dt, devicetree, neil.armstrong,
	linux-phy, olteanv
In-Reply-To: <20260719-x1e-csi2-phy-v12-2-cc7311326d1b@linaro.org>

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] Valid calculated settle_cnt of 0 is erroneously rejected as an error, causing PHY initialization to fail.
- [High] Potential NULL pointer dereference in clock name comparison during probe when parsing malformed device trees.
- [Medium] Missing PM_OPP Kconfig dependency causes unconditional runtime probe failures.
--

--- Patch [2]: [PATCH v12 2/2] phy: qcom-mipi-csi2: Add a CSI2 MIPI DPHY driver ---
commit 7fdedc509474184e47a62af468ae08b71f96dfd5
Author: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Subject: phy: qcom-mipi-csi2: Add a CSI2 MIPI DPHY driver

This commit adds a new MIPI CSI2 driver in DPHY mode. It imports existing
CAMSS CSI PHY initialization sequences to support devices like the
qcom,x1e80100-csi2-phy.

> diff --git a/drivers/phy/qualcomm/Kconfig b/drivers/phy/qualcomm/Kconfig
> index 60a0ead127fa9..779a3511ba852 100644
> --- a/drivers/phy/qualcomm/Kconfig
> +++ b/drivers/phy/qualcomm/Kconfig
> @@ -28,6 +28,20 @@ config PHY_QCOM_EDP
>  	  Enable this driver to support the Qualcomm eDP PHY found in various
>  	  Qualcomm chipsets.
>  
> +config PHY_QCOM_MIPI_CSI2
> +	tristate "Qualcomm MIPI CSI2 PHY driver"
> +	depends on ARCH_QCOM || COMPILE_TEST
> +	depends on OF
> +	depends on PM
> +	depends on COMMON_CLK
> +	select GENERIC_PHY
> +	select GENERIC_PHY_MIPI_DPHY

[Severity: Medium]
Should this Kconfig entry select or depend on PM_OPP?

Without CONFIG_PM_OPP enabled, the stub for devm_pm_opp_of_add_table()
used during probe will return -EOPNOTSUPP, causing the driver probe to
unconditionally fail with an "invalid OPP table" error.

> diff --git a/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c
> new file mode 100644
> --- /dev/null
> +++ b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c

[ ... ]

> +static int phy_qcom_mipi_csi2_lanes_enable(struct mipi_csi2phy_device *csi2phy,
> +					   struct mipi_csi2phy_stream_cfg *cfg)
> +{
> +	const struct mipi_csi2phy_device_regs *regs = csi2phy_dev_to_regs(csi2phy);
> +	struct mipi_csi2phy_lanes_cfg *lane_cfg = &cfg->lane_cfg;
> +	u8 settle_cnt;
> +	u8 val;
> +	int i;
> +
> +	settle_cnt = phy_qcom_mipi_csi2_settle_cnt_calc(cfg->link_freq, csi2phy->timer_clk_rate);
> +	if (!settle_cnt)
> +		return -EINVAL;

[Severity: High]
Does this incorrectly reject a valid settle count of zero?

Looking at the math in phy_qcom_mipi_csi2_settle_cnt_calc():

phy_qcom_mipi_csi2_settle_cnt_calc() {
        ...
        settle_cnt = t_hs_settle_ps / timer_period_ps - 6;
        return settle_cnt;
}

If the link frequency and timer clock rate yield exactly 6 timer periods
for t_hs_settle, the calculation results in 0. By rejecting 0 here,
legitimate MIPI CSI2 configurations might fail to initialize.

> diff --git a/drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c
> new file mode 100644
> --- /dev/null
> +++ b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c

[ ... ]

> +static int phy_qcom_mipi_csi2_probe(struct platform_device *pdev)
> +{

[ ... ]

> +	ret = devm_clk_bulk_get_all(dev, &csi2phy->clks);
> +	if (ret < 0)
> +		return dev_err_probe(dev, ret, "Failed to get clocks\n");
> +
> +	if (num_clk != ret) {
> +		return dev_err_probe(dev, -ENODEV, "clock count %d expected %d\n",
> +				     ret, num_clk);
> +	}
> +
> +	for (i = 0; i < num_clk; i++) {
> +		if (!strcmp(csi2phy->clks[i].id, "timer")) {

[Severity: High]
Could csi2phy->clks[i].id be NULL here?

The clk_bulk_get_all() infrastructure can leave the .id field as NULL if
the device tree node has a "clocks" property but is missing "clock-names".
Calling strcmp() on a NULL pointer will cause a kernel panic during probe
when parsing malformed device trees.

> +			csi2phy->timer_clk = csi2phy->clks[i].clk;
> +			break;
> +		}
> +	}
> +	if (!csi2phy->timer_clk)
> +		return dev_err_probe(dev, -ENODEV, "no timer clock\n");

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260719-x1e-csi2-phy-v12-0-cc7311326d1b@linaro.org?part=2

^ permalink raw reply

* [PATCH] dt-bindings: net: can: Convert TI HECC to DT schema
From: Eduard Bostina @ 2026-07-19 14:01 UTC (permalink / raw)
  To: Conor Dooley, devicetree, Eduard Bostina, Krzysztof Kozlowski,
	linux-can, linux-kernel, Marc Kleine-Budde, Rob Herring,
	Vincent Mailhol
  Cc: daniel.baluta, simona.toaca, goledhruva, m-chawdhry

Convert the Texas Instruments High End CAN Controller (HECC) bindings
to DT schema.

Signed-off-by: Eduard Bostina <egbostina@gmail.com>
---
 .../bindings/net/can/ti,am3517-hecc.yaml      | 64 +++++++++++++++++++
 .../devicetree/bindings/net/can/ti_hecc.txt   | 32 ----------
 2 files changed, 64 insertions(+), 32 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/net/can/ti,am3517-hecc.yaml
 delete mode 100644 Documentation/devicetree/bindings/net/can/ti_hecc.txt

diff --git a/Documentation/devicetree/bindings/net/can/ti,am3517-hecc.yaml b/Documentation/devicetree/bindings/net/can/ti,am3517-hecc.yaml
new file mode 100644
index 000000000000..7874e9e49224
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/can/ti,am3517-hecc.yaml
@@ -0,0 +1,64 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/can/ti,am3517-hecc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Texas Instruments High End CAN Controller (HECC)
+
+maintainers:
+  - Eduard Bostina <egbostina@gmail.com>
+
+allOf:
+  - $ref: can-controller.yaml#
+
+properties:
+  compatible:
+    const: ti,am3517-hecc
+
+  reg:
+    maxItems: 3
+
+  reg-names:
+    items:
+      - const: hecc
+      - const: hecc-ram
+      - const: mbx
+
+  interrupts:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  ti,use-hecc1int:
+    type: boolean
+    description:
+      If provided, configures HECC to produce all interrupts on the
+      HECC1INT interrupt line. By default, the HECC0INT interrupt line
+      will be used.
+    default: false
+
+  xceiver-supply:
+    description: Regulator that powers the CAN transceiver.
+
+required:
+  - compatible
+  - reg
+  - reg-names
+  - interrupts
+  - clocks
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    can@5c050000 {
+        compatible = "ti,am3517-hecc";
+        reg = <0x5c050000 0x80>,
+              <0x5c053000 0x180>,
+              <0x5c052000 0x200>;
+        reg-names = "hecc", "hecc-ram", "mbx";
+        interrupts = <24>;
+        clocks = <&hecc_ck>;
+    };
diff --git a/Documentation/devicetree/bindings/net/can/ti_hecc.txt b/Documentation/devicetree/bindings/net/can/ti_hecc.txt
deleted file mode 100644
index e0f0a7cfe329..000000000000
--- a/Documentation/devicetree/bindings/net/can/ti_hecc.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-Texas Instruments High End CAN Controller (HECC)
-================================================
-
-This file provides information, what the device node
-for the hecc interface contains.
-
-Required properties:
-- compatible: "ti,am3517-hecc"
-- reg: addresses and lengths of the register spaces for 'hecc', 'hecc-ram'
-       and 'mbx'
-- reg-names :"hecc", "hecc-ram", "mbx"
-- interrupts: interrupt mapping for the hecc interrupts sources
-- clocks: clock phandles (see clock bindings for details)
-
-Optional properties:
-- ti,use-hecc1int: if provided configures HECC to produce all interrupts
-		   on HECC1INT interrupt line. By default HECC0INT interrupt
-		   line will be used.
-- xceiver-supply: regulator that powers the CAN transceiver
-
-Example:
-
-For am3517evm board:
-	hecc: can@5c050000 {
-		compatible = "ti,am3517-hecc";
-		reg = <0x5c050000 0x80>,
-		      <0x5c053000 0x180>,
-		      <0x5c052000 0x200>;
-		reg-names = "hecc", "hecc-ram", "mbx";
-		interrupts = <24>;
-		clocks = <&hecc_ck>;
-	};
-- 
2.43.0


^ permalink raw reply related

* [PATCH 0/2] dt-bindings: rtc: Convert to DT schema
From: Eduard Bostina @ 2026-07-19 14:10 UTC (permalink / raw)
  To: Aaro Koskinen, Alexandre Belloni, Andreas Kemnade, Conor Dooley,
	devicetree, Eduard Bostina, Kevin Hilman, Krzysztof Kozlowski,
	linux-kernel, linux-omap, linux-rtc, Rob Herring, Roger Quadros,
	Tony Lindgren
  Cc: daniel.baluta, simona.toaca, goledhruva, m-chawdhry

This series converts the Texas Instruments Palmas RTC bindings to DT schema
and resolves a node name compliance issue.

Patch 1 converts the text binding to DT schema.

Patch 2 updates the tps659038_rtc nodes across the AM57xx device trees 
to use the generic 'rtc' node name.

Eduard Bostina (2):
  dt-bindings: rtc: Convert TI Palmas RTC to DT schema
  ARM: dts: ti: omap: Fix Palmas RTC node names

 .../devicetree/bindings/rtc/rtc-palmas.txt    | 32 -----------
 .../bindings/rtc/ti,palmas-rtc.yaml           | 57 +++++++++++++++++++
 .../boot/dts/ti/omap/am5729-beagleboneai.dts  |  2 +-
 .../dts/ti/omap/am57xx-beagle-x15-common.dtsi |  2 +-
 .../boot/dts/ti/omap/am57xx-idk-common.dtsi   |  2 +-
 5 files changed, 60 insertions(+), 35 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/rtc/rtc-palmas.txt
 create mode 100644 Documentation/devicetree/bindings/rtc/ti,palmas-rtc.yaml

-- 
2.43.0


^ permalink raw reply

* [PATCH 1/2] dt-bindings: rtc: Convert TI Palmas RTC to DT schema
From: Eduard Bostina @ 2026-07-19 14:10 UTC (permalink / raw)
  To: Aaro Koskinen, Alexandre Belloni, Andreas Kemnade, Conor Dooley,
	devicetree, Eduard Bostina, Kevin Hilman, Krzysztof Kozlowski,
	linux-kernel, linux-omap, linux-rtc, Rob Herring, Roger Quadros,
	Tony Lindgren
  Cc: daniel.baluta, simona.toaca, goledhruva, m-chawdhry
In-Reply-To: <20260719141008.3562347-1-egbostina@gmail.com>

Convert the Texas Instruments Palmas RTC controller bindings
to DT schema.

As part of the conversion, declare 'wakeup-source: true'.
This documents the Palmas PMIC's capability to wake the system.

Signed-off-by: Eduard Bostina <egbostina@gmail.com>
---
 .../devicetree/bindings/rtc/rtc-palmas.txt    | 32 -----------
 .../bindings/rtc/ti,palmas-rtc.yaml           | 57 +++++++++++++++++++
 2 files changed, 57 insertions(+), 32 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/rtc/rtc-palmas.txt
 create mode 100644 Documentation/devicetree/bindings/rtc/ti,palmas-rtc.yaml

diff --git a/Documentation/devicetree/bindings/rtc/rtc-palmas.txt b/Documentation/devicetree/bindings/rtc/rtc-palmas.txt
deleted file mode 100644
index c6cf37758a77..000000000000
--- a/Documentation/devicetree/bindings/rtc/rtc-palmas.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-Palmas RTC controller bindings
-
-Required properties:
-- compatible:
-  - "ti,palmas-rtc" for palma series of the RTC controller
-- interrupts: Interrupt number of RTC submodule on device.
-
-Optional properties:
-
-- ti,backup-battery-chargeable: The Palmas series device like TPS65913 or
-	TPS80036 supports the backup battery for powering the RTC when main
-	battery is removed or in very low power state. The backup battery
-	can be chargeable or non-chargeable. This flag will tells whether
-	battery is chargeable or not. If charging battery then driver can
-	enable the charging.
-- ti,backup-battery-charge-high-current: Enable high current charging in
-	backup battery. Device supports the < 100uA and > 100uA charging.
-	The high current will be > 100uA. Absence of this property will
-	charge battery to lower current i.e. < 100uA.
-
-Example:
-	palmas: tps65913@58 {
-		...
-		palmas_rtc: rtc {
-			compatible = "ti,palmas-rtc";
-			interrupt-parent = <&palmas>;
-			interrupts = <8 0>;
-			ti,backup-battery-chargeable;
-			ti,backup-battery-charge-high-current;
-		};
-		...
-	};
diff --git a/Documentation/devicetree/bindings/rtc/ti,palmas-rtc.yaml b/Documentation/devicetree/bindings/rtc/ti,palmas-rtc.yaml
new file mode 100644
index 000000000000..ac64f0589c84
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/ti,palmas-rtc.yaml
@@ -0,0 +1,57 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/rtc/ti,palmas-rtc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Texas Instruments Palmas RTC
+
+maintainers:
+  - Eduard Bostina <egbostina@gmail.com>
+
+allOf:
+  - $ref: /schemas/rtc/rtc.yaml#
+
+properties:
+  compatible:
+    const: ti,palmas-rtc
+
+  interrupts:
+    maxItems: 1
+
+  wakeup-source: true
+
+  ti,backup-battery-chargeable:
+    type: boolean
+    description:
+      The backup battery can be chargeable or non-chargeable. This flag
+      indicates whether the battery is chargeable. If present, the driver
+      can enable charging.
+
+  ti,backup-battery-charge-high-current:
+    type: boolean
+    description:
+      Enable high current charging in the backup battery.
+      Device supports the < 100uA and > 100uA charging. The high current will
+      be > 100uA. Absence of this property will charge battery to lower
+      current i.e. < 100uA.
+
+required:
+  - compatible
+  - interrupts
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    pmic {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        rtc {
+            compatible = "ti,palmas-rtc";
+            interrupts = <8 0>;
+            ti,backup-battery-chargeable;
+            ti,backup-battery-charge-high-current;
+        };
+    };
-- 
2.43.0


^ permalink raw reply related

* [PATCH 2/2] ARM: dts: ti: omap: Fix Palmas RTC node names
From: Eduard Bostina @ 2026-07-19 14:10 UTC (permalink / raw)
  To: Aaro Koskinen, Alexandre Belloni, Andreas Kemnade, Conor Dooley,
	devicetree, Eduard Bostina, Kevin Hilman, Krzysztof Kozlowski,
	linux-kernel, linux-omap, linux-rtc, Rob Herring, Roger Quadros,
	Tony Lindgren
  Cc: daniel.baluta, simona.toaca, goledhruva, m-chawdhry
In-Reply-To: <20260719141008.3562347-1-egbostina@gmail.com>

The core RTC Device Tree schema expects RTC nodes to be named generically
('rtc' or 'rtc@...').

Update the tps659038_rtc nodes across the AM57xx device trees to use
the generic 'rtc' node name to resolve dtbs_check warnings.

Signed-off-by: Eduard Bostina <egbostina@gmail.com>
---
 arch/arm/boot/dts/ti/omap/am5729-beagleboneai.dts       | 2 +-
 arch/arm/boot/dts/ti/omap/am57xx-beagle-x15-common.dtsi | 2 +-
 arch/arm/boot/dts/ti/omap/am57xx-idk-common.dtsi        | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/ti/omap/am5729-beagleboneai.dts b/arch/arm/boot/dts/ti/omap/am5729-beagleboneai.dts
index 76bfb364777e..46270ed87377 100644
--- a/arch/arm/boot/dts/ti/omap/am5729-beagleboneai.dts
+++ b/arch/arm/boot/dts/ti/omap/am5729-beagleboneai.dts
@@ -386,7 +386,7 @@ regen2: regen2 {
 			};
 		};
 
-		tps659038_rtc: tps659038_rtc {
+		tps659038_rtc: rtc {
 			compatible = "ti,palmas-rtc";
 			interrupt-parent = <&tps659038>;
 			interrupts = <8 IRQ_TYPE_EDGE_FALLING>;
diff --git a/arch/arm/boot/dts/ti/omap/am57xx-beagle-x15-common.dtsi b/arch/arm/boot/dts/ti/omap/am57xx-beagle-x15-common.dtsi
index 87b61a98d5e9..e7c186941c23 100644
--- a/arch/arm/boot/dts/ti/omap/am57xx-beagle-x15-common.dtsi
+++ b/arch/arm/boot/dts/ti/omap/am57xx-beagle-x15-common.dtsi
@@ -360,7 +360,7 @@ regen1: regen1 {
 			};
 		};
 
-		tps659038_rtc: tps659038_rtc {
+		tps659038_rtc: rtc {
 			compatible = "ti,palmas-rtc";
 			interrupt-parent = <&tps659038>;
 			interrupts = <8 IRQ_TYPE_EDGE_FALLING>;
diff --git a/arch/arm/boot/dts/ti/omap/am57xx-idk-common.dtsi b/arch/arm/boot/dts/ti/omap/am57xx-idk-common.dtsi
index 5eccff3bb4b6..a2a654ef4ef9 100644
--- a/arch/arm/boot/dts/ti/omap/am57xx-idk-common.dtsi
+++ b/arch/arm/boot/dts/ti/omap/am57xx-idk-common.dtsi
@@ -405,7 +405,7 @@ regen2: regen2 {
 			};
 		};
 
-		tps659038_rtc: tps659038_rtc {
+		tps659038_rtc: rtc {
 			compatible = "ti,palmas-rtc";
 			interrupt-parent = <&tps659038>;
 			interrupts = <8 IRQ_TYPE_EDGE_FALLING>;
-- 
2.43.0


^ permalink raw reply related

* Re: [PATCH v2 00/12] arm64: dts: apple: Add SMC hwmon nodes
From: Sven Peter @ 2026-07-19 14:11 UTC (permalink / raw)
  To: James Calligeros, Janne Grunau, Neal Gompa, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley
  Cc: asahi, linux-arm-kernel, devicetree, linux-kernel
In-Reply-To: <20260714-smc-subdev-dt-v2-0-13fa78873121@gmail.com>



On 7/14/26 08:28, James Calligeros wrote:
> Hi folks,
>
> Following on from the series which added SMC hwmon driver[1], this
> series spins out and adds the Devicetree nodes required for the hwmon
> driver to operate. These were missed back in December.
>
> The System Management Controller on Apple Silicon devices exposes
> the temperature, voltage, power and fan speed data from numerous
> (potentially hundreds) of sensors scattered about the SoC and
> device at large. Unfortunately there is very little rhyme or reason
> to how Apple expose these using the SMC firmware's FourCC key-value
> system. Some sensors are reliably common across all devices and
> all SoCs, like PSTR which measures the total platform power consumption.
> Others are specific to a class of device, like the fan control
> keys, which are only present on devices with fans. Some are specific
> to a single SoC, and others still are specific to a single device.
> To complicate matters further, some SoCs are not even consistent
> across devices; the application core temperature sensors for a
> given SoC are read from different keys depending on the device
> that SoC is in...
>

Applied to sven/linux (apple-soc/dt-7.3), thanks!

[01/12] arm64: dts: apple: t8112: Add SMC hwmon node
        https://github.com/AsahiLinux/linux/commit/89efdbd8ea62
[02/12] arm64: dts: apple: t8103: Add SMC hwmon node
        https://github.com/AsahiLinux/linux/commit/4dea4ee249ec
[03/12] arm64: dts: apple: t600x: Add SMC hwmon node
        https://github.com/AsahiLinux/linux/commit/d02aeb6980b6
[04/12] arm64: dts: apple: t602x: Add SMC hwmon node
        https://github.com/AsahiLinux/linux/commit/f424abc3075b
[05/12] arm64: dts: apple: Add common SMC hwmon infrastructure
        https://github.com/AsahiLinux/linux/commit/56c65dc95f3d
[06/12] arm64: dts: apple: t8103: Add common SMC hwmon sensors
        https://github.com/AsahiLinux/linux/commit/d77603e44f55
[07/12] arm64: dts: apple: t8112: Add common SMC hwmon sensors
        https://github.com/AsahiLinux/linux/commit/ae42d7fe0793
[08/12] arm64: dts: apple: t600x: Add common SMC hwmon sensors
        https://github.com/AsahiLinux/linux/commit/fe521d15d9c5
[09/12] arm64: dts: apple: t602x: Add common SMC hwmon sensors
        https://github.com/AsahiLinux/linux/commit/fd42ff865357
[10/12] arm64: dts: apple: t8103: jxxx: Add device-specific SMC hwmon 
sensors
        https://github.com/AsahiLinux/linux/commit/b6935375d536
[11/12] arm64: dts: apple: t8112: jxxx: Add device-specific SMC hwmon 
sensors
        https://github.com/AsahiLinux/linux/commit/da160f258c36
[12/12] arm64: dts: apple: t60xx: jxxx: Add device-specific SMC hwmon 
sensors
        https://github.com/AsahiLinux/linux/commit/e88070b74578

Best regards,
-- 
Sven Peter <sven@kernel.org>



^ permalink raw reply

* [PATCH] dt-bindings: clock: Convert TI Palmas Clock to DT schema
From: Eduard Bostina @ 2026-07-19 14:12 UTC (permalink / raw)
  To: Brian Masney, Conor Dooley, devicetree, Eduard Bostina,
	Krzysztof Kozlowski, linux-clk, linux-kernel, Michael Turquette,
	Rob Herring, Stephen Boyd
  Cc: daniel.baluta, simona.toaca, goledhruva, m-chawdhry

Convert the Texas Instruments Palmas 32KHz clock bindings
to DT schema.

During the conversion, the node name in the example was updated
from 'palmas_clk32k@0' to 'clock-controller'. The old example
contained a unit address without a 'reg' property, which causes
dtc compilation warnings.

Signed-off-by: Eduard Bostina <egbostina@gmail.com>
---
 .../clock/clk-palmas-clk32kg-clocks.txt       | 35 ------------
 .../bindings/clock/ti,palmas-clk32kg.yaml     | 56 +++++++++++++++++++
 2 files changed, 56 insertions(+), 35 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/clock/clk-palmas-clk32kg-clocks.txt
 create mode 100644 Documentation/devicetree/bindings/clock/ti,palmas-clk32kg.yaml

diff --git a/Documentation/devicetree/bindings/clock/clk-palmas-clk32kg-clocks.txt b/Documentation/devicetree/bindings/clock/clk-palmas-clk32kg-clocks.txt
deleted file mode 100644
index 4208886d834a..000000000000
--- a/Documentation/devicetree/bindings/clock/clk-palmas-clk32kg-clocks.txt
+++ /dev/null
@@ -1,35 +0,0 @@
-* Palmas 32KHz clocks *
-
-Palmas device has two clock output pins for 32KHz, KG and KG_AUDIO.
-
-This binding uses the common clock binding ./clock-bindings.txt.
-
-Required properties:
-- compatible :	"ti,palmas-clk32kg" for clk32kg clock
-		"ti,palmas-clk32kgaudio" for clk32kgaudio clock
-- #clock-cells : shall be set to 0.
-
-Optional property:
-- ti,external-sleep-control: The external enable input pins controlled the
-	enable/disable of clocks.  The external enable input pins ENABLE1,
-	ENABLE2 and NSLEEP. The valid values for the external pins are:
-		PALMAS_EXT_CONTROL_PIN_ENABLE1 for ENABLE1 pin
-		PALMAS_EXT_CONTROL_PIN_ENABLE2 for ENABLE2 pin
-		PALMAS_EXT_CONTROL_PIN_NSLEEP for NSLEEP pin
-	Option 0 or missing this property means the clock is enabled/disabled
-	via register access and these pins do not have any control.
-	The macros of external control pins for DTS is defined at
-	dt-bindings/mfd/palmas.h
-
-Example:
-	#include <dt-bindings/mfd/palmas.h>
-	...
-	palmas: tps65913@58 {
-		...
-		clk32kg: palmas_clk32k@0 {
-			compatible = "ti,palmas-clk32kg";
-			#clock-cells = <0>;
-			ti,external-sleep-control = <PALMAS_EXT_CONTROL_PIN_NSLEEP>;
-		};
-		...
-	};
diff --git a/Documentation/devicetree/bindings/clock/ti,palmas-clk32kg.yaml b/Documentation/devicetree/bindings/clock/ti,palmas-clk32kg.yaml
new file mode 100644
index 000000000000..c2a49be9b95a
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/ti,palmas-clk32kg.yaml
@@ -0,0 +1,56 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/ti,palmas-clk32kg.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Texas Instruments Palmas 32KHz Clocks
+
+maintainers:
+  - Eduard Bostina <egbostina@gmail.com>
+
+description:
+  The Palmas device family has two clock output pins for 32KHz,
+  KG and KG_AUDIO.
+
+allOf:
+  - $ref: /schemas/clock/clock.yaml#
+
+properties:
+  compatible:
+    enum:
+      - ti,palmas-clk32kg
+      - ti,palmas-clk32kgaudio
+
+  "#clock-cells":
+    const: 0
+
+  ti,external-sleep-control:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    enum: [ 0, 1, 2, 3 ]
+    description: |
+      The external enable input pins control the enable/disable of clocks.
+      The valid values (defined in dt-bindings/mfd/palmas.h) are:
+        1: PALMAS_EXT_CONTROL_PIN_ENABLE1
+        2: PALMAS_EXT_CONTROL_PIN_ENABLE2
+        3: PALMAS_EXT_CONTROL_PIN_NSLEEP
+      Option 0 or missing this property means the clock is enabled/disabled
+      via register access and these pins do not have any control.
+
+required:
+  - compatible
+  - "#clock-cells"
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/mfd/palmas.h>
+
+    pmic {
+        clock-controller {
+            compatible = "ti,palmas-clk32kg";
+            #clock-cells = <0>;
+            ti,external-sleep-control = <PALMAS_EXT_CONTROL_PIN_NSLEEP>;
+        };
+    };
-- 
2.43.0


^ permalink raw reply related

* Re: [PATCH 2/2] ARM: dts: ti: omap: Fix Palmas RTC node names
From: sashiko-bot @ 2026-07-19 14:13 UTC (permalink / raw)
  To: Eduard Bostina; +Cc: devicetree, conor+dt, robh, linux-rtc, Alexandre Belloni
In-Reply-To: <20260719141008.3562347-3-egbostina@gmail.com>

> The core RTC Device Tree schema expects RTC nodes to be named generically
> ('rtc' or 'rtc@...').
> 
> Update the tps659038_rtc nodes across the AM57xx device trees to use
> the generic 'rtc' node name to resolve dtbs_check warnings.
> 
> Signed-off-by: Eduard Bostina <egbostina@gmail.com>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260719141008.3562347-1-egbostina@gmail.com?part=2


^ permalink raw reply

* Re: [PATCH v7 1/4] dt-bindings: vendor-prefixes: Add GXCAS Technology
From: Guenter Roeck @ 2026-07-19 14:16 UTC (permalink / raw)
  To: Zaixiang Xu
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-hwmon,
	devicetree, linux-kernel, Conor Dooley, Krzysztof Kozlowski
In-Reply-To: <20260713074559.12196-2-zaixiang.xu.dev@gmail.com>

On Mon, Jul 13, 2026 at 03:45:56PM +0800, Zaixiang Xu wrote:
> Add vendor prefix for Beijing Galaxy-CAS Technology Co., Ltd. (GXCAS).
> The prefix was confirmed from the manufacturer's website:
> https://www.gxcas.com/en/index.html
> 
> Acked-by: Conor Dooley <conor.dooley@microchip.com>
> Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
> Signed-off-by: Zaixiang Xu <zaixiang.xu.dev@gmail.com>

Applied.

Thanks,
Guenter

^ permalink raw reply

* [PATCH] dt-bindings: input: Convert TI Palmas Power Button to DT schema
From: Eduard Bostina @ 2026-07-19 14:17 UTC (permalink / raw)
  To: Conor Dooley, devicetree, Dmitry Torokhov, Eduard Bostina,
	Krzysztof Kozlowski, linux-input, linux-kernel, Rob Herring
  Cc: daniel.baluta, simona.toaca, goledhruva, m-chawdhry

Convert the Texas Instruments Palmas power button bindings
to DT schema.

During the conversion, 'wakeup-source' was added.
It was missing from the original text binding but is actively
used by in-tree boards.

Signed-off-by: Eduard Bostina <egbostina@gmail.com>
---
 .../bindings/input/ti,palmas-pwrbutton.txt    | 35 -----------
 .../bindings/input/ti,palmas-pwrbutton.yaml   | 58 +++++++++++++++++++
 2 files changed, 58 insertions(+), 35 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/input/ti,palmas-pwrbutton.txt
 create mode 100644 Documentation/devicetree/bindings/input/ti,palmas-pwrbutton.yaml

diff --git a/Documentation/devicetree/bindings/input/ti,palmas-pwrbutton.txt b/Documentation/devicetree/bindings/input/ti,palmas-pwrbutton.txt
deleted file mode 100644
index c829e18e1a05..000000000000
--- a/Documentation/devicetree/bindings/input/ti,palmas-pwrbutton.txt
+++ /dev/null
@@ -1,35 +0,0 @@
-Texas Instruments Palmas family power button module
-
-This module is part of the Palmas family of PMICs. For more details
-about the whole chip see:
-Documentation/devicetree/bindings/mfd/palmas.txt.
-
-This module provides a simple power button event via an Interrupt.
-
-Required properties:
-- compatible: should be one of the following
-   - "ti,palmas-pwrbutton": For Palmas compatible power on button
-- interrupts: Interrupt number of power button submodule on device.
-
-Optional Properties:
-
-- ti,palmas-long-press-seconds: Duration in seconds which the power
-  button should be kept pressed for Palmas to power off automatically.
-  NOTE: This depends on OTP support and POWERHOLD signal configuration
-  on platform. Valid values are 6, 8, 10 and 12.
-- ti,palmas-pwron-debounce-milli-seconds: Duration in milliseconds
-  which the power button should be kept pressed for Palmas to register
-  a press for debouncing purposes. NOTE: This depends on specific
-  Palmas variation capability. Valid values are 15, 100, 500 and 1000.
-
-Example:
-
-&palmas {
-	palmas_pwr_button: pwrbutton {
-		compatible = "ti,palmas-pwrbutton";
-		interrupt-parent = <&tps659038>;
-		interrupts = <1 IRQ_TYPE_EDGE_FALLING>;
-		ti,palmas-long-press-seconds = <12>;
-		ti,palmas-pwron-debounce-milli-seconds = <15>;
-	};
-};
diff --git a/Documentation/devicetree/bindings/input/ti,palmas-pwrbutton.yaml b/Documentation/devicetree/bindings/input/ti,palmas-pwrbutton.yaml
new file mode 100644
index 000000000000..9f64caaac00d
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/ti,palmas-pwrbutton.yaml
@@ -0,0 +1,58 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/ti,palmas-pwrbutton.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Texas Instruments Palmas Power Button
+
+maintainers:
+  - Eduard Bostina <egbostina@gmail.com>
+
+description:
+  This module is part of the Palmas PMIC. It provides a simple power button
+  event via an interrupt.
+
+properties:
+  compatible:
+    const: ti,palmas-pwrbutton
+
+  interrupts:
+    maxItems: 1
+
+  ti,palmas-long-press-seconds:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    enum: [ 6, 8, 10, 12 ]
+    description: |
+      Duration in seconds which the power button should be kept pressed
+      for Palmas to power off automatically. NOTE: This depends on OTP
+      support and POWERHOLD signal configuration on platform.
+
+  ti,palmas-pwron-debounce-milli-seconds:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    enum: [ 15, 100, 500, 1000 ]
+    description: |
+      Duration in milliseconds which the power button should be kept
+      pressed for Palmas to register a press for debouncing purposes.
+      NOTE: This depends on specific Palmas variation capability.
+
+  wakeup-source: true
+
+required:
+  - compatible
+  - interrupts
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+
+    pmic {
+        power-button {
+            compatible = "ti,palmas-pwrbutton";
+            interrupts = <1 IRQ_TYPE_EDGE_FALLING>;
+            ti,palmas-long-press-seconds = <12>;
+            ti,palmas-pwron-debounce-milli-seconds = <15>;
+        };
+    };
-- 
2.43.0


^ permalink raw reply related

* Re: [PATCH v7 2/4] dt-bindings: hwmon: Add Sensirion SHT30 series
From: Guenter Roeck @ 2026-07-19 14:17 UTC (permalink / raw)
  To: Zaixiang Xu
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-hwmon,
	devicetree, linux-kernel
In-Reply-To: <20260713074559.12196-3-zaixiang.xu.dev@gmail.com>

On Mon, Jul 13, 2026 at 03:45:57PM +0800, Zaixiang Xu wrote:
> Add a YAML devicetree binding for the Sensirion SHT3x/STS3x sensor
> family and the compatible GXCAS GXHT30, with the ALERT interrupt,
> nRESET GPIO and VDD supply as optional properties.
> 
> The SHT30, SHT31, SHT35 and SHT85 measure humidity and temperature
> and differ only in accuracy and packaging, while the STS30, STS31,
> STS32 and STS35 are temperature-only parts. Within each group the
> parts share the same software interface, so model them with a
> fallback to the base part of their group: "sensirion,sht30" for the
> SHT parts and "sensirion,sts30" for the STS parts.
> 
> The GXCAS GXHT30 is a drop-in replacement for the SHT30 and uses it
> as fallback as well.
> 
> Signed-off-by: Zaixiang Xu <zaixiang.xu.dev@gmail.com>
> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>

Applied.

Thanks,
Guenter

^ permalink raw reply

* Re: [PATCH v7 3/4] hwmon: (sht3x) Add devicetree support
From: Guenter Roeck @ 2026-07-19 14:18 UTC (permalink / raw)
  To: Zaixiang Xu
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-hwmon,
	devicetree, linux-kernel
In-Reply-To: <20260713074559.12196-4-zaixiang.xu.dev@gmail.com>

On Mon, Jul 13, 2026 at 03:45:58PM +0800, Zaixiang Xu wrote:
> Add an of_device_id table to support devicetree based instantiation
> of the supported sensors.
> 
> The devicetree binding models all higher accuracy parts with a
> fallback to the base part of their group, so only the two base
> compatibles need to be listed. The match data distinguishes the
> humidity and temperature parts (SHT3x) from the temperature-only
> parts (STS3x), which require different configuration.
> 
> Start enum sht3x_chips at 1: with sht3x equal to 0, the OF match
> data for the SHT devices would be NULL, causing i2c_get_match_data()
> to fall back to i2c_device_id name matching, which fails for
> devicetree names. The devices would then only work because the
> resulting chip id 0 happens to equal sht3x. Non-zero match data
> avoids relying on that coincidence.
> 
> Signed-off-by: Zaixiang Xu <zaixiang.xu.dev@gmail.com>

Applied.

Thanks,
Guenter

^ permalink raw reply

* Re: [PATCH 1/2] dt-bindings: rtc: Convert TI Palmas RTC to DT schema
From: sashiko-bot @ 2026-07-19 14:18 UTC (permalink / raw)
  To: Eduard Bostina; +Cc: Alexandre Belloni, devicetree, linux-rtc, conor+dt, robh
In-Reply-To: <20260719141008.3562347-2-egbostina@gmail.com>

> Convert the Texas Instruments Palmas RTC controller bindings
> to DT schema.
> 
> As part of the conversion, declare 'wakeup-source: true'.
> This documents the Palmas PMIC's capability to wake the system.
> 
> Signed-off-by: Eduard Bostina <egbostina@gmail.com>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260719141008.3562347-1-egbostina@gmail.com?part=1


^ permalink raw reply

* Re: [PATCH v7 4/4] hwmon: (sht3x) Document support for GXCAS GXHT30
From: Guenter Roeck @ 2026-07-19 14:18 UTC (permalink / raw)
  To: Zaixiang Xu
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-hwmon,
	devicetree, linux-kernel
In-Reply-To: <20260713074559.12196-5-zaixiang.xu.dev@gmail.com>

On Mon, Jul 13, 2026 at 03:45:59PM +0800, Zaixiang Xu wrote:
> The GXCAS GXHT30 is a humidity and temperature sensor that is a
> drop-in replacement for and fully software compatible with the
> Sensirion SHT30.
> 
> It is handled by the "sensirion,sht30" fallback compatible without
> any driver changes; manual instantiation works with the existing
> sht3x device name. Document the chip as supported.
> 
> Signed-off-by: Zaixiang Xu <zaixiang.xu.dev@gmail.com>

Applied.

Thanks,
Guenter

^ permalink raw reply

* Re: [PATCH net-next v2 2/2] nfc: s3fwrn5: support the S3NRN4V variant
From: Jorijn van der Graaf @ 2026-07-19 14:22 UTC (permalink / raw)
  To: David Heidelberg, Krzysztof Kozlowski
  Cc: Jorijn van der Graaf, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Rob Herring, Conor Dooley,
	oe-linux-nfc, netdev, devicetree, linux-kernel, Luca Weiss
In-Reply-To: <18c3e13f-88e4-458e-9f57-7aceeb1ce1d1@ixit.cz>

Hello David,

Thank you for the review!

On 19/07/2026 15:15, David Heidelberg wrote:
> Please, send the "drop the of_match_ptr()/__maybe_unused annotations
> from it." type of change as part of the series, but as a separate
> commit before the new HW support introduction.

Will do in v3.

> Since you touch S3FWRN5_I2C_DRIVER_NAME, replace define
> S3FWRN5_I2C_DRIVER_NAME occurenced with the "s3fwrn5_i2c" directly
> before introducing the support (also separate commit)

Will do, also in v3.

> is S3NRN4V really a variant of S3FWRN5 or is it just S3NRN4V?

It is a separate, later part, but from the same Samsung S.LSI NFC
controller line this driver covers. Samsung's downstream stack drives
that whole line with one kernel driver and one HAL: the HAL's product
table lists the N5 (S3FWRN5) and N82 (S3FWRN82) generations next to
RN4V (S3NRN4V) and others, dispatching on a product code reported by
the chip's bootloader, and the parts share the I2C framing, the
power-control GPIO scheme and the proprietary-NCI style of
configuration. The generational differences (bootloader protocol,
RF-register transport command, FW_CFG payload form) are exactly what
this patch dispatches on -- the same way the driver already supports
the S3FWRN82 next to the S3FWRN5.

That said, "S3FWRN5-family" can indeed be read as "a variant of the
S3FWRN5 chip", which it is not, so I'll reword it in v3 to something
like "a later part of the same Samsung NFC controller line". The
phrase also sits in the commit message of the already-acked binding
patch; I'll tweak it there too (commit message only) and note it in
the changelog.

> While it's "register update" and function is named "configure_dual",
> it's loading firmware.
>
> If it's not a firmware, but only configuration, it can reside inside
> the driver, maybe LLM even be able to decode to understandable
> sequence of registers and values.

There are two separate things here: the chip's executable firmware
(~180 KiB) ships in its flash and is not touched by this patch at all
-- its download protocol is not implemented, which is why the
download step is skipped. What is loaded here are only the two RF
register tables (~3.5 KiB combined).

Those tables are configuration by nature, but I don't think they can
reside in the driver:

- They are board-specific analog/RF tuning, not chip constants: the
  values match a particular antenna/matching-network design, and the
  vendor revises them across software releases (my two Fairphone 6
  units shipped different builds of these files, with different
  version stamps embedded). A different S3NRN4V board design would be
  expected to ship its own tables. Per-device data loaded at runtime
  is what request_firmware() is there for, much like Wi-Fi
  board/calibration files. The tables ship in the device's vendor
  image, which is where I extracted them from.

- There is nothing to decode them against. The register map of these
  controllers is not publicly documented, and even Samsung's own
  (Apache-licensed) HAL treats the register content as opaque: the
  only part of the image it interprets is a 16-byte metadata trailer
  at its end (version stamps, used to decide whether an update is
  needed at all, plus a region code), while the register content
  itself is pushed to the chip untouched, in 252-byte sections.
  Nothing in the stream or in the vendor stack identifies
  address/value pairs one could transcribe, so "decoded" into the
  driver this could only become a 3.5 KiB hex array in C, and we
  would lose the ability to ship a newer table without rebuilding
  the kernel.

- It also mirrors what this driver already does for the parts it
  supports: s3fwrn5_nci_rf_configure() loads the same class of table
  (sec_s3fwrn5_rfreg.bin) with request_firmware() and pushes it via
  the older START/SET/STOP_RFREG commands. The new function is the
  same operation over the newer parts' transport command.

If the naming reads confusingly I'm happy to rename the function or
extend its comment to spell out the firmware-vs-register-table
distinction.

> For next revision of the patch, I'll likely still have some
> additional feedback.

Understood -- I'll send the v3 with all of the above shortly.

> With next revision send also as last patch the device-tree entry for
> the Fairphone 6, so we can also get additional testing from
> developers/users.

Will do -- v3 will carry the Fairphone 6 DT patch at the end of the
series, marked as included for testing and presumably to be picked up
via the Qualcomm DT tree once the driver side is settled; I'll Cc
linux-arm-msm and the qcom maintainers on that patch.

Thanks again,
Jorijn

^ permalink raw reply

* Re: [PATCH v2 3/5] hwmon: (pmbus/max20830): add VOUT feedback resistor scaling support
From: Guenter Roeck @ 2026-07-19 14:24 UTC (permalink / raw)
  To: sashiko-reviews, Alexis Czezar Torreno
  Cc: linux-hwmon, conor+dt, devicetree, robh
In-Reply-To: <20260706022155.C5B251F000E9@smtp.kernel.org>

On 7/5/26 19:21, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
> - [High] Scaled `PMBUS_READ_VOUT` value can exceed the 16-bit capacity of the PMBus `LINEAR16` format, causing silent truncation and incorrect voltage reporting.
> - [High] Missing software scaling for VOUT limit attributes and missing `.write_word_data` callback causes hardware limits to be programmed completely out of bounds.
> --
> 

Please comment on Sashiko's findings and either fix or explain in
comments why the issues do not apply.

Thanks,
Guenter

> commit 19e6041d100f0e80c9e49784d17900b141e3ea61
> Author: Alexis Czezar Torreno <alexisczezar.torreno@analog.com>
> 
> hwmon: (pmbus/max20830): add VOUT feedback resistor scaling support
>      
> Implement support for external voltage divider scaling using the
> adi,vout-rfb1-ohms and adi,vout-rfb2-ohms device tree properties.
> 
> When the desired output voltage exceeds VREF, a resistor divider
> (RFB1 and RFB2) is used to scale down the feedback voltage. The
> driver reads these resistor values from device tree and applies
> the scaling formula: VOUT_actual = VOUT_measured × (1 + RFB1/RFB2)
> 
>> diff --git a/drivers/hwmon/pmbus/max20830.c b/drivers/hwmon/pmbus/max20830.c
>> index cb2c23672166d..5aad4448054fc 100644
>> --- a/drivers/hwmon/pmbus/max20830.c
>> +++ b/drivers/hwmon/pmbus/max20830.c
> 
> [ ... ]
> 
>> @@ -14,6 +15,45 @@
>>   
>>   #define MAX20830_IC_DEVICE_ID_LENGTH	9
>>   
>> +struct max20830_data {
>> +	struct pmbus_driver_info info;
>> +	u32 vout_rfb1;
>> +	u32 vout_rfb2;
>> +};
>> +
>> +/*
>> + * Driver currently only supports READ_VOUT for monitoring that needs scaling to
>> + * convert from feedback voltage to actual output voltage.
>> + *
>> + * vout_actual = vout_fb × (1 + RFB1/RFB2)
>> + *
>> + * VOUT_COMMAND and VOUT_MAX are currently not in use, but work with feedback
>> + * voltage. If regulator support is added, VOUT_COMMAND values would need
>> + * to be adjusted accordingly.
>> + */
>> +static int max20830_read_word_data(struct i2c_client *client, int page,
>> +				   int phase, int reg)
>> +{
>> +	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
>> +	const struct max20830_data *data = container_of(info, struct max20830_data, info);
>> +	int ret;
>> +
>> +	switch (reg) {
>> +	case PMBUS_READ_VOUT:
>> +		ret = pmbus_read_word_data(client, page, phase, reg);
>> +		if (ret < 0)
>> +			return ret;
>> +
>> +		/* Apply voltage divider scaling if resistors are non-zero */
>> +		if (data->vout_rfb1 && data->vout_rfb2)
>> +			ret = DIV_ROUND_CLOSEST_ULL((u64)ret * (data->vout_rfb1 +
>> +						    data->vout_rfb2), data->vout_rfb2);
>> +		return ret;
> 
> [Severity: High]
> Does this returned value need bounds checking?
> 
> If a large resistor divider is used, the scaled PMBus word calculated here
> can exceed 0xFFFF. The generic PMBus core function pmbus_reg2data_linear()
> will cast this returned value to a u16, silently wrapping the value modulo
> 65536 and resulting in wildly incorrect telemetry (e.g., reporting 2V instead
> of 12V).
> 
> Should this be clamped using clamp_val(ret, 0, 0xffff)?
> 
>> +	default:
>> +		return -ENODATA;
>> +	}
>> +}
> 
> [Severity: High]
> Will returning -ENODATA bypass software scaling for VOUT limit attributes?
> 
> The driver sets PMBUS_HAVE_VOUT below, which exposes hardware VOUT limits
> (like inX_max or inX_lcrit). Because only PMBUS_READ_VOUT is intercepted
> here, the core will read those limits unscaled from the hardware.
> 
>> +
>>   static struct pmbus_driver_info max20830_info = {
>>   	.pages = 1,
>>   	.format[PSC_VOLTAGE_IN] = linear,
>> @@ -24,13 +64,25 @@ static struct pmbus_driver_info max20830_info = {
>>   		PMBUS_HAVE_TEMP |
>>   		PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT |
>>   		PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_STATUS_TEMP,
>> +	.read_word_data = max20830_read_word_data,
> 
> [Severity: High]
> Does this struct also need a .write_word_data callback?
> 
> Since PMBUS_HAVE_VOUT is enabled, user writes to limit attributes will fall
> through to the PMBus core, which writes the scaled PMBus word directly into
> the hardware's limit register. Because the hardware expects limits in the
> unscaled feedback voltage range, the written value will be completely out
> of bounds.
> 


^ permalink raw reply

* Re: [PATCH 1/2] dt-bindings: hwmon: Add MPS mpq82d00
From: Guenter Roeck @ 2026-07-19 14:28 UTC (permalink / raw)
  To: wenswang
  Cc: robh, krzk+dt, conor+dt, corbet, skhan, devicetree, linux-kernel,
	linux-hwmon, linux-doc
In-Reply-To: <20260704081952.1701914-1-wenswang@yeah.net>

On Sat, Jul 04, 2026 at 04:19:51PM +0800, wenswang@yeah.net wrote:
> From: Wensheng Wang <wenswang@yeah.net>
> 
> Add support for MPS mpq82d00 controller.
> 
> Signed-off-by: Wensheng Wang <wenswang@yeah.net>
> Acked-by: Conor Dooley <conor.dooley@microchip.com>

Applied.

Thanks,
Guenter

^ permalink raw reply

* Re: [PATCH 2/2] hwmon: add MPQ82D00 driver
From: Guenter Roeck @ 2026-07-19 14:29 UTC (permalink / raw)
  To: wenswang
  Cc: robh, krzk+dt, conor+dt, corbet, skhan, devicetree, linux-kernel,
	linux-hwmon, linux-doc
In-Reply-To: <20260704081952.1701914-2-wenswang@yeah.net>

On Sat, Jul 04, 2026 at 04:19:52PM +0800, wenswang@yeah.net wrote:
> From: Wensheng Wang <wenswang@yeah.net>
> 
> Add support for MPS mpq82d00 controller. This driver exposes
> telemetry and limit value readings and writtings.
> 
> Signed-off-by: Wensheng Wang <wenswang@yeah.net>

Applied.

Thanks,
Guenter

^ permalink raw reply

* Re: [PATCH v2 5/6] hwmon: (adt7470) Register as a PWM provider
From: Guenter Roeck @ 2026-07-19 14:49 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Chris Packham,
	Andrew Morton, Darrick J. Wong, Uwe Kleine-König,
	linux-hwmon, devicetree, linux-kernel, linux-pwm
In-Reply-To: <20260717-adt7470_thermalzone-v2-5-a55147958fad@gmail.com>

On Fri, Jul 17, 2026 at 05:59:18PM -0300, Luiz Angelo Daros de Luca wrote:
> hwmon: (adt7470) Register as a PWM provider
> 
> The ADT7470 features four PWM outputs that can be used to control fans.
> Previously, these were only accessible through the legacy hwmon sysfs
> interface.
> 
> Register the ADT7470 as a generic PWM provider. This enables standard
> Device Tree PWM consumers, such as "pwm-fan", to use the device through
> the "#pwm-cells" property.

Use case, please.

Thanks,
Guenter

^ permalink raw reply

* Re: [PATCH 1/2] dt-bindings: rtc: Convert TI Palmas RTC to DT schema
From: Alexandre Belloni @ 2026-07-19 14:56 UTC (permalink / raw)
  To: Eduard Bostina
  Cc: Aaro Koskinen, Andreas Kemnade, Conor Dooley, devicetree,
	Kevin Hilman, Krzysztof Kozlowski, linux-kernel, linux-omap,
	linux-rtc, Rob Herring, Roger Quadros, Tony Lindgren,
	daniel.baluta, simona.toaca, goledhruva, m-chawdhry
In-Reply-To: <20260719141008.3562347-2-egbostina@gmail.com>

On 19/07/2026 14:10:07+0000, Eduard Bostina wrote:
> Convert the Texas Instruments Palmas RTC controller bindings
> to DT schema.
> 
> As part of the conversion, declare 'wakeup-source: true'.
> This documents the Palmas PMIC's capability to wake the system.
> 
> Signed-off-by: Eduard Bostina <egbostina@gmail.com>
> ---
>  .../devicetree/bindings/rtc/rtc-palmas.txt    | 32 -----------
>  .../bindings/rtc/ti,palmas-rtc.yaml           | 57 +++++++++++++++++++
>  2 files changed, 57 insertions(+), 32 deletions(-)
>  delete mode 100644 Documentation/devicetree/bindings/rtc/rtc-palmas.txt
>  create mode 100644 Documentation/devicetree/bindings/rtc/ti,palmas-rtc.yaml
> 
> diff --git a/Documentation/devicetree/bindings/rtc/rtc-palmas.txt b/Documentation/devicetree/bindings/rtc/rtc-palmas.txt
> deleted file mode 100644
> index c6cf37758a77..000000000000
> --- a/Documentation/devicetree/bindings/rtc/rtc-palmas.txt
> +++ /dev/null
> @@ -1,32 +0,0 @@
> -Palmas RTC controller bindings
> -
> -Required properties:
> -- compatible:
> -  - "ti,palmas-rtc" for palma series of the RTC controller
> -- interrupts: Interrupt number of RTC submodule on device.
> -
> -Optional properties:
> -
> -- ti,backup-battery-chargeable: The Palmas series device like TPS65913 or
> -	TPS80036 supports the backup battery for powering the RTC when main
> -	battery is removed or in very low power state. The backup battery
> -	can be chargeable or non-chargeable. This flag will tells whether
> -	battery is chargeable or not. If charging battery then driver can
> -	enable the charging.
> -- ti,backup-battery-charge-high-current: Enable high current charging in
> -	backup battery. Device supports the < 100uA and > 100uA charging.
> -	The high current will be > 100uA. Absence of this property will
> -	charge battery to lower current i.e. < 100uA.
> -
> -Example:
> -	palmas: tps65913@58 {
> -		...
> -		palmas_rtc: rtc {
> -			compatible = "ti,palmas-rtc";
> -			interrupt-parent = <&palmas>;
> -			interrupts = <8 0>;
> -			ti,backup-battery-chargeable;
> -			ti,backup-battery-charge-high-current;
> -		};
> -		...
> -	};
> diff --git a/Documentation/devicetree/bindings/rtc/ti,palmas-rtc.yaml b/Documentation/devicetree/bindings/rtc/ti,palmas-rtc.yaml
> new file mode 100644
> index 000000000000..ac64f0589c84
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/rtc/ti,palmas-rtc.yaml
> @@ -0,0 +1,57 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/rtc/ti,palmas-rtc.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Texas Instruments Palmas RTC
> +
> +maintainers:
> +  - Eduard Bostina <egbostina@gmail.com>
> +
> +allOf:
> +  - $ref: /schemas/rtc/rtc.yaml#
> +
> +properties:
> +  compatible:
> +    const: ti,palmas-rtc
> +
> +  interrupts:
> +    maxItems: 1
> +
> +  wakeup-source: true
> +
> +  ti,backup-battery-chargeable:
> +    type: boolean
> +    description:
> +      The backup battery can be chargeable or non-chargeable. This flag
> +      indicates whether the battery is chargeable. If present, the driver
> +      can enable charging.
> +

It would be great to convert to the genric proeprty which is
aux-voltage-chargeable from rtc.yaml

> +  ti,backup-battery-charge-high-current:
> +    type: boolean
> +    description:
> +      Enable high current charging in the backup battery.
> +      Device supports the < 100uA and > 100uA charging. The high current will
> +      be > 100uA. Absence of this property will charge battery to lower
> +      current i.e. < 100uA.


I guess we could make trickle-resistor-ohms fit or get a new generic
property for this.

-- 
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

^ permalink raw reply

* Re: [PATCH net-next v2 2/2] nfc: s3fwrn5: support the S3NRN4V variant
From: David Heidelberg @ 2026-07-19 14:56 UTC (permalink / raw)
  To: Jorijn van der Graaf, Luca Weiss, Krzysztof Kozlowski
  Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Rob Herring, Conor Dooley, oe-linux-nfc, netdev,
	devicetree, linux-kernel
In-Reply-To: <20260719142241.12640-1-jorijnvdgraaf@catcrafts.net>

On 19/07/2026 16:22, Jorijn van der Graaf wrote:
> Hello David,
> 
> Thank you for the review!
> 
> On 19/07/2026 15:15, David Heidelberg wrote:
>> Please, send the "drop the of_match_ptr()/__maybe_unused annotations
>> from it." type of change as part of the series, but as a separate
>> commit before the new HW support introduction.
> 
> Will do in v3.
> 
>> Since you touch S3FWRN5_I2C_DRIVER_NAME, replace define
>> S3FWRN5_I2C_DRIVER_NAME occurenced with the "s3fwrn5_i2c" directly
>> before introducing the support (also separate commit)
> 
> Will do, also in v3.
> 
>> is S3NRN4V really a variant of S3FWRN5 or is it just S3NRN4V?
> 
> It is a separate, later part, but from the same Samsung S.LSI NFC
> controller line this driver covers. Samsung's downstream stack drives
> that whole line with one kernel driver and one HAL: the HAL's product
> table lists the N5 (S3FWRN5) and N82 (S3FWRN82) generations next to
> RN4V (S3NRN4V) and others, dispatching on a product code reported by
> the chip's bootloader, and the parts share the I2C framing, the
> power-control GPIO scheme and the proprietary-NCI style of
> configuration. The generational differences (bootloader protocol,
> RF-register transport command, FW_CFG payload form) are exactly what
> this patch dispatches on -- the same way the driver already supports
> the S3FWRN82 next to the S3FWRN5.
> 
> That said, "S3FWRN5-family" can indeed be read as "a variant of the
> S3FWRN5 chip", which it is not, so I'll reword it in v3 to something
> like "a later part of the same Samsung NFC controller line". The
> phrase also sits in the commit message of the already-acked binding
> patch; I'll tweak it there too (commit message only) and note it in
> the changelog.
> 
>> While it's "register update" and function is named "configure_dual",
>> it's loading firmware.
>>
>> If it's not a firmware, but only configuration, it can reside inside
>> the driver, maybe LLM even be able to decode to understandable
>> sequence of registers and values.
> 
> There are two separate things here: the chip's executable firmware
> (~180 KiB) ships in its flash and is not touched by this patch at all
> -- its download protocol is not implemented, which is why the
> download step is skipped. What is loaded here are only the two RF
> register tables (~3.5 KiB combined).
> 
> Those tables are configuration by nature, but I don't think they can
> reside in the driver:
> 
> - They are board-specific analog/RF tuning, not chip constants: the
>    values match a particular antenna/matching-network design, and the
>    vendor revises them across software releases (my two Fairphone 6
>    units shipped different builds of these files, with different
>    version stamps embedded). A different S3NRN4V board design would be
>    expected to ship its own tables. Per-device data loaded at runtime
>    is what request_firmware() is there for, much like Wi-Fi
>    board/calibration files. The tables ship in the device's vendor
>    image, which is where I extracted them from.
> 
> - There is nothing to decode them against. The register map of these
>    controllers is not publicly documented, and even Samsung's own
>    (Apache-licensed) HAL treats the register content as opaque: the
>    only part of the image it interprets is a 16-byte metadata trailer
>    at its end (version stamps, used to decide whether an update is
>    needed at all, plus a region code), while the register content
>    itself is pushed to the chip untouched, in 252-byte sections.
>    Nothing in the stream or in the vendor stack identifies
>    address/value pairs one could transcribe, so "decoded" into the
>    driver this could only become a 3.5 KiB hex array in C, and we
>    would lose the ability to ship a newer table without rebuilding
>    the kernel.
> 
> - It also mirrors what this driver already does for the parts it
>    supports: s3fwrn5_nci_rf_configure() loads the same class of table
>    (sec_s3fwrn5_rfreg.bin) with request_firmware() and pushes it via
>    the older START/SET/STOP_RFREG commands. The new function is the
>    same operation over the newer parts' transport command.
> 
> If the naming reads confusingly I'm happy to rename the function or
> extend its comment to spell out the firmware-vs-register-table
> distinction.

Thanks,

now it makes more sense to me, feel free to name it as calibration data.

I would suggest to introduce something as a calibration-variant (see ath10k code).

If I understand right, firmware location path could look like

default path + driver vendor and model + device vendor and model + revision

/lib/firmware/ + Samsung/s3nrn4v/ + Fairphone/FP5/hwrevision.bin

/cc Luca here, as he may know more about the different configuration data shipped.

We should assume the configuration will be shipped with linux-firmware at some 
point.

David

> 
>> For next revision of the patch, I'll likely still have some
>> additional feedback.
> 
> Understood -- I'll send the v3 with all of the above shortly.
> 
>> With next revision send also as last patch the device-tree entry for
>> the Fairphone 6, so we can also get additional testing from
>> developers/users.
> 
> Will do -- v3 will carry the Fairphone 6 DT patch at the end of the
> series, marked as included for testing and presumably to be picked up
> via the Qualcomm DT tree once the driver side is settled; I'll Cc
> linux-arm-msm and the qcom maintainers on that patch.
> 
> Thanks again,
> Jorijn

-- 
David Heidelberg


^ permalink raw reply

* Re: [PATCH v2 3/4] hwmon: (kb9002) Add driver for Kandou KB9002 retimer
From: Guenter Roeck @ 2026-07-19 14:58 UTC (permalink / raw)
  To: sashiko-reviews, Andy Chung; +Cc: conor+dt, robh, linux-hwmon, devicetree
In-Reply-To: <20260715091724.18BC21F000E9@smtp.kernel.org>

On 7/15/26 02:17, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
> - [Medium] The driver implements its own internal mutex for locking hardware accesses instead of using the hwmon subsystem's `hwmon_lock()` API.
> - [Low] The `i2c_device_id` array is initialized using a positional instead of a named initializer.
> --
> 
> --- Patch [3]: [PATCH v2 3/4] hwmon: (kb9002) Add driver for Kandou KB9002 retimer ---
> commit 59c6448090144292eb629f4257436694b1eaaa0d
> Author: Andy Chung <Andy.Chung@amd.com>
> 
> hwmon: (kb9002) Add driver for Kandou KB9002 retimer
>      
> The Kandou KB9002 is an 8-lane PCIe 5.0 retimer that exposes an SMBus
> target with mandatory PEC. Add a hwmon driver reporting the firmware
> aggregated maximum die temperature as temp1_input, with the firmware
> version and boot status under debugfs.
> 
>> diff --git a/drivers/hwmon/kb9002.c b/drivers/hwmon/kb9002.c
>> new file mode 100644
>> index 0000000000000..94c7d95b3fff5
>> --- /dev/null
>> +++ b/drivers/hwmon/kb9002.c
> [ ... ]
>> +struct kb9002_data {
>> +	struct i2c_client *client;
>> +	struct mutex lock;	/* serialises register accesses */
>> +};
> [ ... ]
>> +static int kb9002_fw_read(struct kb9002_data *data, u16 reg, u32 *val)
>> +{
>> +	struct i2c_client *client = data->client;
>> +	u8 addr[2];
>> +	u8 rbuf[I2C_SMBUS_BLOCK_MAX];
>> +	int ret;
>> +
>> +	put_unaligned_le16(reg, addr);
>> +
>> +	mutex_lock(&data->lock);
> 
> [Severity: Medium]
> Is this custom mutex necessary? The hwmon subsystem guidelines state that
> drivers should use hwmon_lock() and hwmon_unlock() to serialize operations
> for attributes registered by other means.
> 
> By using a custom internal mutex, does the driver bypass the standard
> subsystem synchronization architecture and introduce inefficient double-locking
> on sysfs reads, which are already protected by the hwmon core?
> 

Same question here. I do not see the point of this additional lock.

> [ ... ]
>> +static const struct i2c_device_id kb9002_id[] = {
>> +	{ KB9002_DEV_NAME },
>> +	{ }
>> +};
> 
> [Severity: Low]
> This isn't a bug, but does this array initialization bypass the I2C
> subsystem guidelines?
> 
> The I2C client initialization rules request that initialized arrays of type
> struct i2c_device_id use named initializers rather than positional
> initializers.
> 
Correct. Please fix.

Thanks,
Guenter


^ permalink raw reply

* Re: [PATCH v5 2/4] clk: sunxi-ng: div: add read-only operation support
From: Chen-Yu Tsai @ 2026-07-19 15:12 UTC (permalink / raw)
  To: Jerome Brunet
  Cc: sashiko-reviews, robh, linux-rtc, conor+dt, devicetree,
	linux-sunxi, Alexandre Belloni, linux-clk
In-Reply-To: <1jqzkzds54.fsf@starbuckisacylon.baylibre.com>

On Sun, Jul 19, 2026 at 9:29 PM Jerome Brunet <jbrunet@baylibre.com> wrote:
>
> On dim. 19 juil. 2026 at 18:59, Chen-Yu Tsai <wens@kernel.org> wrote:
>
> >
> >> > +
> >> > +     } else {
> >>
> >> [ ... ]
> >>
> >> > @@ -143,3 +157,15 @@ const struct clk_ops ccu_div_ops = {
> >> >       .set_rate       = ccu_div_set_rate,
> >> >  };
> >> >  EXPORT_SYMBOL_NS_GPL(ccu_div_ops, "SUNXI_CCU");
> >> > +
> >> > +const struct clk_ops ccu_rodiv_ops = {
> >> > +     .disable        = ccu_div_disable,
> >> > +     .enable         = ccu_div_enable,
> >> > +     .is_enabled     = ccu_div_is_enabled,
> >> > +
> >> > +     .get_parent     = ccu_div_get_parent,
> >> > +
> >> > +     .determine_rate = ccu_div_determine_rate,
> >> > +     .recalc_rate    = ccu_div_recalc_rate,
> >> > +};
> >>
> >> [Severity: High]
> >> Could the missing .set_parent callback in ccu_rodiv_ops lead to a silent
> >> desynchronization between the software clock tree and the hardware?
> >>
> >> The struct provides reparenting capabilities via .get_parent and
> >> .determine_rate, but omits .set_parent. If a rate request causes
> >> ccu_mux_helper_determine_rate() to evaluate and select a new parent, the
> >> Common Clock Framework will apply this new parent in software but skip
> >> updating the hardware since .set_parent is NULL.
> >
> > This is an issue. I'm not sure if what Sashiko says actually happens.
>
> I think it could. I've defenitely made a mistake here.
>
> > But 1. this is "read-only divider", not "read-only mux & divider",
>
> The correct way to choose between the 2 is CLK_SET_RATE_NO_REPARENT I think.

For standard muxes, just dropping the .set_parent and .determine_rate
callbacks works. The core will just pass the determine_rate request
to the current parent. In fact that is what the basic clk-mux does.
However we have to deal with the pre-dividers, so we need the
.determine_rate callback.

On the other hand CLK_SET_RATE_NO_REPARENT just says that the rate change
cannot reparent the clock. And it requires the ops to actually check for
it. (In the past we didn't always check ...). So we should still drop the
.set_parent op for clarity.

But I think the main thing is that the naming and your intention in
this patch is that the divider is read-only, not the mux.

> > so the .set_parent callback should be provided. And 2. this is using
> > the ccu_mux_determine_rate_helper, so it's possible a clk_set_rate()
> > call is going to cause a reparent.
> >
> > I can add it while applying if there are no other issues.
>
> As you prefer, I don't mind sending another version in a few days
> (giving some review time to patch #1)

That also works if you want to do it. It does help with preserving
history.


Thanks
ChenYu

^ permalink raw reply

* [PATCH v6 0/2] This series adds LT9211C bridge driver by extending LT9211
From: vishnu.saini @ 2026-07-19 15:57 UTC (permalink / raw)
  To: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Luca Ceresoli, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Marek Vasut
  Cc: dri-devel, devicetree, linux-kernel, Yi Zhang, Nilesh Laad,
	Gopi Botlagunta, Vishnu Saini, venkata.valluru, Jessica Zhang

LT9211c is a Single/Dual-Link DSI/LVDS or Single DPI input to
Single-link/Dual-Link DSI/LVDS or Single DPI output bridge chip.
This adds support for DSI to LVDS bridge configuration. By extending the
existing lontium-lt9211 driver to support DSI-to-LVDS bridge configuration.

Signed-off-by: Yi Zhang <zhanyi@qti.qualcomm.com>
Signed-off-by: Nilesh Laad <nilesh.laad@oss.qualcomm.com>
Signed-off-by: Gopi Botlagunta <venkata.botlagunta@oss.qualcomm.com>
Signed-off-by: Vishnu Saini <vishnu.saini@oss.qualcomm.com>
---
Changes in v6:
- Nilesh Laad and Gopi Botlagunta  moved to different org in Qualcomm. Further, i will followup on this series with community, will also submit the dt series where LT9211C bridge is used.
- Rebased onto current drm-misc-next (commit 671b7825dbfe)
- Fixed lt9211_read_chipid: LT9211 match no longer checks chipid[2],
  preserving compatibility with LT9211 rev U5 (db74b04edce1)
- Fixed indentation in lt9211_atomic_enable LT9211 path (was double-indented)
- Fixed indentation in lt9211_delayed_work_func body (was double-indented)
- Gated workqueue creation on LT9211C chip type only
- Fixed few formatting warnings with coccinelle and W=1
- Link to v5: https://lore.kernel.org/r/20260323-add-lt9211c-bridge-v5-0-9c63bb035c17@oss.qualcomm.com

Changes in v5:
- Addressed code formatting in lt9211 driver (no functional or design changes)
- Addressed v4 comments on lontium-lt9211.yaml
- Link to v4: https://lore.kernel.org/r/20251224-add-lt9211c-bridge-v4-0-406e73ec28c5@oss.qualcomm.com

Changes in v4:
- Removed lontium-lt9211c.yaml
- Extended lontium-lt9211.yaml to support LT9211C
- Link to v3: https://lore.kernel.org/r/20251218-add-lt9211c-bridge-v3-0-1ee0670a0db2@oss.qualcomm.com

Changes in v3:
- Removed lontium-lt9211c as separate driver
- Add support to lontium-lt9211c bridge driver by extending the existing lontium-lt9211.c
- Fixed kernel test robot reported build errors
- Link to v2: https://lore.kernel.org/lkml/20251107-add-lt9211c-bridge-v2-0-b0616e23407c@oss.qualcomm.com/

Changes in v2:
- Combined driver patch from https://lore.kernel.org/lkml/20250911-lt9211c-bridge-support-v1-1-c221202cbcd5@oss.qualcomm.com/
- Added MODULE_AUTHOR
- Uppercase to lowercase for hex values
- Link to v1: https://lore.kernel.org/r/20250910-add-lt9211c-bridge-v1-1-4f23740fe101@oss.qualcomm.com

---
Yi Zhang (2):
      dt-bindings: display: bridge: lontium,lt9211: Add lt9211c support
      drm/bridge: add support for lontium lt9211c bridge

 .../bindings/display/bridge/lontium,lt9211.yaml    |   5 +-
 drivers/gpu/drm/bridge/lontium-lt9211.c            | 796 ++++++++++++++++++++-
 2 files changed, 782 insertions(+), 19 deletions(-)
---
base-commit: 671b7825dbfe9ea6e3ad3001003aeee0df48d1b5
change-id: 20250910-add-lt9211c-bridge-5a21fcb1c803

Best regards,
-- 
Vishnu Saini <vishnu.saini@oss.qualcomm.com>


^ permalink raw reply


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