linux-phy.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/2] dt-bindings: phy: add mtk-mipi-csi driver
       [not found] <20230403071929.360911-1-jstephan@baylibre.com>
@ 2023-04-03  7:19 ` Julien Stephan
  2023-04-03  9:49   ` Krzysztof Kozlowski
                     ` (2 more replies)
  2023-04-03  7:19 ` [PATCH 2/2] phy: mtk-mipi-csi: add driver for CSI phy Julien Stephan
  1 sibling, 3 replies; 13+ messages in thread
From: Julien Stephan @ 2023-04-03  7:19 UTC (permalink / raw)
  Cc: Florian Sylvestre, Julien Stephan, Chunfeng Yun, Andy Hsieh,
	Vinod Koul, Kishon Vijay Abraham I, Rob Herring,
	Krzysztof Kozlowski, Matthias Brugger,
	AngeloGioacchino Del Regno,
	moderated list:ARM/Mediatek USB3 PHY DRIVER,
	moderated list:ARM/Mediatek USB3 PHY DRIVER,
	open list:GENERIC PHY FRAMEWORK,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list

From: Florian Sylvestre <fsylvestre@baylibre.com>

Signed-off-by: Florian Sylvestre <fsylvestre@baylibre.com>
Signed-off-by: Julien Stephan <jstephan@baylibre.com>
---
 .../bindings/phy/mediatek,csi-phy.yaml        | 41 +++++++++++++++++++
 MAINTAINERS                                   |  6 +++
 2 files changed, 47 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/phy/mediatek,csi-phy.yaml

diff --git a/Documentation/devicetree/bindings/phy/mediatek,csi-phy.yaml b/Documentation/devicetree/bindings/phy/mediatek,csi-phy.yaml
new file mode 100644
index 000000000000..c026e43f35fd
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/mediatek,csi-phy.yaml
@@ -0,0 +1,41 @@
+# SPDX-License-Identifier: (GPL-2.0-Only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/mediatek,csi-phy.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Mediatek Sensor Interface MIPI CSI CD-PHY
+
+maintainers:
+  - Julien Stephan <jstephan@baylibre.com>
+  - Andy Hsieh <andy.hsieh@mediatek.com>
+
+description: |
+  The SENINF CD-PHY is a set of CD-PHY connected to the SENINF CSI-2
+  receivers. The number of PHYs depends on the SoC model.
+
+properties:
+  compatible:
+    const: mediatek,mt8365-mipi-csi
+
+  reg:
+    minItems: 1
+
+  '#phy-cells':
+    const: 1
+
+required:
+  - compatible
+  - reg
+  - '#phy-cells'
+
+additionalProperties: false
+
+examples:
+  - |
+    phy@10011800 {
+        compatible = "mediatek,mt8365-mipi-csi";
+        reg = <0 0x10011800 0 0x60>;
+        #phy-cells = <1>;
+    };
+...
diff --git a/MAINTAINERS b/MAINTAINERS
index 6d54f3193075..9308b4bb88bf 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -13098,6 +13098,12 @@ F:	Documentation/devicetree/bindings/media/mediatek-vpu.txt
 F:	drivers/media/platform/mediatek/vcodec/
 F:	drivers/media/platform/mediatek/vpu/
 
+MEDIATEK MIPI-CSI CDPHY DRIVER
+M:	Julien Stephan <jstephan@baylibre.com>
+M:	Andy Hsieh <andy.hsieh@mediatek.com>
+S:	Supported
+F:	Documentation/devicetree/bindings/phy/mediatek,csi-phy.yaml
+
 MEDIATEK MMC/SD/SDIO DRIVER
 M:	Chaotian Jing <chaotian.jing@mediatek.com>
 S:	Maintained
-- 
2.40.0


-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

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

* [PATCH 2/2] phy: mtk-mipi-csi: add driver for CSI phy
       [not found] <20230403071929.360911-1-jstephan@baylibre.com>
  2023-04-03  7:19 ` [PATCH 1/2] dt-bindings: phy: add mtk-mipi-csi driver Julien Stephan
@ 2023-04-03  7:19 ` Julien Stephan
  2023-04-03  9:51   ` Krzysztof Kozlowski
                     ` (5 more replies)
  1 sibling, 6 replies; 13+ messages in thread
From: Julien Stephan @ 2023-04-03  7:19 UTC (permalink / raw)
  Cc: Phi-bang Nguyen, Louis Kuo, Julien Stephan, Chunfeng Yun,
	Andy Hsieh, Vinod Koul, Kishon Vijay Abraham I, Rob Herring,
	Krzysztof Kozlowski, Chun-Kuang Hu, Philipp Zabel,
	Matthias Brugger, AngeloGioacchino Del Regno,
	moderated list:ARM/Mediatek USB3 PHY DRIVER,
	moderated list:ARM/Mediatek USB3 PHY DRIVER,
	open list:GENERIC PHY FRAMEWORK,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list, open list:DRM DRIVERS FOR MEDIATEK

From: Phi-bang Nguyen <pnguyen@baylibre.com>

This is a new driver that supports the MIPI CSI CD-PHY for mediatek
mt8365 soc

Signed-off-by: Louis Kuo <louis.kuo@mediatek.com>
Signed-off-by: Phi-bang Nguyen <pnguyen@baylibre.com>
[Julien Stephan: use regmap]
[Julien Stephan: use GENMASK]
Co-developed-by: Julien Stephan <jstephan@baylibre.com>
Signed-off-by: Julien Stephan <jstephan@baylibre.com>
---
 .../bindings/phy/mediatek,csi-phy.yaml        |   9 +-
 MAINTAINERS                                   |   1 +
 drivers/phy/mediatek/Kconfig                  |   8 +
 drivers/phy/mediatek/Makefile                 |   2 +
 .../phy/mediatek/phy-mtk-mipi-csi-rx-reg.h    | 435 ++++++++++++++++++
 drivers/phy/mediatek/phy-mtk-mipi-csi.c       | 392 ++++++++++++++++
 6 files changed, 845 insertions(+), 2 deletions(-)
 create mode 100644 drivers/phy/mediatek/phy-mtk-mipi-csi-rx-reg.h
 create mode 100644 drivers/phy/mediatek/phy-mtk-mipi-csi.c

diff --git a/Documentation/devicetree/bindings/phy/mediatek,csi-phy.yaml b/Documentation/devicetree/bindings/phy/mediatek,csi-phy.yaml
index c026e43f35fd..ad4ba1d93a68 100644
--- a/Documentation/devicetree/bindings/phy/mediatek,csi-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/mediatek,csi-phy.yaml
@@ -33,9 +33,14 @@ additionalProperties: false
 
 examples:
   - |
-    phy@10011800 {
+    soc {
+      #address-cells = <2>;
+      #size-cells = <2>;
+
+      phy@11c10000 {
         compatible = "mediatek,mt8365-mipi-csi";
-        reg = <0 0x10011800 0 0x60>;
+        reg = <0 0x11c10000 0 0x4000>;
         #phy-cells = <1>;
+      };
     };
 ...
diff --git a/MAINTAINERS b/MAINTAINERS
index 9308b4bb88bf..b3077eddd0bf 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -13103,6 +13103,7 @@ M:	Julien Stephan <jstephan@baylibre.com>
 M:	Andy Hsieh <andy.hsieh@mediatek.com>
 S:	Supported
 F:	Documentation/devicetree/bindings/phy/mediatek,csi-phy.yaml
+F:	drivers/phy/mediatek/phy-mtk-mipi-csi*
 
 MEDIATEK MMC/SD/SDIO DRIVER
 M:	Chaotian Jing <chaotian.jing@mediatek.com>
diff --git a/drivers/phy/mediatek/Kconfig b/drivers/phy/mediatek/Kconfig
index 3125ecb5d119..63fb0fa77573 100644
--- a/drivers/phy/mediatek/Kconfig
+++ b/drivers/phy/mediatek/Kconfig
@@ -74,3 +74,11 @@ config PHY_MTK_DP
 	select GENERIC_PHY
 	help
 	  Support DisplayPort PHY for MediaTek SoCs.
+
+config PHY_MTK_MIPI_CSI
+	tristate "MediaTek CSI CD-PHY Driver"
+	depends on ARCH_MEDIATEK && OF
+	select GENERIC_PHY
+	help
+	  Enable this to support the MIPI CSI CD-PHY receiver.
+	  The driver supports multiple CSI cdphy ports simultaneously.
diff --git a/drivers/phy/mediatek/Makefile b/drivers/phy/mediatek/Makefile
index fb1f8edaffa7..9a178c1c2628 100644
--- a/drivers/phy/mediatek/Makefile
+++ b/drivers/phy/mediatek/Makefile
@@ -18,3 +18,5 @@ phy-mtk-mipi-dsi-drv-y			:= phy-mtk-mipi-dsi.o
 phy-mtk-mipi-dsi-drv-y			+= phy-mtk-mipi-dsi-mt8173.o
 phy-mtk-mipi-dsi-drv-y			+= phy-mtk-mipi-dsi-mt8183.o
 obj-$(CONFIG_PHY_MTK_MIPI_DSI)		+= phy-mtk-mipi-dsi-drv.o
+
+obj-$(CONFIG_PHY_MTK_MIPI_CSI)		+= phy-mtk-mipi-csi.o
diff --git a/drivers/phy/mediatek/phy-mtk-mipi-csi-rx-reg.h b/drivers/phy/mediatek/phy-mtk-mipi-csi-rx-reg.h
new file mode 100644
index 000000000000..f360e807e3d1
--- /dev/null
+++ b/drivers/phy/mediatek/phy-mtk-mipi-csi-rx-reg.h
@@ -0,0 +1,435 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __MIPI_CDPHY_RX_REG_H__
+#define __MIPI_CDPHY_RX_REG_H__
+
+/*
+ * CSI1 and CSI2 are identical, and similar to CSI0. All CSIx macros are
+ * applicable to the three PHYs. Where differences exist, they are denoted by
+ * macro names using CSI0 and CSI1, the latter being applicable to CSI1 and
+ * CSI2 alike.
+ */
+
+/*
+ * Due to lanes supporting C-PHY mode on CSI0, register fields that control the
+ * behaviour of lanes are named differently between CSI0 and CSI1/CSI2, even
+ * when they control parameters that are agnostic to the PHY mode. In those
+ * cases, the macros below use the CSI0 field names (e.g.
+ * MIPI_RX_ANA08_CSIxA_RG_CSIxA_L0P_T0A_HSRT_CODE_SHIFT).
+ */
+
+#define MIPI_RX_ANA00_CSIxA							0x0000
+#define MIPI_RX_ANA00_CSIxA_RG_CSI0A_CPHY_EN_SHIFT				0
+#define MIPI_RX_ANA00_CSIxA_RG_CSI0A_CPHY_EN_MASK				BIT(0)
+#define MIPI_RX_ANA00_CSIxA_RG_CSIxA_EQ_PROTECT_EN_SHIFT			1
+#define MIPI_RX_ANA00_CSIxA_RG_CSIxA_EQ_PROTECT_EN_MASK				BIT(1)
+#define MIPI_RX_ANA00_CSIxA_RG_CSIxA_BG_LPF_EN_SHIFT				2
+#define MIPI_RX_ANA00_CSIxA_RG_CSIxA_BG_LPF_EN_MASK				BIT(2)
+#define MIPI_RX_ANA00_CSIxA_RG_CSIxA_BG_CORE_EN_SHIFT				3
+#define MIPI_RX_ANA00_CSIxA_RG_CSIxA_BG_CORE_EN_MASK				BIT(3)
+#define MIPI_RX_ANA00_CSIxA_RG_CSIxA_DPHY_L0_CKMODE_EN_SHIFT			5
+#define MIPI_RX_ANA00_CSIxA_RG_CSIxA_DPHY_L0_CKMODE_EN_MASK			BIT(5)
+#define MIPI_RX_ANA00_CSIxA_RG_CSIxA_DPHY_L0_CKSEL_SHIFT			6
+#define MIPI_RX_ANA00_CSIxA_RG_CSIxA_DPHY_L0_CKSEL_MASK				BIT(6)
+#define MIPI_RX_ANA00_CSIxA_RG_CSIxA_DPHY_L1_CKMODE_EN_SHIFT			8
+#define MIPI_RX_ANA00_CSIxA_RG_CSIxA_DPHY_L1_CKMODE_EN_MASK			BIT(8)
+#define MIPI_RX_ANA00_CSIxA_RG_CSIxA_DPHY_L1_CKSEL_SHIFT			9
+#define MIPI_RX_ANA00_CSIxA_RG_CSIxA_DPHY_L1_CKSEL_MASK				BIT(9)
+#define MIPI_RX_ANA00_CSIxA_RG_CSIxA_DPHY_L2_CKMODE_EN_SHIFT			11
+#define MIPI_RX_ANA00_CSIxA_RG_CSIxA_DPHY_L2_CKMODE_EN_MASK			BIT(11)
+#define MIPI_RX_ANA00_CSIxA_RG_CSIxA_DPHY_L2_CKSEL_SHIFT			12
+#define MIPI_RX_ANA00_CSIxA_RG_CSIxA_DPHY_L2_CKSEL_MASK				BIT(12)
+
+#define MIPI_RX_ANA04_CSIxA							0x0004
+#define MIPI_RX_ANA04_CSIxA_RG_CSIxA_BG_LPRX_VTH_SEL_SHIFT			0
+#define MIPI_RX_ANA04_CSIxA_RG_CSIxA_BG_LPRX_VTH_SEL_MASK			GENMASK(2, 0)
+#define MIPI_RX_ANA04_CSIxA_RG_CSIxA_BG_LPRX_VTL_SEL_SHIFT			4
+#define MIPI_RX_ANA04_CSIxA_RG_CSIxA_BG_LPRX_VTL_SEL_MASK			GENMASK(6, 4)
+#define MIPI_RX_ANA04_CSIxA_RG_CSIxA_BG_HSDET_VTH_SEL_SHIFT			8
+#define MIPI_RX_ANA04_CSIxA_RG_CSIxA_BG_HSDET_VTH_SEL_MASK			GENMASK(10, 8)
+#define MIPI_RX_ANA04_CSIxA_RG_CSIxA_BG_HSDET_VTL_SEL_SHIFT			12
+#define MIPI_RX_ANA04_CSIxA_RG_CSIxA_BG_HSDET_VTL_SEL_MASK			GENMASK(14, 12)
+#define MIPI_RX_ANA04_CSIxA_RG_CSIxA_BG_VREF_SEL_SHIFT				16
+#define MIPI_RX_ANA04_CSIxA_RG_CSIxA_BG_VREF_SEL_MASK				GENMASK(19, 16)
+#define MIPI_RX_ANA04_CSIxA_RG_CSIxA_BG_MON_VREF_SEL_SHIFT			24
+#define MIPI_RX_ANA04_CSIxA_RG_CSIxA_BG_MON_VREF_SEL_MASK			GENMASK(27, 24)
+#define MIPI_RX_ANA04_CSIxA_RG_CSIxA_FORCE_HSRT_EN_SHIFT			28
+#define MIPI_RX_ANA04_CSIxA_RG_CSIxA_FORCE_HSRT_EN_MASK				BIT(28)
+
+#define MIPI_RX_ANA08_CSIxA							0x0008
+#define MIPI_RX_ANA08_CSIxA_RG_CSIxA_L0P_T0A_HSRT_CODE_SHIFT			0
+#define MIPI_RX_ANA08_CSIxA_RG_CSIxA_L0P_T0A_HSRT_CODE_MASK			GENMASK(4, 0)
+#define MIPI_RX_ANA08_CSIxA_RG_CSIxA_L0N_T0B_HSRT_CODE_SHIFT			8
+#define MIPI_RX_ANA08_CSIxA_RG_CSIxA_L0N_T0B_HSRT_CODE_MASK			GENMASK(12, 8)
+#define MIPI_RX_ANA08_CSIxA_RG_CSIxA_L1P_T0C_HSRT_CODE_SHIFT			16
+#define MIPI_RX_ANA08_CSIxA_RG_CSIxA_L1P_T0C_HSRT_CODE_MASK			GENMASK(20, 16)
+#define MIPI_RX_ANA08_CSIxA_RG_CSIxA_L1N_T1A_HSRT_CODE_SHIFT			24
+#define MIPI_RX_ANA08_CSIxA_RG_CSIxA_L1N_T1A_HSRT_CODE_MASK			GENMASK(28, 24)
+
+#define MIPI_RX_ANA0C_CSIxA							0x000c
+#define MIPI_RX_ANA0C_CSIxA_RG_CSIxA_L2P_T1B_HSRT_CODE_SHIFT			0
+#define MIPI_RX_ANA0C_CSIxA_RG_CSIxA_L2P_T1B_HSRT_CODE_MASK			GENMASK(4, 0)
+#define MIPI_RX_ANA0C_CSIxA_RG_CSIxA_L2N_T1C_HSRT_CODE_SHIFT			8
+#define MIPI_RX_ANA0C_CSIxA_RG_CSIxA_L2N_T1C_HSRT_CODE_MASK			GENMASK(12, 8)
+
+#define MIPI_RX_ANA10_CSIxA							0x0010
+#define MIPI_RX_ANA10_CSIxA_RG_CSIxA_DPHY_L0_DELAYCAL_EN_SHIFT			0
+#define MIPI_RX_ANA10_CSIxA_RG_CSIxA_DPHY_L0_DELAYCAL_EN_MASK			BIT(0)
+#define MIPI_RX_ANA10_CSIxA_RG_CSIxA_DPHY_L0_DELAYCAL_RSTB_SHIFT		1
+#define MIPI_RX_ANA10_CSIxA_RG_CSIxA_DPHY_L0_DELAYCAL_RSTB_MASK			BIT(1)
+#define MIPI_RX_ANA10_CSIxA_RG_CSIxA_DPHY_L0_VREF_SEL_SHIFT			2
+#define MIPI_RX_ANA10_CSIxA_RG_CSIxA_DPHY_L0_VREF_SEL_MASK			GENMASK(7, 2)
+#define MIPI_RX_ANA10_CSIxA_RG_CSIxA_DPHY_L1_DELAYCAL_EN_SHIFT			8
+#define MIPI_RX_ANA10_CSIxA_RG_CSIxA_DPHY_L1_DELAYCAL_EN_MASK			BIT(8)
+#define MIPI_RX_ANA10_CSIxA_RG_CSIxA_DPHY_L1_DELAYCAL_RSTB_SHIFT		9
+#define MIPI_RX_ANA10_CSIxA_RG_CSIxA_DPHY_L1_DELAYCAL_RSTB_MASK			BIT(9)
+#define MIPI_RX_ANA10_CSIxA_RG_CSIxA_DPHY_L1_VREF_SEL_SHIFT			10
+#define MIPI_RX_ANA10_CSIxA_RG_CSIxA_DPHY_L1_VREF_SEL_MASK			GENMASK(15, 10)
+#define MIPI_RX_ANA10_CSIxA_RG_CSIxA_DPHY_L2_DELAYCAL_EN_SHIFT			16
+#define MIPI_RX_ANA10_CSIxA_RG_CSIxA_DPHY_L2_DELAYCAL_EN_MASK			BIT(16)
+#define MIPI_RX_ANA10_CSIxA_RG_CSIxA_DPHY_L2_DELAYCAL_RSTB_SHIFT		17
+#define MIPI_RX_ANA10_CSIxA_RG_CSIxA_DPHY_L2_DELAYCAL_RSTB_MASK			BIT(17)
+#define MIPI_RX_ANA10_CSIxA_RG_CSIxA_DPHY_L2_VREF_SEL_SHIFT			18
+#define MIPI_RX_ANA10_CSIxA_RG_CSIxA_DPHY_L2_VREF_SEL_MASK			GENMASK(23, 18)
+/* C-PHY fields are only available in CSIx. */
+#define MIPI_RX_ANA10_CSIxA_RG_CSI0A_CPHY_T0_CDR_DELAYCAL_EN_SHIFT		24
+#define MIPI_RX_ANA10_CSIxA_RG_CSI0A_CPHY_T0_CDR_DELAYCAL_EN_MASK		BIT(24)
+#define MIPI_RX_ANA10_CSIxA_RG_CSI0A_CPHY_T0_CDR_DELAYCAL_RSTB_SHIFT		25
+#define MIPI_RX_ANA10_CSIxA_RG_CSI0A_CPHY_T0_CDR_DELAYCAL_RSTB_MASK		BIT(25)
+#define MIPI_RX_ANA10_CSIxA_RG_CSI0A_CPHY_T0_VREF_SEL_SHIFT			26
+#define MIPI_RX_ANA10_CSIxA_RG_CSI0A_CPHY_T0_VREF_SEL_MASK			GENMASK(31, 26)
+
+#define MIPI_RX_ANA14_CSIxA							0x0014
+/* C-PHY fields are only available in CSIx. */
+#define MIPI_RX_ANA14_CSIxA_RG_CSI0A_CPHY_T1_CDR_DELAYCAL_EN_SHIFT		0
+#define MIPI_RX_ANA14_CSIxA_RG_CSI0A_CPHY_T1_CDR_DELAYCAL_EN_MASK		BIT(0)
+#define MIPI_RX_ANA14_CSIxA_RG_CSI0A_CPHY_T1_CDR_DELAYCAL_RSTB_SHIFT		1
+#define MIPI_RX_ANA14_CSIxA_RG_CSI0A_CPHY_T1_CDR_DELAYCAL_RSTB_MASK		BIT(1)
+#define MIPI_RX_ANA14_CSIxA_RG_CSI0A_CPHY_T1_VREF_SEL_SHIFT			2
+#define MIPI_RX_ANA14_CSIxA_RG_CSI0A_CPHY_T1_VREF_SEL_MASK			GENMASK(7, 2)
+
+#define MIPI_RX_ANA18_CSIxA							0x0018
+/* CSIx-specific fields. */
+#define MIPI_RX_ANA18_CSIxA_RG_CSI0A_L0_T0AB_EQ_OS_CAL_EN_SHIFT			0
+#define MIPI_RX_ANA18_CSIxA_RG_CSI0A_L0_T0AB_EQ_OS_CAL_EN_MASK			BIT(0)
+#define MIPI_RX_ANA18_CSIxA_RG_CSI0A_L0_T0AB_EQ_MON_EN_SHIFT			1
+#define MIPI_RX_ANA18_CSIxA_RG_CSI0A_L0_T0AB_EQ_MON_EN_MASK			BIT(1)
+#define MIPI_RX_ANA18_CSIxA_RG_CSI0A_L0_T0AB_EQ_SCA_SHIFT			2
+#define MIPI_RX_ANA18_CSIxA_RG_CSI0A_L0_T0AB_EQ_SCA_MASK			BIT(2)
+#define MIPI_RX_ANA18_CSIxA_RG_CSI0A_L0_T0AB_EQ_SCB_SHIFT			3
+#define MIPI_RX_ANA18_CSIxA_RG_CSI0A_L0_T0AB_EQ_SCB_MASK			BIT(3)
+#define MIPI_RX_ANA18_CSIxA_RG_CSI0A_L0_T0AB_EQ_IS_SHIFT			4
+#define MIPI_RX_ANA18_CSIxA_RG_CSI0A_L0_T0AB_EQ_IS_MASK				GENMASK(5, 4)
+#define MIPI_RX_ANA18_CSIxA_RG_CSI0A_L0_T0AB_EQ_BW_SHIFT			6
+#define MIPI_RX_ANA18_CSIxA_RG_CSI0A_L0_T0AB_EQ_BW_MASK				GENMASK(7, 6)
+#define MIPI_RX_ANA18_CSIxA_RG_CSI0A_L0_T0AB_EQ_SRA_SHIFT			8
+#define MIPI_RX_ANA18_CSIxA_RG_CSI0A_L0_T0AB_EQ_SRA_MASK			GENMASK(11, 8)
+#define MIPI_RX_ANA18_CSIxA_RG_CSI0A_L0_T0AB_EQ_SRB_SHIFT			12
+#define MIPI_RX_ANA18_CSIxA_RG_CSI0A_L0_T0AB_EQ_SRB_MASK			GENMASK(15, 12)
+#define MIPI_RX_ANA18_CSIxA_RG_CSI0A_XX_T0CA_EQ_OS_CAL_EN_SHIFT			16
+#define MIPI_RX_ANA18_CSIxA_RG_CSI0A_XX_T0CA_EQ_OS_CAL_EN_MASK			BIT(16)
+#define MIPI_RX_ANA18_CSIxA_RG_CSI0A_XX_T0CA_EQ_MON_EN_SHIFT			17
+#define MIPI_RX_ANA18_CSIxA_RG_CSI0A_XX_T0CA_EQ_MON_EN_MASK			BIT(17)
+#define MIPI_RX_ANA18_CSIxA_RG_CSI0A_XX_T0CA_EQ_SCA_SHIFT			18
+#define MIPI_RX_ANA18_CSIxA_RG_CSI0A_XX_T0CA_EQ_SCA_MASK			BIT(18)
+#define MIPI_RX_ANA18_CSIxA_RG_CSI0A_XX_T0CA_EQ_SCB_SHIFT			19
+#define MIPI_RX_ANA18_CSIxA_RG_CSI0A_XX_T0CA_EQ_SCB_MASK			BIT(19)
+#define MIPI_RX_ANA18_CSIxA_RG_CSI0A_XX_T0CA_EQ_IS_SHIFT			20
+#define MIPI_RX_ANA18_CSIxA_RG_CSI0A_XX_T0CA_EQ_IS_MASK				GENMASK(21, 20)
+#define MIPI_RX_ANA18_CSIxA_RG_CSI0A_XX_T0CA_EQ_BW_SHIFT			22
+#define MIPI_RX_ANA18_CSIxA_RG_CSI0A_XX_T0CA_EQ_BW_MASK				GENMASK(23, 22)
+#define MIPI_RX_ANA18_CSIxA_RG_CSI0A_XX_T0CA_EQ_SRA_SHIFT			24
+#define MIPI_RX_ANA18_CSIxA_RG_CSI0A_XX_T0CA_EQ_SRA_MASK			GENMASK(27, 24)
+#define MIPI_RX_ANA18_CSIxA_RG_CSI0A_XX_T0CA_EQ_SRB_SHIFT			28
+#define MIPI_RX_ANA18_CSIxA_RG_CSI0A_XX_T0CA_EQ_SRB_MASK			GENMASK(31, 28)
+/* CSI1- and CSI2-specific fields. */
+#define MIPI_RX_ANA18_CSIxA_RG_CSI1A_L0_EQ_OS_CAL_EN_SHIFT			0
+#define MIPI_RX_ANA18_CSIxA_RG_CSI1A_L0_EQ_OS_CAL_EN_MASK			BIT(0)
+#define MIPI_RX_ANA18_CSIxA_RG_CSI1A_L0_EQ_MON_EN_SHIFT				1
+#define MIPI_RX_ANA18_CSIxA_RG_CSI1A_L0_EQ_MON_EN_MASK				BIT(1)
+#define MIPI_RX_ANA18_CSIxA_RG_CSI1A_L0_EQ_SCA_SHIFT				2
+#define MIPI_RX_ANA18_CSIxA_RG_CSI1A_L0_EQ_SCA_MASK				BIT(2)
+#define MIPI_RX_ANA18_CSIxA_RG_CSI1A_L0_EQ_SCB_SHIFT				3
+#define MIPI_RX_ANA18_CSIxA_RG_CSI1A_L0_EQ_SCB_MASK				BIT(3)
+#define MIPI_RX_ANA18_CSIxA_RG_CSI1A_L0_EQ_IS_SHIFT				4
+#define MIPI_RX_ANA18_CSIxA_RG_CSI1A_L0_EQ_IS_MASK				GENMASK(5, 4)
+#define MIPI_RX_ANA18_CSIxA_RG_CSI1A_L0_EQ_BW_SHIFT				6
+#define MIPI_RX_ANA18_CSIxA_RG_CSI1A_L0_EQ_BW_MASK				GENMASK(7, 6)
+#define MIPI_RX_ANA18_CSIxA_RG_CSI1A_L0_EQ_SRA_SHIFT				8
+#define MIPI_RX_ANA18_CSIxA_RG_CSI1A_L0_EQ_SRA_MASK				GENMASK(11, 8)
+#define MIPI_RX_ANA18_CSIxA_RG_CSI1A_L0_EQ_SRB_SHIFT				12
+#define MIPI_RX_ANA18_CSIxA_RG_CSI1A_L0_EQ_SRB_MASK				GENMASK(15, 12)
+#define MIPI_RX_ANA18_CSIxA_RG_CSI1A_L1_EQ_OS_CAL_EN_SHIFT			16
+#define MIPI_RX_ANA18_CSIxA_RG_CSI1A_L1_EQ_OS_CAL_EN_MASK			BIT(16)
+#define MIPI_RX_ANA18_CSIxA_RG_CSI1A_L1_EQ_MON_EN_SHIFT				17
+#define MIPI_RX_ANA18_CSIxA_RG_CSI1A_L1_EQ_MON_EN_MASK				BIT(17)
+#define MIPI_RX_ANA18_CSIxA_RG_CSI1A_L1_EQ_SCA_SHIFT				18
+#define MIPI_RX_ANA18_CSIxA_RG_CSI1A_L1_EQ_SCA_MASK				BIT(18)
+#define MIPI_RX_ANA18_CSIxA_RG_CSI1A_L1_EQ_SCB_SHIFT				19
+#define MIPI_RX_ANA18_CSIxA_RG_CSI1A_L1_EQ_SCB_MASK				BIT(19)
+#define MIPI_RX_ANA18_CSIxA_RG_CSI1A_L1_EQ_IS_SHIFT				20
+#define MIPI_RX_ANA18_CSIxA_RG_CSI1A_L1_EQ_IS_MASK				GENMASK(21, 20)
+#define MIPI_RX_ANA18_CSIxA_RG_CSI1A_L1_EQ_BW_SHIFT				22
+#define MIPI_RX_ANA18_CSIxA_RG_CSI1A_L1_EQ_BW_MASK				GENMASK(23, 22)
+#define MIPI_RX_ANA18_CSIxA_RG_CSI1A_L1_EQ_SRA_SHIFT				24
+#define MIPI_RX_ANA18_CSIxA_RG_CSI1A_L1_EQ_SRA_MASK				GENMASK(27, 24)
+#define MIPI_RX_ANA18_CSIxA_RG_CSI1A_L1_EQ_SRB_SHIFT				28
+#define MIPI_RX_ANA18_CSIxA_RG_CSI1A_L1_EQ_SRB_MASK				GENMASK(31, 28)
+
+#define MIPI_RX_ANA1C_CSIxA							0x001c
+/* CSIx-specific fields. */
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI0A_XX_T0BC_EQ_OS_CAL_EN_SHIFT			0
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI0A_XX_T0BC_EQ_OS_CAL_EN_MASK			BIT(0)
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI0A_XX_T0BC_EQ_MON_EN_SHIFT			1
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI0A_XX_T0BC_EQ_MON_EN_MASK			BIT(1)
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI0A_XX_T0BC_EQ_SCA_SHIFT			2
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI0A_XX_T0BC_EQ_SCA_MASK			BIT(2)
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI0A_XX_T0BC_EQ_SCB_SHIFT			3
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI0A_XX_T0BC_EQ_SCB_MASK			BIT(3)
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI0A_XX_T0BC_EQ_IS_SHIFT			4
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI0A_XX_T0BC_EQ_IS_MASK				GENMASK(5, 4)
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI0A_XX_T0BC_EQ_BW_SHIFT			6
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI0A_XX_T0BC_EQ_BW_MASK				GENMASK(7, 6)
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI0A_XX_T0BC_EQ_SRA_SHIFT			8
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI0A_XX_T0BC_EQ_SRA_MASK			GENMASK(11, 8)
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI0A_XX_T0BC_EQ_SRB_SHIFT			12
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI0A_XX_T0BC_EQ_SRB_MASK			GENMASK(15, 12)
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI0A_L1_T1AB_EQ_OS_CAL_EN_SHIFT			16
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI0A_L1_T1AB_EQ_OS_CAL_EN_MASK			BIT(16)
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI0A_L1_T1AB_EQ_MON_EN_SHIFT			17
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI0A_L1_T1AB_EQ_MON_EN_MASK			BIT(17)
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI0A_L1_T1AB_EQ_SCA_SHIFT			18
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI0A_L1_T1AB_EQ_SCA_MASK			BIT(18)
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI0A_L1_T1AB_EQ_SCB_SHIFT			19
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI0A_L1_T1AB_EQ_SCB_MASK			BIT(19)
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI0A_L1_T1AB_EQ_IS_SHIFT			20
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI0A_L1_T1AB_EQ_IS_MASK				GENMASK(21, 20)
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI0A_L1_T1AB_EQ_BW_SHIFT			22
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI0A_L1_T1AB_EQ_BW_MASK				GENMASK(23, 22)
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI0A_L1_T1AB_EQ_SRA_SHIFT			24
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI0A_L1_T1AB_EQ_SRA_MASK			GENMASK(27, 24)
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI0A_L1_T1AB_EQ_SRB_SHIFT			28
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI0A_L1_T1AB_EQ_SRB_MASK			GENMASK(31, 28)
+/* CSI1- and CSI2-specific fields. */
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI1A_L2_EQ_OS_CAL_EN_SHIFT			0
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI1A_L2_EQ_OS_CAL_EN_MASK			BIT(0)
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI1A_L2_EQ_MON_EN_SHIFT				1
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI1A_L2_EQ_MON_EN_MASK				BIT(1)
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI1A_L2_EQ_SCA_SHIFT				2
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI1A_L2_EQ_SCA_MASK				BIT(2)
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI1A_L2_EQ_SCB_SHIFT				3
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI1A_L2_EQ_SCB_MASK				BIT(3)
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI1A_L2_EQ_IS_SHIFT				4
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI1A_L2_EQ_IS_MASK				GENMASK(5, 4)
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI1A_L2_EQ_BW_SHIFT				6
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI1A_L2_EQ_BW_MASK				GENMASK(7, 6)
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI1A_L2_EQ_SRA_SHIFT				8
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI1A_L2_EQ_SRA_MASK				GENMASK(11, 8)
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI1A_L2_EQ_SRB_SHIFT				12
+#define MIPI_RX_ANA1C_CSIxA_RG_CSI1A_L2_EQ_SRB_MASK				GENMASK(15, 12)
+
+/* CSI0-specific register. */
+#define MIPI_RX_ANA20_CSI0A							0x0020
+#define MIPI_RX_ANA20_CSI0A_RG_CSI0A_XX_T1CA_EQ_OS_CAL_EN_SHIFT			0
+#define MIPI_RX_ANA20_CSI0A_RG_CSI0A_XX_T1CA_EQ_OS_CAL_EN_MASK			BIT(0)
+#define MIPI_RX_ANA20_CSI0A_RG_CSI0A_XX_T1CA_EQ_MON_EN_SHIFT			1
+#define MIPI_RX_ANA20_CSI0A_RG_CSI0A_XX_T1CA_EQ_MON_EN_MASK			BIT(1)
+#define MIPI_RX_ANA20_CSI0A_RG_CSI0A_XX_T1CA_EQ_SCA_SHIFT			2
+#define MIPI_RX_ANA20_CSI0A_RG_CSI0A_XX_T1CA_EQ_SCA_MASK			BIT(2)
+#define MIPI_RX_ANA20_CSI0A_RG_CSI0A_XX_T1CA_EQ_SCB_SHIFT			3
+#define MIPI_RX_ANA20_CSI0A_RG_CSI0A_XX_T1CA_EQ_SCB_MASK			BIT(3)
+#define MIPI_RX_ANA20_CSI0A_RG_CSI0A_XX_T1CA_EQ_IS_SHIFT			4
+#define MIPI_RX_ANA20_CSI0A_RG_CSI0A_XX_T1CA_EQ_IS_MASK				GENMASK(5, 4)
+#define MIPI_RX_ANA20_CSI0A_RG_CSI0A_XX_T1CA_EQ_BW_SHIFT			6
+#define MIPI_RX_ANA20_CSI0A_RG_CSI0A_XX_T1CA_EQ_BW_MASK				GENMASK(7, 6)
+#define MIPI_RX_ANA20_CSI0A_RG_CSI0A_XX_T1CA_EQ_SRA_SHIFT			8
+#define MIPI_RX_ANA20_CSI0A_RG_CSI0A_XX_T1CA_EQ_SRA_MASK			GENMASK(11, 8)
+#define MIPI_RX_ANA20_CSI0A_RG_CSI0A_XX_T1CA_EQ_SRB_SHIFT			12
+#define MIPI_RX_ANA20_CSI0A_RG_CSI0A_XX_T1CA_EQ_SRB_MASK			GENMASK(15, 12)
+#define MIPI_RX_ANA20_CSI0A_RG_CSI0A_L2_T1BC_EQ_OS_CAL_EN_SHIFT			16
+#define MIPI_RX_ANA20_CSI0A_RG_CSI0A_L2_T1BC_EQ_OS_CAL_EN_MASK			BIT(16)
+#define MIPI_RX_ANA20_CSI0A_RG_CSI0A_L2_T1BC_EQ_MON_EN_SHIFT			17
+#define MIPI_RX_ANA20_CSI0A_RG_CSI0A_L2_T1BC_EQ_MON_EN_MASK			BIT(17)
+#define MIPI_RX_ANA20_CSI0A_RG_CSI0A_L2_T1BC_EQ_SCA_SHIFT			18
+#define MIPI_RX_ANA20_CSI0A_RG_CSI0A_L2_T1BC_EQ_SCA_MASK			BIT(18)
+#define MIPI_RX_ANA20_CSI0A_RG_CSI0A_L2_T1BC_EQ_SCB_SHIFT			19
+#define MIPI_RX_ANA20_CSI0A_RG_CSI0A_L2_T1BC_EQ_SCB_MASK			BIT(19)
+#define MIPI_RX_ANA20_CSI0A_RG_CSI0A_L2_T1BC_EQ_IS_SHIFT			20
+#define MIPI_RX_ANA20_CSI0A_RG_CSI0A_L2_T1BC_EQ_IS_MASK				GENMASK(21, 20)
+#define MIPI_RX_ANA20_CSI0A_RG_CSI0A_L2_T1BC_EQ_BW_SHIFT			22
+#define MIPI_RX_ANA20_CSI0A_RG_CSI0A_L2_T1BC_EQ_BW_MASK				GENMASK(23, 22)
+#define MIPI_RX_ANA20_CSI0A_RG_CSI0A_L2_T1BC_EQ_SRA_SHIFT			24
+#define MIPI_RX_ANA20_CSI0A_RG_CSI0A_L2_T1BC_EQ_SRA_MASK			GENMASK(27, 24)
+#define MIPI_RX_ANA20_CSI0A_RG_CSI0A_L2_T1BC_EQ_SRB_SHIFT			28
+#define MIPI_RX_ANA20_CSI0A_RG_CSI0A_L2_T1BC_EQ_SRB_MASK			GENMASK(31, 28)
+
+#define MIPI_RX_ANA24_CSIxA							0x0024
+#define MIPI_RX_ANA24_CSIxA_RG_CSIxA_RESERVE_SHIFT				24
+#define MIPI_RX_ANA24_CSIxA_RG_CSIxA_RESERVE_MASK				(0xff << 24)
+
+/* CSI0-specific register. */
+#define MIPI_RX_ANA28_CSI0A							0x0028
+#define MIPI_RX_ANA28_CSI0A_RG_CSI0A_CPHY_T0_CDR_DIRECT_EN_SHIFT		0
+#define MIPI_RX_ANA28_CSI0A_RG_CSI0A_CPHY_T0_CDR_DIRECT_EN_MASK			BIT(0)
+#define MIPI_RX_ANA28_CSI0A_RG_CSI0A_CPHY_T0_CDR_AUTOLOAD_EN_SHIFT		1
+#define MIPI_RX_ANA28_CSI0A_RG_CSI0A_CPHY_T0_CDR_AUTOLOAD_EN_MASK		BIT(1)
+#define MIPI_RX_ANA28_CSI0A_RG_CSI0A_CPHY_T0_CDR_LPF_CTRL_SHIFT			2
+#define MIPI_RX_ANA28_CSI0A_RG_CSI0A_CPHY_T0_CDR_LPF_CTRL_MASK			GENMASK(3, 2)
+#define MIPI_RX_ANA28_CSI0A_RG_CSI0A_CPHY_T0_CDR_AB_WIDTH_SHIFT			4
+#define MIPI_RX_ANA28_CSI0A_RG_CSI0A_CPHY_T0_CDR_AB_WIDTH_MASK			GENMASK(7, 4)
+#define MIPI_RX_ANA28_CSI0A_RG_CSI0A_CPHY_T0_CDR_BC_WIDTH_SHIFT			8
+#define MIPI_RX_ANA28_CSI0A_RG_CSI0A_CPHY_T0_CDR_BC_WIDTH_MASK			GENMASK(11, 8)
+#define MIPI_RX_ANA28_CSI0A_RG_CSI0A_CPHY_T0_CDR_CA_WIDTH_SHIFT			12
+#define MIPI_RX_ANA28_CSI0A_RG_CSI0A_CPHY_T0_CDR_CA_WIDTH_MASK			GENMASK(15, 12)
+#define MIPI_RX_ANA28_CSI0A_RG_CSI0A_CPHY_T0_CDR_CK_DELAY_SHIFT			16
+#define MIPI_RX_ANA28_CSI0A_RG_CSI0A_CPHY_T0_CDR_CK_DELAY_MASK			GENMASK(19, 16)
+#define MIPI_RX_ANA28_CSI0A_RG_CSI0A_CPHY_T0_HSDET_SEL_SHIFT			20
+#define MIPI_RX_ANA28_CSI0A_RG_CSI0A_CPHY_T0_HSDET_SEL_MASK			GENMASK(21, 20)
+#define MIPI_RX_ANA28_CSI0A_RG_CSI0A_CPHY_T0_CDR_MANUAL_EN_SHIFT		24
+#define MIPI_RX_ANA28_CSI0A_RG_CSI0A_CPHY_T0_CDR_MANUAL_EN_MASK			BIT(24)
+
+/* CSI0-specific register. */
+#define MIPI_RX_ANA2C_CSI0A							0x002c
+#define MIPI_RX_ANA2C_CSI0A_RG_CSI0A_CPHY_T0_CDR_INIT_CODE_SHIFT		0
+#define MIPI_RX_ANA2C_CSI0A_RG_CSI0A_CPHY_T0_CDR_INIT_CODE_MASK			GENMASK(4, 0)
+#define MIPI_RX_ANA2C_CSI0A_RG_CSI0A_CPHY_T0_CDR_EARLY_CODE_SHIFT		8
+#define MIPI_RX_ANA2C_CSI0A_RG_CSI0A_CPHY_T0_CDR_EARLY_CODE_MASK		GENMASK(12, 8)
+#define MIPI_RX_ANA2C_CSI0A_RG_CSI0A_CPHY_T0_CDR_LATE_CODE_SHIFT		16
+#define MIPI_RX_ANA2C_CSI0A_RG_CSI0A_CPHY_T0_CDR_LATE_CODE_MASK			GENMASK(20, 16)
+
+/* CSI0-specific register. */
+#define MIPI_RX_ANA34_CSI0A							0x0034
+#define MIPI_RX_ANA34_CSI0A_RG_CSI0A_CPHY_T1_CDR_DIRECT_EN_SHIFT		0
+#define MIPI_RX_ANA34_CSI0A_RG_CSI0A_CPHY_T1_CDR_DIRECT_EN_MASK			BIT(0)
+#define MIPI_RX_ANA34_CSI0A_RG_CSI0A_CPHY_T1_CDR_AUTOLOAD_EN_SHIFT		1
+#define MIPI_RX_ANA34_CSI0A_RG_CSI0A_CPHY_T1_CDR_AUTOLOAD_EN_MASK		BIT(1)
+#define MIPI_RX_ANA34_CSI0A_RG_CSI0A_CPHY_T1_CDR_LPF_CTRL_SHIFT			2
+#define MIPI_RX_ANA34_CSI0A_RG_CSI0A_CPHY_T1_CDR_LPF_CTRL_MASK			GENMASK(3, 2)
+#define MIPI_RX_ANA34_CSI0A_RG_CSI0A_CPHY_T1_CDR_AB_WIDTH_SHIFT			4
+#define MIPI_RX_ANA34_CSI0A_RG_CSI0A_CPHY_T1_CDR_AB_WIDTH_MASK			GENMASK(7, 4)
+#define MIPI_RX_ANA34_CSI0A_RG_CSI0A_CPHY_T1_CDR_BC_WIDTH_SHIFT			8
+#define MIPI_RX_ANA34_CSI0A_RG_CSI0A_CPHY_T1_CDR_BC_WIDTH_MASK			GENMASK(11, 8)
+#define MIPI_RX_ANA34_CSI0A_RG_CSI0A_CPHY_T1_CDR_CA_WIDTH_SHIFT			12
+#define MIPI_RX_ANA34_CSI0A_RG_CSI0A_CPHY_T1_CDR_CA_WIDTH_MASK			GENMASK(15, 12)
+#define MIPI_RX_ANA34_CSI0A_RG_CSI0A_CPHY_T1_CDR_CK_DELAY_SHIFT			16
+#define MIPI_RX_ANA34_CSI0A_RG_CSI0A_CPHY_T1_CDR_CK_DELAY_MASK			GENMASK(19, 16)
+#define MIPI_RX_ANA34_CSI0A_RG_CSI0A_CPHY_T1_HSDET_SEL_SHIFT			20
+#define MIPI_RX_ANA34_CSI0A_RG_CSI0A_CPHY_T1_HSDET_SEL_MASK			GENMASK(21, 20)
+#define MIPI_RX_ANA34_CSI0A_RG_CSI0A_CPHY_T1_CDR_MANUAL_EN_SHIFT		24
+#define MIPI_RX_ANA34_CSI0A_RG_CSI0A_CPHY_T1_CDR_MANUAL_EN_MASK			BIT(24)
+
+/* CSI0-specific register. */
+#define MIPI_RX_ANA38_CSI0A							0x0038
+#define MIPI_RX_ANA38_CSI0A_RG_CSI0A_CPHY_T1_CDR_INIT_CODE_SHIFT		0
+#define MIPI_RX_ANA38_CSI0A_RG_CSI0A_CPHY_T1_CDR_INIT_CODE_MASK			GENMASK(4, 0)
+#define MIPI_RX_ANA38_CSI0A_RG_CSI0A_CPHY_T1_CDR_EARLY_CODE_SHIFT		8
+#define MIPI_RX_ANA38_CSI0A_RG_CSI0A_CPHY_T1_CDR_EARLY_CODE_MASK		GENMASK(12, 8)
+#define MIPI_RX_ANA38_CSI0A_RG_CSI0A_CPHY_T1_CDR_LATE_CODE_SHIFT		16
+#define MIPI_RX_ANA38_CSI0A_RG_CSI0A_CPHY_T1_CDR_LATE_CODE_MASK			GENMASK(20, 16)
+
+#define MIPI_RX_ANA40_CSIxA							0x0040
+#define MIPI_RX_ANA40_CSIxA_RG_CSIxA_CPHY_FMCK_SEL_SHIFT			0
+#define MIPI_RX_ANA40_CSIxA_RG_CSIxA_CPHY_FMCK_SEL_MASK				GENMASK(1, 0)
+#define MIPI_RX_ANA40_CSIxA_RG_CSIxA_ASYNC_OPTION_SHIFT				4
+#define MIPI_RX_ANA40_CSIxA_RG_CSIxA_ASYNC_OPTION_MASK				GENMASK(7, 4)
+#define MIPI_RX_ANA40_CSIxA_RG_CSIxA_CPHY_SPARE_SHIFT				16
+#define MIPI_RX_ANA40_CSIxA_RG_CSIxA_CPHY_SPARE_MASK				GENMASK(31, 16)
+
+#define MIPI_RX_ANA48_CSIxA							0x0048
+/* CSI0-specific fields. */
+#define MIPI_RX_ANA48_CSIxA_RGS_CSI0A_CDPHY_L0_T0AB_OS_CAL_CPLT_SHIFT		0
+#define MIPI_RX_ANA48_CSIxA_RGS_CSI0A_CDPHY_L0_T0AB_OS_CAL_CPLT_MASK		BIT(0)
+#define MIPI_RX_ANA48_CSIxA_RGS_CSI0A_CPHY_T0CA_OS_CAL_CPLT_SHIFT		1
+#define MIPI_RX_ANA48_CSIxA_RGS_CSI0A_CPHY_T0CA_OS_CAL_CPLT_MASK		BIT(1)
+#define MIPI_RX_ANA48_CSIxA_RGS_CSI0A_CPHY_T0BC_OS_CAL_CPLT_SHIFT		2
+#define MIPI_RX_ANA48_CSIxA_RGS_CSI0A_CPHY_T0BC_OS_CAL_CPLT_MASK		BIT(2)
+#define MIPI_RX_ANA48_CSIxA_RGS_CSI0A_CDPHY_L1_T1AB_OS_CAL_CPLT_SHIFT		3
+#define MIPI_RX_ANA48_CSIxA_RGS_CSI0A_CDPHY_L1_T1AB_OS_CAL_CPLT_MASK		BIT(3)
+#define MIPI_RX_ANA48_CSIxA_RGS_CSI0A_CPHY_T1CA_OS_CAL_CPLT_SHIFT		4
+#define MIPI_RX_ANA48_CSIxA_RGS_CSI0A_CPHY_T1CA_OS_CAL_CPLT_MASK		BIT(4)
+#define MIPI_RX_ANA48_CSIxA_RGS_CSI0A_CDPHY_L2_T1BC_OS_CAL_CPLT_SHIFT		5
+#define MIPI_RX_ANA48_CSIxA_RGS_CSI0A_CDPHY_L2_T1BC_OS_CAL_CPLT_MASK		BIT(5)
+/* CSI1- and CSI2-specific fields. */
+#define MIPI_RX_ANA48_CSIxA_RGS_CSI1A_DPHY_L0_OS_CAL_CPLT_SHIFT			3
+#define MIPI_RX_ANA48_CSIxA_RGS_CSI1A_DPHY_L0_OS_CAL_CPLT_MASK			BIT(3)
+#define MIPI_RX_ANA48_CSIxA_RGS_CSI1A_DPHY_L1_OS_CAL_CPLT_SHIFT			4
+#define MIPI_RX_ANA48_CSIxA_RGS_CSI1A_DPHY_L1_OS_CAL_CPLT_MASK			BIT(4)
+#define MIPI_RX_ANA48_CSIxA_RGS_CSI1A_DPHY_L2_OS_CAL_CPLT_SHIFT			5
+#define MIPI_RX_ANA48_CSIxA_RGS_CSI1A_DPHY_L2_OS_CAL_CPLT_MASK			BIT(5)
+/* Common fields. */
+#define MIPI_RX_ANA48_CSIxA_RGS_CSIxA_OS_CAL_CODE_SHIFT				8
+#define MIPI_RX_ANA48_CSIxA_RGS_CSIxA_OS_CAL_CODE_MASK				GENMASK(15, 8)
+
+#define MIPI_RX_WRAPPER80_CSIxA							0x0080
+#define MIPI_RX_WRAPPER80_CSIxA_CSR_CSI_CLK_MON_SHIFT				0
+#define MIPI_RX_WRAPPER80_CSIxA_CSR_CSI_CLK_MON_MASK				BIT(0)
+#define MIPI_RX_WRAPPER80_CSIxA_CSR_CSI_CLK_EN_SHIFT				1
+#define MIPI_RX_WRAPPER80_CSIxA_CSR_CSI_CLK_EN_MASK				BIT(1)
+#define MIPI_RX_WRAPPER80_CSIxA_CSR_CSI_MON_MUX_SHIFT				8
+#define MIPI_RX_WRAPPER80_CSIxA_CSR_CSI_MON_MUX_MASK				GENMASK(15, 8)
+#define MIPI_RX_WRAPPER80_CSIxA_CSR_CSI_RST_MODE_SHIFT				16
+#define MIPI_RX_WRAPPER80_CSIxA_CSR_CSI_RST_MODE_MASK				GENMASK(17, 16)
+#define MIPI_RX_WRAPPER80_CSIxA_CSR_SW_RST_SHIFT				24
+#define MIPI_RX_WRAPPER80_CSIxA_CSR_SW_RST_MASK					GENMASK(27, 24)
+
+#define MIPI_RX_WRAPPER84_CSIxA							0x0084
+#define MIPI_RX_WRAPPER84_CSIxA_CSI_DEBUG_OUT_SHIFT				0
+#define MIPI_RX_WRAPPER84_CSIxA_CSI_DEBUG_OUT_MASK				GENMASK(31, 0)
+
+#define MIPI_RX_WRAPPER88_CSIxA							0x0088
+#define MIPI_RX_WRAPPER88_CSIxA_CSR_SW_MODE_0_SHIFT				0
+#define MIPI_RX_WRAPPER88_CSIxA_CSR_SW_MODE_0_MASK				GENMASK(31, 0)
+
+#define MIPI_RX_WRAPPER8C_CSIxA							0x008c
+#define MIPI_RX_WRAPPER8C_CSIxA_CSR_SW_MODE_1_SHIFT				0
+#define MIPI_RX_WRAPPER8C_CSIxA_CSR_SW_MODE_1_MASK				GENMASK(31, 0)
+
+#define MIPI_RX_WRAPPER90_CSIxA							0x0090
+#define MIPI_RX_WRAPPER90_CSIxA_CSR_SW_MODE_2_SHIFT				0
+#define MIPI_RX_WRAPPER90_CSIxA_CSR_SW_MODE_2_MASK				GENMASK(31, 0)
+
+#define MIPI_RX_WRAPPER94_CSIxA							0x0094
+#define MIPI_RX_WRAPPER94_CSIxA_CSR_SW_VALUE_0_SHIFT				0
+#define MIPI_RX_WRAPPER94_CSIxA_CSR_SW_VALUE_0_MASK				GENMASK(31, 0)
+
+#define MIPI_RX_WRAPPER98_CSIxA							0x0098
+#define MIPI_RX_WRAPPER98_CSIxA_CSR_SW_VALUE_1_SHIFT				0
+#define MIPI_RX_WRAPPER98_CSIxA_CSR_SW_VALUE_1_MASK				GENMASK(31, 0)
+
+#define MIPI_RX_WRAPPER9C_CSIxA							0x009c
+#define MIPI_RX_WRAPPER9C_CSIxA_CSR_SW_VALUE_2_SHIFT				0
+#define MIPI_RX_WRAPPER9C_CSIxA_CSR_SW_VALUE_2_MASK				GENMASK(31, 0)
+
+#define MIPI_RX_ANAA4_CSIxA							0x00a4
+#define MIPI_RX_ANAA4_CSIxA_RG_CSIxA_CDPHY_L0_T0_SYNC_INIT_SEL_SHIFT		0
+#define MIPI_RX_ANAA4_CSIxA_RG_CSIxA_CDPHY_L0_T0_SYNC_INIT_SEL_MASK		BIT(0)
+#define MIPI_RX_ANAA4_CSIxA_RG_CSIxA_CDPHY_L0_T0_FORCE_INIT_SHIFT		1
+#define MIPI_RX_ANAA4_CSIxA_RG_CSIxA_CDPHY_L0_T0_FORCE_INIT_MASK		BIT(1)
+#define MIPI_RX_ANAA4_CSIxA_RG_CSIxA_DPHY_L1_SYNC_INIT_SEL_SHIFT		2
+#define MIPI_RX_ANAA4_CSIxA_RG_CSIxA_DPHY_L1_SYNC_INIT_SEL_MASK			BIT(2)
+#define MIPI_RX_ANAA4_CSIxA_RG_CSIxA_DPHY_L1_FORCE_INIT_SHIFT			3
+#define MIPI_RX_ANAA4_CSIxA_RG_CSIxA_DPHY_L1_FORCE_INIT_MASK			BIT(3)
+#define MIPI_RX_ANAA4_CSIxA_RG_CSIxA_CDPHY_L2_T2_SYNC_INIT_SEL_SHIFT		4
+#define MIPI_RX_ANAA4_CSIxA_RG_CSIxA_CDPHY_L2_T2_SYNC_INIT_SEL_MASK		BIT(4)
+#define MIPI_RX_ANAA4_CSIxA_RG_CSIxA_CDPHY_L2_T2_FORCE_INIT_SHIFT		5
+#define MIPI_RX_ANAA4_CSIxA_RG_CSIxA_CDPHY_L2_T2_FORCE_INIT_MASK		BIT(5)
+
+#define MIPI_RX_ANAA8_CSIxA							0x00a8
+#define MIPI_RX_ANAA8_CSIxA_RG_CSIxA_CDPHY_L0_T0_BYTECK_INVERT_SHIFT		0
+#define MIPI_RX_ANAA8_CSIxA_RG_CSIxA_CDPHY_L0_T0_BYTECK_INVERT_MASK		BIT(0)
+#define MIPI_RX_ANAA8_CSIxA_RG_CSIxA_DPHY_L1_BYTECK_INVERT_SHIFT		1
+#define MIPI_RX_ANAA8_CSIxA_RG_CSIxA_DPHY_L1_BYTECK_INVERT_MASK			BIT(1)
+#define MIPI_RX_ANAA8_CSIxA_RG_CSIxA_CDPHY_L2_T1_BYTECK_INVERT_SHIFT		2
+#define MIPI_RX_ANAA8_CSIxA_RG_CSIxA_CDPHY_L2_T1_BYTECK_INVERT_MASK		BIT(2)
+#define MIPI_RX_ANAA8_CSIxA_RG_CSIxA_DPHY_HSDET_LEVEL_MODE_EN_SHIFT		3
+#define MIPI_RX_ANAA8_CSIxA_RG_CSIxA_DPHY_HSDET_LEVEL_MODE_EN_MASK		BIT(3)
+#define MIPI_RX_ANAA8_CSIxA_RG_CSIxA_OS_CAL_SEL_SHIFT				4
+#define MIPI_RX_ANAA8_CSIxA_RG_CSIxA_OS_CAL_SEL_MASK				GENMASK(6, 4)
+#define MIPI_RX_ANAA8_CSIxA_RG_CSIxA_DPHY_HSDET_DIG_BACK_EN_SHIFT		7
+#define MIPI_RX_ANAA8_CSIxA_RG_CSIxA_DPHY_HSDET_DIG_BACK_EN_MASK		BIT(7)
+#define MIPI_RX_ANAA8_CSIxA_RG_CSIxA_CDPHY_DELAYCAL_CK_SEL_SHIFT		8
+#define MIPI_RX_ANAA8_CSIxA_RG_CSIxA_CDPHY_DELAYCAL_CK_SEL_MASK			GENMASK(10, 8)
+#define MIPI_RX_ANAA8_CSIxA_RG_CSIxA_OS_CAL_DIV_SHIFT				11
+#define MIPI_RX_ANAA8_CSIxA_RG_CSIxA_OS_CAL_DIV_MASK				GENMASK(12, 11)
+
+#endif
diff --git a/drivers/phy/mediatek/phy-mtk-mipi-csi.c b/drivers/phy/mediatek/phy-mtk-mipi-csi.c
new file mode 100644
index 000000000000..6ce3f95f57bd
--- /dev/null
+++ b/drivers/phy/mediatek/phy-mtk-mipi-csi.c
@@ -0,0 +1,392 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/regmap.h>
+
+#include "phy-mtk-mipi-csi-rx-reg.h"
+
+#define CSIxB_OFFSET		0x1000
+
+struct mtk_mipi_dphy;
+
+enum mtk_mipi_dphy_port_id {
+	MTK_MIPI_PHY_PORT_0 = 0x0, /* 4D1C - CDPHY */
+	MTK_MIPI_PHY_PORT_1, /* 4D1C - DPHY */
+	MTK_MIPI_PHY_PORT_2, /* 4D1C - DPHY */
+	MTK_MIPI_PHY_PORT_0A, /* 2D1C - CDPHY */
+	MTK_MIPI_PHY_PORT_0B, /* 2D1C - CDPHY */
+	MTK_MIPI_PHY_PORT_MAX_NUM
+};
+
+struct mtk_mipi_dphy_port {
+	struct mtk_mipi_dphy *dev;
+	enum mtk_mipi_dphy_port_id id;
+	struct regmap *regmap_base;
+	struct regmap *regmap_4d1c;
+	struct phy *phy;
+	bool active;
+	bool is_cdphy;
+	bool is_4d1c;
+};
+
+struct mtk_mipi_dphy {
+	struct device *dev;
+	void __iomem *rx;
+	struct mtk_mipi_dphy_port ports[MTK_MIPI_PHY_PORT_MAX_NUM];
+	struct mutex lock; /* Ports CSI0 and CSI0A/B are mutually exclusive */
+};
+
+#define REGMAP_BIT(map, reg, field, val) \
+	regmap_update_bits((map), reg, reg##_##field##_MASK, \
+			   (val) << reg##_##field##_SHIFT)
+
+static int mtk_mipi_phy_power_on(struct phy *phy)
+{
+	struct mtk_mipi_dphy_port *port = phy_get_drvdata(phy);
+	struct mtk_mipi_dphy *priv = port->dev;
+	struct regmap *regmap_base = port->regmap_base;
+	struct regmap *regmap_4d1c = port->regmap_4d1c;
+	int ret = 0;
+
+	mutex_lock(&priv->lock);
+
+	switch (port->id) {
+	case MTK_MIPI_PHY_PORT_0:
+		if (priv->ports[MTK_MIPI_PHY_PORT_0A].active ||
+		    priv->ports[MTK_MIPI_PHY_PORT_0B].active)
+			ret = -EBUSY;
+		break;
+
+	case MTK_MIPI_PHY_PORT_0A:
+	case MTK_MIPI_PHY_PORT_0B:
+		if (priv->ports[MTK_MIPI_PHY_PORT_0].active)
+			ret = -EBUSY;
+		break;
+	}
+
+	if (!ret)
+		port->active = true;
+
+	mutex_unlock(&priv->lock);
+
+	if (ret < 0)
+		return ret;
+
+	/* Set analog phy mode to DPHY */
+	if (port->is_cdphy)
+		REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
+			   RG_CSI0A_CPHY_EN, 0);
+
+	if (port->is_4d1c) {
+		REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
+			   RG_CSIxA_DPHY_L0_CKMODE_EN, 0);
+		REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
+			   RG_CSIxA_DPHY_L0_CKSEL, 1);
+		REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
+			   RG_CSIxA_DPHY_L1_CKMODE_EN, 0);
+		REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
+			   RG_CSIxA_DPHY_L1_CKSEL, 1);
+		REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
+			   RG_CSIxA_DPHY_L2_CKMODE_EN, 1);
+		REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
+			   RG_CSIxA_DPHY_L2_CKSEL, 1);
+	} else {
+		REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
+			   RG_CSIxA_DPHY_L0_CKMODE_EN, 0);
+		REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
+			   RG_CSIxA_DPHY_L0_CKSEL, 0);
+		REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
+			   RG_CSIxA_DPHY_L1_CKMODE_EN, 1);
+		REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
+			   RG_CSIxA_DPHY_L1_CKSEL, 0);
+		REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
+			   RG_CSIxA_DPHY_L2_CKMODE_EN, 0);
+		REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
+			   RG_CSIxA_DPHY_L2_CKSEL, 0);
+	}
+
+	if (port->is_4d1c) {
+		if (port->is_cdphy)
+			REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA00_CSIxA,
+				   RG_CSI0A_CPHY_EN, 0);
+
+		REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA00_CSIxA,
+			   RG_CSIxA_DPHY_L0_CKMODE_EN, 0);
+		REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA00_CSIxA,
+			   RG_CSIxA_DPHY_L0_CKSEL, 1);
+		REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA00_CSIxA,
+			   RG_CSIxA_DPHY_L1_CKMODE_EN, 0);
+		REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA00_CSIxA,
+			   RG_CSIxA_DPHY_L1_CKSEL, 1);
+		REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA00_CSIxA,
+			   RG_CSIxA_DPHY_L2_CKMODE_EN, 0);
+		REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA00_CSIxA,
+			   RG_CSIxA_DPHY_L2_CKSEL, 1);
+	}
+
+	/* Byte clock invert */
+	REGMAP_BIT(regmap_base, MIPI_RX_ANAA8_CSIxA,
+		   RG_CSIxA_CDPHY_L0_T0_BYTECK_INVERT, 1);
+	REGMAP_BIT(regmap_base, MIPI_RX_ANAA8_CSIxA,
+		   RG_CSIxA_DPHY_L1_BYTECK_INVERT, 1);
+	REGMAP_BIT(regmap_base, MIPI_RX_ANAA8_CSIxA,
+		   RG_CSIxA_CDPHY_L2_T1_BYTECK_INVERT, 1);
+
+	if (port->is_4d1c) {
+		REGMAP_BIT(regmap_4d1c, MIPI_RX_ANAA8_CSIxA,
+			   RG_CSIxA_CDPHY_L0_T0_BYTECK_INVERT, 1);
+		REGMAP_BIT(regmap_4d1c, MIPI_RX_ANAA8_CSIxA,
+			   RG_CSIxA_DPHY_L1_BYTECK_INVERT, 1);
+		REGMAP_BIT(regmap_4d1c, MIPI_RX_ANAA8_CSIxA,
+			   RG_CSIxA_CDPHY_L2_T1_BYTECK_INVERT, 1);
+	}
+
+	/* Start ANA EQ tuning */
+	if (port->is_cdphy) {
+		REGMAP_BIT(regmap_base, MIPI_RX_ANA18_CSIxA,
+			   RG_CSI0A_L0_T0AB_EQ_IS, 1);
+		REGMAP_BIT(regmap_base, MIPI_RX_ANA18_CSIxA,
+			   RG_CSI0A_L0_T0AB_EQ_BW, 1);
+		REGMAP_BIT(regmap_base, MIPI_RX_ANA1C_CSIxA,
+			   RG_CSI0A_L1_T1AB_EQ_IS, 1);
+		REGMAP_BIT(regmap_base, MIPI_RX_ANA1C_CSIxA,
+			   RG_CSI0A_L1_T1AB_EQ_BW, 1);
+		REGMAP_BIT(regmap_base, MIPI_RX_ANA20_CSI0A,
+			   RG_CSI0A_L2_T1BC_EQ_IS, 1);
+		REGMAP_BIT(regmap_base, MIPI_RX_ANA20_CSI0A,
+			   RG_CSI0A_L2_T1BC_EQ_BW, 1);
+
+		if (port->is_4d1c) {
+			REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA18_CSIxA,
+				   RG_CSI0A_L0_T0AB_EQ_IS, 1);
+			REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA18_CSIxA,
+				   RG_CSI0A_L0_T0AB_EQ_BW, 1);
+			REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA1C_CSIxA,
+				   RG_CSI0A_L1_T1AB_EQ_IS, 1);
+			REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA1C_CSIxA,
+				   RG_CSI0A_L1_T1AB_EQ_BW, 1);
+			REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA20_CSI0A,
+				   RG_CSI0A_L2_T1BC_EQ_IS, 1);
+			REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA20_CSI0A,
+				   RG_CSI0A_L2_T1BC_EQ_BW, 1);
+		}
+	} else {
+		REGMAP_BIT(regmap_base, MIPI_RX_ANA18_CSIxA,
+			   RG_CSI1A_L0_EQ_IS, 1);
+		REGMAP_BIT(regmap_base, MIPI_RX_ANA18_CSIxA,
+			   RG_CSI1A_L0_EQ_BW, 1);
+		REGMAP_BIT(regmap_base, MIPI_RX_ANA18_CSIxA,
+			   RG_CSI1A_L1_EQ_IS, 1);
+		REGMAP_BIT(regmap_base, MIPI_RX_ANA18_CSIxA,
+			   RG_CSI1A_L1_EQ_BW, 1);
+		REGMAP_BIT(regmap_base, MIPI_RX_ANA1C_CSIxA,
+			   RG_CSI1A_L2_EQ_IS, 1);
+		REGMAP_BIT(regmap_base, MIPI_RX_ANA1C_CSIxA,
+			   RG_CSI1A_L2_EQ_BW, 1);
+
+		if (port->is_4d1c) {
+			REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA18_CSIxA,
+				   RG_CSI1A_L0_EQ_IS, 1);
+			REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA18_CSIxA,
+				   RG_CSI1A_L0_EQ_BW, 1);
+			REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA18_CSIxA,
+				   RG_CSI1A_L1_EQ_IS, 1);
+			REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA18_CSIxA,
+				   RG_CSI1A_L1_EQ_BW, 1);
+			REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA1C_CSIxA,
+				   RG_CSI1A_L2_EQ_IS, 1);
+			REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA1C_CSIxA,
+				   RG_CSI1A_L2_EQ_BW, 1);
+		}
+	}
+
+	/* End ANA EQ tuning */
+	regmap_write(regmap_base, MIPI_RX_ANA40_CSIxA, 0x90);
+
+	REGMAP_BIT(regmap_base, MIPI_RX_ANA24_CSIxA,
+		   RG_CSIxA_RESERVE, 0x40);
+	if (port->is_4d1c)
+		REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA24_CSIxA,
+			   RG_CSIxA_RESERVE, 0x40);
+	REGMAP_BIT(regmap_base, MIPI_RX_WRAPPER80_CSIxA,
+		   CSR_CSI_RST_MODE, 0);
+	if (port->is_4d1c)
+		REGMAP_BIT(regmap_4d1c, MIPI_RX_WRAPPER80_CSIxA,
+			   CSR_CSI_RST_MODE, 0);
+	/* ANA power on */
+	REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
+		   RG_CSIxA_BG_CORE_EN, 1);
+	if (port->is_4d1c)
+		REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA00_CSIxA,
+			   RG_CSIxA_BG_CORE_EN, 1);
+	usleep_range(20, 40);
+	REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
+		   RG_CSIxA_BG_LPF_EN, 1);
+	if (port->is_4d1c)
+		REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA00_CSIxA,
+			   RG_CSIxA_BG_LPF_EN, 1);
+
+	return 0;
+}
+
+static int mtk_mipi_phy_power_off(struct phy *phy)
+{
+	struct mtk_mipi_dphy_port *port = phy_get_drvdata(phy);
+	struct regmap *regmap_base = port->regmap_base;
+	struct regmap *regmap_4d1c = port->regmap_4d1c;
+
+	/* Disable MIPI BG. */
+	REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
+		   RG_CSIxA_BG_CORE_EN, 0);
+	REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
+		   RG_CSIxA_BG_LPF_EN, 0);
+
+	if (port->is_4d1c) {
+		REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA00_CSIxA,
+			   RG_CSIxA_BG_CORE_EN, 0);
+		REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA00_CSIxA,
+			   RG_CSIxA_BG_LPF_EN, 0);
+	}
+
+	mutex_lock(&port->dev->lock);
+	port->active = false;
+	mutex_unlock(&port->dev->lock);
+
+	return 0;
+}
+
+static const struct phy_ops mtk_dphy_ops = {
+	.power_on	= mtk_mipi_phy_power_on,
+	.power_off	= mtk_mipi_phy_power_off,
+	.owner		= THIS_MODULE,
+};
+
+static struct phy *mtk_mipi_dphy_xlate(struct device *dev,
+				       struct of_phandle_args *args)
+{
+	struct mtk_mipi_dphy *priv = dev_get_drvdata(dev);
+
+	if (args->args_count != 1)
+		return ERR_PTR(-EINVAL);
+
+	if (args->args[0] >= ARRAY_SIZE(priv->ports))
+		return ERR_PTR(-ENODEV);
+
+	return priv->ports[args->args[0]].phy;
+}
+
+static const struct regmap_config mt8365_phy_regmap_config = {
+	.reg_bits = 32,
+	.val_bits = 32,
+	.reg_stride = 4,
+	.max_register = 0x700,
+};
+
+static int mtk_mipi_dphy_probe(struct platform_device *pdev)
+{
+	static const unsigned int ports_offsets[] = {
+		[MTK_MIPI_PHY_PORT_0] = 0,
+		[MTK_MIPI_PHY_PORT_0A] = 0,
+		[MTK_MIPI_PHY_PORT_0B] = 0x1000,
+		[MTK_MIPI_PHY_PORT_1] = 0x2000,
+		[MTK_MIPI_PHY_PORT_2] = 0x4000,
+	};
+
+	struct device *dev = &pdev->dev;
+	struct phy_provider *phy_provider;
+	struct mtk_mipi_dphy *priv;
+	struct resource *res;
+	unsigned int i;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	dev_set_drvdata(dev, priv);
+	priv->dev = dev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	priv->rx = devm_ioremap_resource(dev, res);
+	if (IS_ERR(priv->rx))
+		return PTR_ERR(priv->rx);
+
+	for (i = 0; i < ARRAY_SIZE(priv->ports); ++i) {
+		struct mtk_mipi_dphy_port *port = &priv->ports[i];
+		struct phy *phy;
+		void __iomem *base;
+
+		port->dev = priv;
+		port->id = i;
+		base = priv->rx + ports_offsets[i];
+
+		port->regmap_base = devm_regmap_init_mmio(port->dev->dev,
+							  base,
+							  &mt8365_phy_regmap_config);
+
+		port->is_cdphy = i == MTK_MIPI_PHY_PORT_0A ||
+				 i == MTK_MIPI_PHY_PORT_0B ||
+				 i == MTK_MIPI_PHY_PORT_0;
+		port->is_4d1c = i < MTK_MIPI_PHY_PORT_0A;
+
+		if (port->is_4d1c)
+			port->regmap_4d1c = devm_regmap_init_mmio(port->dev->dev,
+								  base + CSIxB_OFFSET,
+								  &mt8365_phy_regmap_config);
+
+		phy = devm_phy_create(dev, NULL, &mtk_dphy_ops);
+		if (IS_ERR(phy)) {
+			dev_err(dev, "Failed to create PHY: %ld\n", PTR_ERR(phy));
+			return PTR_ERR(phy);
+		}
+
+		port->phy = phy;
+		phy_set_drvdata(phy, port);
+	}
+
+	phy_provider = devm_of_phy_provider_register(dev, mtk_mipi_dphy_xlate);
+	if (IS_ERR(phy_provider)) {
+		dev_err(dev, "Failed to register PHY provider: %ld\n",
+			PTR_ERR(phy_provider));
+		return PTR_ERR(phy_provider);
+	}
+
+	mutex_init(&priv->lock);
+
+	return 0;
+}
+
+static int mtk_mipi_dphy_remove(struct platform_device *pdev)
+{
+	struct mtk_mipi_dphy *priv = platform_get_drvdata(pdev);
+
+	mutex_destroy(&priv->lock);
+
+	return 0;
+}
+
+static const struct of_device_id mtk_mipi_dphy_of_match[] = {
+	{.compatible = "mediatek,mt8365-mipi-csi"},
+	{},
+};
+MODULE_DEVICE_TABLE(of, mtk_mipi_dphy_of_match);
+
+static struct platform_driver mipi_dphy_pdrv = {
+	.probe = mtk_mipi_dphy_probe,
+	.remove = mtk_mipi_dphy_remove,
+	.driver	= {
+		.name	= "mtk-mipi-csi",
+		.of_match_table = of_match_ptr(mtk_mipi_dphy_of_match),
+	},
+};
+
+module_platform_driver(mipi_dphy_pdrv);
+
+MODULE_DESCRIPTION("MTK mipi csi cdphy driver");
+MODULE_AUTHOR("Louis Kuo <louis.kuo@mediatek.com>");
+MODULE_LICENSE("GPL");
-- 
2.40.0


-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

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

* Re: [PATCH 1/2] dt-bindings: phy: add mtk-mipi-csi driver
  2023-04-03  7:19 ` [PATCH 1/2] dt-bindings: phy: add mtk-mipi-csi driver Julien Stephan
@ 2023-04-03  9:49   ` Krzysztof Kozlowski
       [not found]     ` <CAEHHSvYJrCZop8OvTjsLJjr5HHSrG8dsSQ+K_W2cjdKJ4xfodA@mail.gmail.com>
  2023-04-03 13:10   ` Rob Herring
  2023-04-07  2:40   ` Chunfeng Yun (云春峰)
  2 siblings, 1 reply; 13+ messages in thread
From: Krzysztof Kozlowski @ 2023-04-03  9:49 UTC (permalink / raw)
  To: Julien Stephan
  Cc: Florian Sylvestre, Chunfeng Yun, Andy Hsieh, Vinod Koul,
	Kishon Vijay Abraham I, Rob Herring, Krzysztof Kozlowski,
	Matthias Brugger, AngeloGioacchino Del Regno,
	moderated list:ARM/Mediatek USB3 PHY DRIVER,
	moderated list:ARM/Mediatek USB3 PHY DRIVER,
	open list:GENERIC PHY FRAMEWORK,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list

On 03/04/2023 09:19, Julien Stephan wrote:
> From: Florian Sylvestre <fsylvestre@baylibre.com>
> 

There is no commit msg.

> Signed-off-by: Florian Sylvestre <fsylvestre@baylibre.com>
> Signed-off-by: Julien Stephan <jstephan@baylibre.com>
> ---
>  .../bindings/phy/mediatek,csi-phy.yaml        | 41 +++++++++++++++++++
>  MAINTAINERS                                   |  6 +++
>  2 files changed, 47 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/phy/mediatek,csi-phy.yaml
> 
> diff --git a/Documentation/devicetree/bindings/phy/mediatek,csi-phy.yaml b/Documentation/devicetree/bindings/phy/mediatek,csi-phy.yaml
> new file mode 100644
> index 000000000000..c026e43f35fd
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/phy/mediatek,csi-phy.yaml

Filename like compatible.

> @@ -0,0 +1,41 @@
> +# SPDX-License-Identifier: (GPL-2.0-Only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/phy/mediatek,csi-phy.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Mediatek Sensor Interface MIPI CSI CD-PHY
> +
> +maintainers:
> +  - Julien Stephan <jstephan@baylibre.com>
> +  - Andy Hsieh <andy.hsieh@mediatek.com>
> +
> +description: |

Do not need '|'.

> +  The SENINF CD-PHY is a set of CD-PHY connected to the SENINF CSI-2
> +  receivers. The number of PHYs depends on the SoC model.
> +
> +properties:
> +  compatible:
> +    const: mediatek,mt8365-mipi-csi
> +
> +  reg:
> +    minItems: 1

maxItems instead
(from where did you get such example?)

> +
> +  '#phy-cells':
> +    const: 1
> +


Best regards,
Krzysztof


-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

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

* Re: [PATCH 2/2] phy: mtk-mipi-csi: add driver for CSI phy
  2023-04-03  7:19 ` [PATCH 2/2] phy: mtk-mipi-csi: add driver for CSI phy Julien Stephan
@ 2023-04-03  9:51   ` Krzysztof Kozlowski
  2023-04-05  9:27     ` Julien Stephan
  2023-04-03 10:15   ` Chun-Kuang Hu
                     ` (4 subsequent siblings)
  5 siblings, 1 reply; 13+ messages in thread
From: Krzysztof Kozlowski @ 2023-04-03  9:51 UTC (permalink / raw)
  To: Julien Stephan
  Cc: Phi-bang Nguyen, Louis Kuo, Chunfeng Yun, Andy Hsieh, Vinod Koul,
	Kishon Vijay Abraham I, Rob Herring, Krzysztof Kozlowski,
	Chun-Kuang Hu, Philipp Zabel, Matthias Brugger,
	AngeloGioacchino Del Regno,
	moderated list:ARM/Mediatek USB3 PHY DRIVER,
	moderated list:ARM/Mediatek USB3 PHY DRIVER,
	open list:GENERIC PHY FRAMEWORK,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list, open list:DRM DRIVERS FOR MEDIATEK

On 03/04/2023 09:19, Julien Stephan wrote:
> From: Phi-bang Nguyen <pnguyen@baylibre.com>
> 
> This is a new driver that supports the MIPI CSI CD-PHY for mediatek
> mt8365 soc
> 
> Signed-off-by: Louis Kuo <louis.kuo@mediatek.com>
> Signed-off-by: Phi-bang Nguyen <pnguyen@baylibre.com>
> [Julien Stephan: use regmap]
> [Julien Stephan: use GENMASK]
> Co-developed-by: Julien Stephan <jstephan@baylibre.com>
> Signed-off-by: Julien Stephan <jstephan@baylibre.com>
> ---
>  .../bindings/phy/mediatek,csi-phy.yaml        |   9 +-
>  MAINTAINERS                                   |   1 +
>  drivers/phy/mediatek/Kconfig                  |   8 +
>  drivers/phy/mediatek/Makefile                 |   2 +
>  .../phy/mediatek/phy-mtk-mipi-csi-rx-reg.h    | 435 ++++++++++++++++++
>  drivers/phy/mediatek/phy-mtk-mipi-csi.c       | 392 ++++++++++++++++
>  6 files changed, 845 insertions(+), 2 deletions(-)
>  create mode 100644 drivers/phy/mediatek/phy-mtk-mipi-csi-rx-reg.h
>  create mode 100644 drivers/phy/mediatek/phy-mtk-mipi-csi.c
> 
> diff --git a/Documentation/devicetree/bindings/phy/mediatek,csi-phy.yaml b/Documentation/devicetree/bindings/phy/mediatek,csi-phy.yaml
> index c026e43f35fd..ad4ba1d93a68 100644
> --- a/Documentation/devicetree/bindings/phy/mediatek,csi-phy.yaml
> +++ b/Documentation/devicetree/bindings/phy/mediatek,csi-phy.yaml

NAK, bindings are always separate patches. It also does not make any
sense - you just added it.

> @@ -33,9 +33,14 @@ additionalProperties: false
>  
>  examples:
>    - |
> -    phy@10011800 {
> +    soc {
> +      #address-cells = <2>;
> +      #size-cells = <2>;
> +
> +      phy@11c10000 {
>          compatible = "mediatek,mt8365-mipi-csi";
> -        reg = <0 0x10011800 0 0x60>;
> +        reg = <0 0x11c10000 0 0x4000>;
>          #phy-cells = <1>;
> +      };
>      };



k_mipi_dphy_of_match[] = {
> +	{.compatible = "mediatek,mt8365-mipi-csi"},
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, mtk_mipi_dphy_of_match);
> +
> +static struct platform_driver mipi_dphy_pdrv = {
> +	.probe = mtk_mipi_dphy_probe,
> +	.remove = mtk_mipi_dphy_remove,
> +	.driver	= {
> +		.name	= "mtk-mipi-csi",
> +		.of_match_table = of_match_ptr(mtk_mipi_dphy_of_match),

Drop of_match_ptr(). You should see W=1 warnings when compile testing.


Best regards,
Krzysztof


-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

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

* Re: [PATCH 2/2] phy: mtk-mipi-csi: add driver for CSI phy
  2023-04-03  7:19 ` [PATCH 2/2] phy: mtk-mipi-csi: add driver for CSI phy Julien Stephan
  2023-04-03  9:51   ` Krzysztof Kozlowski
@ 2023-04-03 10:15   ` Chun-Kuang Hu
  2023-04-03 15:21   ` Chun-Kuang Hu
                     ` (3 subsequent siblings)
  5 siblings, 0 replies; 13+ messages in thread
From: Chun-Kuang Hu @ 2023-04-03 10:15 UTC (permalink / raw)
  To: Julien Stephan
  Cc: Phi-bang Nguyen, Louis Kuo, Chunfeng Yun, Andy Hsieh, Vinod Koul,
	Kishon Vijay Abraham I, Rob Herring, Krzysztof Kozlowski,
	Chun-Kuang Hu, Philipp Zabel, Matthias Brugger,
	AngeloGioacchino Del Regno,
	moderated list:ARM/Mediatek USB3 PHY DRIVER,
	moderated list:ARM/Mediatek USB3 PHY DRIVER,
	open list:GENERIC PHY FRAMEWORK,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list, open list:DRM DRIVERS FOR MEDIATEK

Hi, Julien:

Julien Stephan <jstephan@baylibre.com> 於 2023年4月3日 週一 下午3:20寫道:
>
> From: Phi-bang Nguyen <pnguyen@baylibre.com>
>
> This is a new driver that supports the MIPI CSI CD-PHY for mediatek
> mt8365 soc
>
> Signed-off-by: Louis Kuo <louis.kuo@mediatek.com>
> Signed-off-by: Phi-bang Nguyen <pnguyen@baylibre.com>
> [Julien Stephan: use regmap]
> [Julien Stephan: use GENMASK]
> Co-developed-by: Julien Stephan <jstephan@baylibre.com>
> Signed-off-by: Julien Stephan <jstephan@baylibre.com>
> ---
>  .../bindings/phy/mediatek,csi-phy.yaml        |   9 +-
>  MAINTAINERS                                   |   1 +
>  drivers/phy/mediatek/Kconfig                  |   8 +
>  drivers/phy/mediatek/Makefile                 |   2 +
>  .../phy/mediatek/phy-mtk-mipi-csi-rx-reg.h    | 435 ++++++++++++++++++
>  drivers/phy/mediatek/phy-mtk-mipi-csi.c       | 392 ++++++++++++++++
>  6 files changed, 845 insertions(+), 2 deletions(-)
>  create mode 100644 drivers/phy/mediatek/phy-mtk-mipi-csi-rx-reg.h
>  create mode 100644 drivers/phy/mediatek/phy-mtk-mipi-csi.c
>

[snip]

> +static int mtk_mipi_phy_power_on(struct phy *phy)
> +{
> +       struct mtk_mipi_dphy_port *port = phy_get_drvdata(phy);
> +       struct mtk_mipi_dphy *priv = port->dev;
> +       struct regmap *regmap_base = port->regmap_base;
> +       struct regmap *regmap_4d1c = port->regmap_4d1c;
> +       int ret = 0;
> +
> +       mutex_lock(&priv->lock);
> +
> +       switch (port->id) {
> +       case MTK_MIPI_PHY_PORT_0:
> +               if (priv->ports[MTK_MIPI_PHY_PORT_0A].active ||
> +                   priv->ports[MTK_MIPI_PHY_PORT_0B].active)
> +                       ret = -EBUSY;
> +               break;
> +
> +       case MTK_MIPI_PHY_PORT_0A:
> +       case MTK_MIPI_PHY_PORT_0B:
> +               if (priv->ports[MTK_MIPI_PHY_PORT_0].active)
> +                       ret = -EBUSY;
> +               break;
> +       }
> +
> +       if (!ret)
> +               port->active = true;
> +
> +       mutex_unlock(&priv->lock);
> +
> +       if (ret < 0)
> +               return ret;
> +
> +       /* Set analog phy mode to DPHY */
> +       if (port->is_cdphy)
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSI0A_CPHY_EN, 0);
> +
> +       if (port->is_4d1c) {
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L0_CKMODE_EN, 0);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L0_CKSEL, 1);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L1_CKMODE_EN, 0);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L1_CKSEL, 1);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L2_CKMODE_EN, 1);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L2_CKSEL, 1);
> +       } else {
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L0_CKMODE_EN, 0);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L0_CKSEL, 0);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L1_CKMODE_EN, 1);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L1_CKSEL, 0);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L2_CKMODE_EN, 0);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L2_CKSEL, 0);
> +       }
> +
> +       if (port->is_4d1c) {
> +               if (port->is_cdphy)
> +                       REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA00_CSIxA,
> +                                  RG_CSI0A_CPHY_EN, 0);
> +
> +               REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L0_CKMODE_EN, 0);
> +               REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L0_CKSEL, 1);
> +               REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L1_CKMODE_EN, 0);
> +               REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L1_CKSEL, 1);
> +               REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L2_CKMODE_EN, 0);
> +               REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L2_CKSEL, 1);
> +       }
> +
> +       /* Byte clock invert */
> +       REGMAP_BIT(regmap_base, MIPI_RX_ANAA8_CSIxA,
> +                  RG_CSIxA_CDPHY_L0_T0_BYTECK_INVERT, 1);
> +       REGMAP_BIT(regmap_base, MIPI_RX_ANAA8_CSIxA,
> +                  RG_CSIxA_DPHY_L1_BYTECK_INVERT, 1);
> +       REGMAP_BIT(regmap_base, MIPI_RX_ANAA8_CSIxA,
> +                  RG_CSIxA_CDPHY_L2_T1_BYTECK_INVERT, 1);
> +
> +       if (port->is_4d1c) {
> +               REGMAP_BIT(regmap_4d1c, MIPI_RX_ANAA8_CSIxA,
> +                          RG_CSIxA_CDPHY_L0_T0_BYTECK_INVERT, 1);
> +               REGMAP_BIT(regmap_4d1c, MIPI_RX_ANAA8_CSIxA,
> +                          RG_CSIxA_DPHY_L1_BYTECK_INVERT, 1);
> +               REGMAP_BIT(regmap_4d1c, MIPI_RX_ANAA8_CSIxA,
> +                          RG_CSIxA_CDPHY_L2_T1_BYTECK_INVERT, 1);
> +       }
> +
> +       /* Start ANA EQ tuning */
> +       if (port->is_cdphy) {
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA18_CSIxA,
> +                          RG_CSI0A_L0_T0AB_EQ_IS, 1);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA18_CSIxA,
> +                          RG_CSI0A_L0_T0AB_EQ_BW, 1);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA1C_CSIxA,
> +                          RG_CSI0A_L1_T1AB_EQ_IS, 1);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA1C_CSIxA,
> +                          RG_CSI0A_L1_T1AB_EQ_BW, 1);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA20_CSI0A,
> +                          RG_CSI0A_L2_T1BC_EQ_IS, 1);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA20_CSI0A,
> +                          RG_CSI0A_L2_T1BC_EQ_BW, 1);
> +
> +               if (port->is_4d1c) {
> +                       REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA18_CSIxA,
> +                                  RG_CSI0A_L0_T0AB_EQ_IS, 1);
> +                       REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA18_CSIxA,
> +                                  RG_CSI0A_L0_T0AB_EQ_BW, 1);
> +                       REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA1C_CSIxA,
> +                                  RG_CSI0A_L1_T1AB_EQ_IS, 1);
> +                       REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA1C_CSIxA,
> +                                  RG_CSI0A_L1_T1AB_EQ_BW, 1);
> +                       REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA20_CSI0A,
> +                                  RG_CSI0A_L2_T1BC_EQ_IS, 1);
> +                       REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA20_CSI0A,
> +                                  RG_CSI0A_L2_T1BC_EQ_BW, 1);
> +               }
> +       } else {
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA18_CSIxA,
> +                          RG_CSI1A_L0_EQ_IS, 1);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA18_CSIxA,
> +                          RG_CSI1A_L0_EQ_BW, 1);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA18_CSIxA,
> +                          RG_CSI1A_L1_EQ_IS, 1);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA18_CSIxA,
> +                          RG_CSI1A_L1_EQ_BW, 1);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA1C_CSIxA,
> +                          RG_CSI1A_L2_EQ_IS, 1);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA1C_CSIxA,
> +                          RG_CSI1A_L2_EQ_BW, 1);
> +
> +               if (port->is_4d1c) {
> +                       REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA18_CSIxA,
> +                                  RG_CSI1A_L0_EQ_IS, 1);

RG_CSI1A_L0_EQ_IS is identical to RG_CSI0A_L0_T0AB_EQ_IS, and ditto
for below register. I think the function of each bitwise register is
the same. Define only one copy of the these register, don't duplicate
the same thing.

Regards,
Chun-Kuang.

> +                       REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA18_CSIxA,
> +                                  RG_CSI1A_L0_EQ_BW, 1);
> +                       REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA18_CSIxA,
> +                                  RG_CSI1A_L1_EQ_IS, 1);
> +                       REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA18_CSIxA,
> +                                  RG_CSI1A_L1_EQ_BW, 1);
> +                       REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA1C_CSIxA,
> +                                  RG_CSI1A_L2_EQ_IS, 1);
> +                       REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA1C_CSIxA,
> +                                  RG_CSI1A_L2_EQ_BW, 1);
> +               }
> +       }
> +
> +       /* End ANA EQ tuning */
> +       regmap_write(regmap_base, MIPI_RX_ANA40_CSIxA, 0x90);
> +
> +       REGMAP_BIT(regmap_base, MIPI_RX_ANA24_CSIxA,
> +                  RG_CSIxA_RESERVE, 0x40);
> +       if (port->is_4d1c)
> +               REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA24_CSIxA,
> +                          RG_CSIxA_RESERVE, 0x40);
> +       REGMAP_BIT(regmap_base, MIPI_RX_WRAPPER80_CSIxA,
> +                  CSR_CSI_RST_MODE, 0);
> +       if (port->is_4d1c)
> +               REGMAP_BIT(regmap_4d1c, MIPI_RX_WRAPPER80_CSIxA,
> +                          CSR_CSI_RST_MODE, 0);
> +       /* ANA power on */
> +       REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                  RG_CSIxA_BG_CORE_EN, 1);
> +       if (port->is_4d1c)
> +               REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_BG_CORE_EN, 1);
> +       usleep_range(20, 40);
> +       REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                  RG_CSIxA_BG_LPF_EN, 1);
> +       if (port->is_4d1c)
> +               REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_BG_LPF_EN, 1);
> +
> +       return 0;
> +}
> +

-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

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

* Re: [PATCH 1/2] dt-bindings: phy: add mtk-mipi-csi driver
  2023-04-03  7:19 ` [PATCH 1/2] dt-bindings: phy: add mtk-mipi-csi driver Julien Stephan
  2023-04-03  9:49   ` Krzysztof Kozlowski
@ 2023-04-03 13:10   ` Rob Herring
  2023-04-07  2:40   ` Chunfeng Yun (云春峰)
  2 siblings, 0 replies; 13+ messages in thread
From: Rob Herring @ 2023-04-03 13:10 UTC (permalink / raw)
  To: Julien Stephan
  Cc: Matthias Brugger, linux-mediatek, devicetree, Andy Hsieh,
	AngeloGioacchino Del Regno, Chunfeng Yun, Rob Herring,
	Florian Sylvestre, Vinod Koul, Kishon Vijay Abraham I,
	Krzysztof Kozlowski, linux-kernel, linux-phy, linux-arm-kernel


On Mon, 03 Apr 2023 09:19:28 +0200, Julien Stephan wrote:
> From: Florian Sylvestre <fsylvestre@baylibre.com>
> 
> Signed-off-by: Florian Sylvestre <fsylvestre@baylibre.com>
> Signed-off-by: Julien Stephan <jstephan@baylibre.com>
> ---
>  .../bindings/phy/mediatek,csi-phy.yaml        | 41 +++++++++++++++++++
>  MAINTAINERS                                   |  6 +++
>  2 files changed, 47 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/phy/mediatek,csi-phy.yaml
> 

My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
on your patch (DT_CHECKER_FLAGS is new in v5.13):

yamllint warnings/errors:

dtschema/dtc warnings/errors:
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/phy/mediatek,csi-phy.example.dtb: phy@10011800: reg: [[0, 268507136], [0, 96]] is too long
	From schema: /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/phy/mediatek,csi-phy.yaml

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20230403071929.360911-2-jstephan@baylibre.com

The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.


-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

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

* Re: [PATCH 1/2] dt-bindings: phy: add mtk-mipi-csi driver
       [not found]     ` <CAEHHSvYJrCZop8OvTjsLJjr5HHSrG8dsSQ+K_W2cjdKJ4xfodA@mail.gmail.com>
@ 2023-04-03 14:54       ` Krzysztof Kozlowski
  0 siblings, 0 replies; 13+ messages in thread
From: Krzysztof Kozlowski @ 2023-04-03 14:54 UTC (permalink / raw)
  To: Julien Stephan
  Cc: Florian Sylvestre, Chunfeng Yun, Andy Hsieh, Vinod Koul,
	Kishon Vijay Abraham I, Rob Herring, Krzysztof Kozlowski,
	Matthias Brugger, AngeloGioacchino Del Regno,
	moderated list:ARM/Mediatek USB3 PHY DRIVER,
	moderated list:ARM/Mediatek USB3 PHY DRIVER,
	open list:GENERIC PHY FRAMEWORK,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list

On 03/04/2023 16:40, Julien Stephan wrote:
> Hi Krzysztof,
> 
> Le lun. 3 avr. 2023 à 11:49, Krzysztof Kozlowski <
> krzysztof.kozlowski@linaro.org> a écrit :
> 
>> On 03/04/2023 09:19, Julien Stephan wrote:
>>> From: Florian Sylvestre <fsylvestre@baylibre.com>
>>>
>>
>> There is no commit msg.
>>
>>> Signed-off-by: Florian Sylvestre <fsylvestre@baylibre.com>
>>> Signed-off-by: Julien Stephan <jstephan@baylibre.com>
>>> ---
>>>  .../bindings/phy/mediatek,csi-phy.yaml        | 41 +++++++++++++++++++
>>>  MAINTAINERS                                   |  6 +++
>>>  2 files changed, 47 insertions(+)
>>>  create mode 100644
>> Documentation/devicetree/bindings/phy/mediatek,csi-phy.yaml
>>>
>>> diff --git a/Documentation/devicetree/bindings/phy/mediatek,csi-phy.yaml
>> b/Documentation/devicetree/bindings/phy/mediatek,csi-phy.yaml
>>> new file mode 100644
>>> index 000000000000..c026e43f35fd
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/phy/mediatek,csi-phy.yaml
>>
>> Filename like compatible.
>>
> Should I rename the binding  file
> Documentation/devicetree/bindings/phy/mediatek,mt8365-mipi-csi.yaml or

This.

> should I rename the compatible string mediatek,csi-phy?
> The csi PHY module is a module of the mt8365 soc and can possibly be used
> on other mediatek soc.  I think this binding is generic enough to have a
> generic name, what do you think?

You did not allow adding new variants, as you made it const, not enum.
If there are other devices with this phy, they could be even added now.
Bindings should be rather complete.


Best regards,
Krzysztof


-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

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

* Re: [PATCH 2/2] phy: mtk-mipi-csi: add driver for CSI phy
  2023-04-03  7:19 ` [PATCH 2/2] phy: mtk-mipi-csi: add driver for CSI phy Julien Stephan
  2023-04-03  9:51   ` Krzysztof Kozlowski
  2023-04-03 10:15   ` Chun-Kuang Hu
@ 2023-04-03 15:21   ` Chun-Kuang Hu
  2023-04-03 16:36   ` Chun-Kuang Hu
                     ` (2 subsequent siblings)
  5 siblings, 0 replies; 13+ messages in thread
From: Chun-Kuang Hu @ 2023-04-03 15:21 UTC (permalink / raw)
  To: Julien Stephan
  Cc: Phi-bang Nguyen, Louis Kuo, Chunfeng Yun, Andy Hsieh, Vinod Koul,
	Kishon Vijay Abraham I, Rob Herring, Krzysztof Kozlowski,
	Chun-Kuang Hu, Philipp Zabel, Matthias Brugger,
	AngeloGioacchino Del Regno,
	moderated list:ARM/Mediatek USB3 PHY DRIVER,
	moderated list:ARM/Mediatek USB3 PHY DRIVER,
	open list:GENERIC PHY FRAMEWORK,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list, open list:DRM DRIVERS FOR MEDIATEK

Hi, Julien:

Julien Stephan <jstephan@baylibre.com> 於 2023年4月3日 週一 下午3:20寫道:
>
> From: Phi-bang Nguyen <pnguyen@baylibre.com>
>
> This is a new driver that supports the MIPI CSI CD-PHY for mediatek
> mt8365 soc
>
> Signed-off-by: Louis Kuo <louis.kuo@mediatek.com>
> Signed-off-by: Phi-bang Nguyen <pnguyen@baylibre.com>
> [Julien Stephan: use regmap]
> [Julien Stephan: use GENMASK]
> Co-developed-by: Julien Stephan <jstephan@baylibre.com>
> Signed-off-by: Julien Stephan <jstephan@baylibre.com>
> ---
>  .../bindings/phy/mediatek,csi-phy.yaml        |   9 +-
>  MAINTAINERS                                   |   1 +
>  drivers/phy/mediatek/Kconfig                  |   8 +
>  drivers/phy/mediatek/Makefile                 |   2 +
>  .../phy/mediatek/phy-mtk-mipi-csi-rx-reg.h    | 435 ++++++++++++++++++
>  drivers/phy/mediatek/phy-mtk-mipi-csi.c       | 392 ++++++++++++++++
>  6 files changed, 845 insertions(+), 2 deletions(-)
>  create mode 100644 drivers/phy/mediatek/phy-mtk-mipi-csi-rx-reg.h
>  create mode 100644 drivers/phy/mediatek/phy-mtk-mipi-csi.c
>

[snip]

> +
> +#define MIPI_RX_ANA04_CSIxA                                                    0x0004

Useless, so drop this.

> +#define MIPI_RX_ANA04_CSIxA_RG_CSIxA_BG_LPRX_VTH_SEL_SHIFT                     0
> +#define MIPI_RX_ANA04_CSIxA_RG_CSIxA_BG_LPRX_VTH_SEL_MASK                      GENMASK(2, 0)
> +#define MIPI_RX_ANA04_CSIxA_RG_CSIxA_BG_LPRX_VTL_SEL_SHIFT                     4
> +#define MIPI_RX_ANA04_CSIxA_RG_CSIxA_BG_LPRX_VTL_SEL_MASK                      GENMASK(6, 4)
> +#define MIPI_RX_ANA04_CSIxA_RG_CSIxA_BG_HSDET_VTH_SEL_SHIFT                    8
> +#define MIPI_RX_ANA04_CSIxA_RG_CSIxA_BG_HSDET_VTH_SEL_MASK                     GENMASK(10, 8)
> +#define MIPI_RX_ANA04_CSIxA_RG_CSIxA_BG_HSDET_VTL_SEL_SHIFT                    12
> +#define MIPI_RX_ANA04_CSIxA_RG_CSIxA_BG_HSDET_VTL_SEL_MASK                     GENMASK(14, 12)
> +#define MIPI_RX_ANA04_CSIxA_RG_CSIxA_BG_VREF_SEL_SHIFT                         16
> +#define MIPI_RX_ANA04_CSIxA_RG_CSIxA_BG_VREF_SEL_MASK                          GENMASK(19, 16)
> +#define MIPI_RX_ANA04_CSIxA_RG_CSIxA_BG_MON_VREF_SEL_SHIFT                     24
> +#define MIPI_RX_ANA04_CSIxA_RG_CSIxA_BG_MON_VREF_SEL_MASK                      GENMASK(27, 24)
> +#define MIPI_RX_ANA04_CSIxA_RG_CSIxA_FORCE_HSRT_EN_SHIFT                       28
> +#define MIPI_RX_ANA04_CSIxA_RG_CSIxA_FORCE_HSRT_EN_MASK                                BIT(28)
> +
> +#define MIPI_RX_ANA08_CSIxA                                                    0x0008

Ditto.

> +#define MIPI_RX_ANA08_CSIxA_RG_CSIxA_L0P_T0A_HSRT_CODE_SHIFT                   0
> +#define MIPI_RX_ANA08_CSIxA_RG_CSIxA_L0P_T0A_HSRT_CODE_MASK                    GENMASK(4, 0)
> +#define MIPI_RX_ANA08_CSIxA_RG_CSIxA_L0N_T0B_HSRT_CODE_SHIFT                   8
> +#define MIPI_RX_ANA08_CSIxA_RG_CSIxA_L0N_T0B_HSRT_CODE_MASK                    GENMASK(12, 8)
> +#define MIPI_RX_ANA08_CSIxA_RG_CSIxA_L1P_T0C_HSRT_CODE_SHIFT                   16
> +#define MIPI_RX_ANA08_CSIxA_RG_CSIxA_L1P_T0C_HSRT_CODE_MASK                    GENMASK(20, 16)
> +#define MIPI_RX_ANA08_CSIxA_RG_CSIxA_L1N_T1A_HSRT_CODE_SHIFT                   24
> +#define MIPI_RX_ANA08_CSIxA_RG_CSIxA_L1N_T1A_HSRT_CODE_MASK                    GENMASK(28, 24)
> +
> +#define MIPI_RX_ANA0C_CSIxA                                                    0x000c

Ditto.

> +#define MIPI_RX_ANA0C_CSIxA_RG_CSIxA_L2P_T1B_HSRT_CODE_SHIFT                   0
> +#define MIPI_RX_ANA0C_CSIxA_RG_CSIxA_L2P_T1B_HSRT_CODE_MASK                    GENMASK(4, 0)
> +#define MIPI_RX_ANA0C_CSIxA_RG_CSIxA_L2N_T1C_HSRT_CODE_SHIFT                   8
> +#define MIPI_RX_ANA0C_CSIxA_RG_CSIxA_L2N_T1C_HSRT_CODE_MASK                    GENMASK(12, 8)
> +
> +#define MIPI_RX_ANA10_CSIxA                                                    0x0010

Ditto.

> +#define MIPI_RX_ANA10_CSIxA_RG_CSIxA_DPHY_L0_DELAYCAL_EN_SHIFT                 0
> +#define MIPI_RX_ANA10_CSIxA_RG_CSIxA_DPHY_L0_DELAYCAL_EN_MASK                  BIT(0)
> +#define MIPI_RX_ANA10_CSIxA_RG_CSIxA_DPHY_L0_DELAYCAL_RSTB_SHIFT               1
> +#define MIPI_RX_ANA10_CSIxA_RG_CSIxA_DPHY_L0_DELAYCAL_RSTB_MASK                        BIT(1)
> +#define MIPI_RX_ANA10_CSIxA_RG_CSIxA_DPHY_L0_VREF_SEL_SHIFT                    2
> +#define MIPI_RX_ANA10_CSIxA_RG_CSIxA_DPHY_L0_VREF_SEL_MASK                     GENMASK(7, 2)
> +#define MIPI_RX_ANA10_CSIxA_RG_CSIxA_DPHY_L1_DELAYCAL_EN_SHIFT                 8
> +#define MIPI_RX_ANA10_CSIxA_RG_CSIxA_DPHY_L1_DELAYCAL_EN_MASK                  BIT(8)
> +#define MIPI_RX_ANA10_CSIxA_RG_CSIxA_DPHY_L1_DELAYCAL_RSTB_SHIFT               9
> +#define MIPI_RX_ANA10_CSIxA_RG_CSIxA_DPHY_L1_DELAYCAL_RSTB_MASK                        BIT(9)
> +#define MIPI_RX_ANA10_CSIxA_RG_CSIxA_DPHY_L1_VREF_SEL_SHIFT                    10
> +#define MIPI_RX_ANA10_CSIxA_RG_CSIxA_DPHY_L1_VREF_SEL_MASK                     GENMASK(15, 10)
> +#define MIPI_RX_ANA10_CSIxA_RG_CSIxA_DPHY_L2_DELAYCAL_EN_SHIFT                 16
> +#define MIPI_RX_ANA10_CSIxA_RG_CSIxA_DPHY_L2_DELAYCAL_EN_MASK                  BIT(16)
> +#define MIPI_RX_ANA10_CSIxA_RG_CSIxA_DPHY_L2_DELAYCAL_RSTB_SHIFT               17
> +#define MIPI_RX_ANA10_CSIxA_RG_CSIxA_DPHY_L2_DELAYCAL_RSTB_MASK                        BIT(17)
> +#define MIPI_RX_ANA10_CSIxA_RG_CSIxA_DPHY_L2_VREF_SEL_SHIFT                    18
> +#define MIPI_RX_ANA10_CSIxA_RG_CSIxA_DPHY_L2_VREF_SEL_MASK                     GENMASK(23, 18)
> +/* C-PHY fields are only available in CSIx. */
> +#define MIPI_RX_ANA10_CSIxA_RG_CSI0A_CPHY_T0_CDR_DELAYCAL_EN_SHIFT             24
> +#define MIPI_RX_ANA10_CSIxA_RG_CSI0A_CPHY_T0_CDR_DELAYCAL_EN_MASK              BIT(24)
> +#define MIPI_RX_ANA10_CSIxA_RG_CSI0A_CPHY_T0_CDR_DELAYCAL_RSTB_SHIFT           25
> +#define MIPI_RX_ANA10_CSIxA_RG_CSI0A_CPHY_T0_CDR_DELAYCAL_RSTB_MASK            BIT(25)
> +#define MIPI_RX_ANA10_CSIxA_RG_CSI0A_CPHY_T0_VREF_SEL_SHIFT                    26
> +#define MIPI_RX_ANA10_CSIxA_RG_CSI0A_CPHY_T0_VREF_SEL_MASK                     GENMASK(31, 26)
> +
> +#define MIPI_RX_ANA14_CSIxA                                                    0x0014

Ditto.

Regards,
Chun-Kuang.


> +/* C-PHY fields are only available in CSIx. */
> +#define MIPI_RX_ANA14_CSIxA_RG_CSI0A_CPHY_T1_CDR_DELAYCAL_EN_SHIFT             0
> +#define MIPI_RX_ANA14_CSIxA_RG_CSI0A_CPHY_T1_CDR_DELAYCAL_EN_MASK              BIT(0)
> +#define MIPI_RX_ANA14_CSIxA_RG_CSI0A_CPHY_T1_CDR_DELAYCAL_RSTB_SHIFT           1
> +#define MIPI_RX_ANA14_CSIxA_RG_CSI0A_CPHY_T1_CDR_DELAYCAL_RSTB_MASK            BIT(1)
> +#define MIPI_RX_ANA14_CSIxA_RG_CSI0A_CPHY_T1_VREF_SEL_SHIFT                    2
> +#define MIPI_RX_ANA14_CSIxA_RG_CSI0A_CPHY_T1_VREF_SEL_MASK                     GENMASK(7, 2)
> +

-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

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

* Re: [PATCH 2/2] phy: mtk-mipi-csi: add driver for CSI phy
  2023-04-03  7:19 ` [PATCH 2/2] phy: mtk-mipi-csi: add driver for CSI phy Julien Stephan
                     ` (2 preceding siblings ...)
  2023-04-03 15:21   ` Chun-Kuang Hu
@ 2023-04-03 16:36   ` Chun-Kuang Hu
  2023-04-07  3:31   ` Chunfeng Yun (云春峰)
  2023-04-07  5:30   ` Chunfeng Yun (云春峰)
  5 siblings, 0 replies; 13+ messages in thread
From: Chun-Kuang Hu @ 2023-04-03 16:36 UTC (permalink / raw)
  To: Julien Stephan
  Cc: Phi-bang Nguyen, Louis Kuo, Chunfeng Yun, Andy Hsieh, Vinod Koul,
	Kishon Vijay Abraham I, Rob Herring, Krzysztof Kozlowski,
	Chun-Kuang Hu, Philipp Zabel, Matthias Brugger,
	AngeloGioacchino Del Regno,
	moderated list:ARM/Mediatek USB3 PHY DRIVER,
	moderated list:ARM/Mediatek USB3 PHY DRIVER,
	open list:GENERIC PHY FRAMEWORK,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list, open list:DRM DRIVERS FOR MEDIATEK

Hi, Julien:

Julien Stephan <jstephan@baylibre.com> 於 2023年4月3日 週一 下午3:20寫道:
>
> From: Phi-bang Nguyen <pnguyen@baylibre.com>
>
> This is a new driver that supports the MIPI CSI CD-PHY for mediatek
> mt8365 soc
>
> Signed-off-by: Louis Kuo <louis.kuo@mediatek.com>
> Signed-off-by: Phi-bang Nguyen <pnguyen@baylibre.com>
> [Julien Stephan: use regmap]
> [Julien Stephan: use GENMASK]
> Co-developed-by: Julien Stephan <jstephan@baylibre.com>
> Signed-off-by: Julien Stephan <jstephan@baylibre.com>
> ---
>  .../bindings/phy/mediatek,csi-phy.yaml        |   9 +-
>  MAINTAINERS                                   |   1 +
>  drivers/phy/mediatek/Kconfig                  |   8 +
>  drivers/phy/mediatek/Makefile                 |   2 +
>  .../phy/mediatek/phy-mtk-mipi-csi-rx-reg.h    | 435 ++++++++++++++++++
>  drivers/phy/mediatek/phy-mtk-mipi-csi.c       | 392 ++++++++++++++++
>  6 files changed, 845 insertions(+), 2 deletions(-)
>  create mode 100644 drivers/phy/mediatek/phy-mtk-mipi-csi-rx-reg.h
>  create mode 100644 drivers/phy/mediatek/phy-mtk-mipi-csi.c
>

[snip]

> +
> +#define REGMAP_BIT(map, reg, field, val) \
> +       regmap_update_bits((map), reg, reg##_##field##_MASK, \
> +                          (val) << reg##_##field##_SHIFT)
> +

Use FIELD_PREP() macro  so you can drop the definition of SHIFT symbol.

Regards,
Chun-Kuang.

-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

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

* Re: [PATCH 2/2] phy: mtk-mipi-csi: add driver for CSI phy
  2023-04-03  9:51   ` Krzysztof Kozlowski
@ 2023-04-05  9:27     ` Julien Stephan
  0 siblings, 0 replies; 13+ messages in thread
From: Julien Stephan @ 2023-04-05  9:27 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Phi-bang Nguyen, Louis Kuo, Chunfeng Yun, Andy Hsieh, Vinod Koul,
	Kishon Vijay Abraham I, Rob Herring, Krzysztof Kozlowski,
	Chun-Kuang Hu, Philipp Zabel, Matthias Brugger,
	AngeloGioacchino Del Regno,
	moderated list:ARM/Mediatek USB3 PHY DRIVER,
	moderated list:ARM/Mediatek USB3 PHY DRIVER,
	open list:GENERIC PHY FRAMEWORK,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list, open list:DRM DRIVERS FOR MEDIATEK

On Mon, Apr 03, 2023 at 11:51:50AM +0200, Krzysztof Kozlowski wrote:
> On 03/04/2023 09:19, Julien Stephan wrote:
> > From: Phi-bang Nguyen <pnguyen@baylibre.com>
> >
> > This is a new driver that supports the MIPI CSI CD-PHY for mediatek
> > mt8365 soc
> >
> > Signed-off-by: Louis Kuo <louis.kuo@mediatek.com>
> > Signed-off-by: Phi-bang Nguyen <pnguyen@baylibre.com>
> > [Julien Stephan: use regmap]
> > [Julien Stephan: use GENMASK]
> > Co-developed-by: Julien Stephan <jstephan@baylibre.com>
> > Signed-off-by: Julien Stephan <jstephan@baylibre.com>
> > ---
> >  .../bindings/phy/mediatek,csi-phy.yaml        |   9 +-
> >  MAINTAINERS                                   |   1 +
> >  drivers/phy/mediatek/Kconfig                  |   8 +
> >  drivers/phy/mediatek/Makefile                 |   2 +
> >  .../phy/mediatek/phy-mtk-mipi-csi-rx-reg.h    | 435 ++++++++++++++++++
> >  drivers/phy/mediatek/phy-mtk-mipi-csi.c       | 392 ++++++++++++++++
> >  6 files changed, 845 insertions(+), 2 deletions(-)
> >  create mode 100644 drivers/phy/mediatek/phy-mtk-mipi-csi-rx-reg.h
> >  create mode 100644 drivers/phy/mediatek/phy-mtk-mipi-csi.c
> >
> > diff --git a/Documentation/devicetree/bindings/phy/mediatek,csi-phy.yaml b/Documentation/devicetree/bindings/phy/mediatek,csi-phy.yaml
> > index c026e43f35fd..ad4ba1d93a68 100644
> > --- a/Documentation/devicetree/bindings/phy/mediatek,csi-phy.yaml
> > +++ b/Documentation/devicetree/bindings/phy/mediatek,csi-phy.yaml
>
> NAK, bindings are always separate patches. It also does not make any
> sense - you just added it.
>
:( I messed up my rebase -i. This need to be moved and squashed with the
previous patch. I will fix it in v2. Thank you for reporting it

> > @@ -33,9 +33,14 @@ additionalProperties: false
> >
> >  examples:
> >    - |
> > -    phy@10011800 {
> > +    soc {
> > +      #address-cells = <2>;
> > +      #size-cells = <2>;
> > +
> > +      phy@11c10000 {
> >          compatible = "mediatek,mt8365-mipi-csi";
> > -        reg = <0 0x10011800 0 0x60>;
> > +        reg = <0 0x11c10000 0 0x4000>;
> >          #phy-cells = <1>;
> > +      };
> >      };
>
>
>
> k_mipi_dphy_of_match[] = {
> > +	{.compatible = "mediatek,mt8365-mipi-csi"},
> > +	{},
> > +};
> > +MODULE_DEVICE_TABLE(of, mtk_mipi_dphy_of_match);
> > +
> > +static struct platform_driver mipi_dphy_pdrv = {
> > +	.probe = mtk_mipi_dphy_probe,
> > +	.remove = mtk_mipi_dphy_remove,
> > +	.driver	= {
> > +		.name	= "mtk-mipi-csi",
> > +		.of_match_table = of_match_ptr(mtk_mipi_dphy_of_match),
>
> Drop of_match_ptr(). You should see W=1 warnings when compile testing.
>
I do not not see any warnings when trying to compile with W=1. Am I
missing something? I will drop it in v2 anyway

Best
Julien
>
> Best regards,
> Krzysztof
>

-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

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

* Re: [PATCH 1/2] dt-bindings: phy: add mtk-mipi-csi driver
  2023-04-03  7:19 ` [PATCH 1/2] dt-bindings: phy: add mtk-mipi-csi driver Julien Stephan
  2023-04-03  9:49   ` Krzysztof Kozlowski
  2023-04-03 13:10   ` Rob Herring
@ 2023-04-07  2:40   ` Chunfeng Yun (云春峰)
  2 siblings, 0 replies; 13+ messages in thread
From: Chunfeng Yun (云春峰) @ 2023-04-07  2:40 UTC (permalink / raw)
  To: jstephan
  Cc: linux-mediatek, robh+dt, linux-kernel, kishon, devicetree,
	Andy Hsieh (謝智皓),
	linux-arm-kernel, krzysztof.kozlowski+dt, vkoul, matthias.bgg,
	fsylvestre, linux-phy, angelogioacchino.delregno

On Mon, 2023-04-03 at 09:19 +0200, Julien Stephan wrote:
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> From: Florian Sylvestre <fsylvestre@baylibre.com>
> 
> Signed-off-by: Florian Sylvestre <fsylvestre@baylibre.com>
> Signed-off-by: Julien Stephan <jstephan@baylibre.com>
> ---
>  .../bindings/phy/mediatek,csi-phy.yaml        | 41
> +++++++++++++++++++
>  MAINTAINERS                                   |  6 +++
>  2 files changed, 47 insertions(+)
>  create mode 100644
> Documentation/devicetree/bindings/phy/mediatek,csi-phy.yaml
> 
> diff --git a/Documentation/devicetree/bindings/phy/mediatek,csi-
> phy.yaml b/Documentation/devicetree/bindings/phy/mediatek,csi-
> phy.yaml
> new file mode 100644
> index 000000000000..c026e43f35fd
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/phy/mediatek,csi-phy.yaml
> @@ -0,0 +1,41 @@
> +# SPDX-License-Identifier: (GPL-2.0-Only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: 
> https://urldefense.com/v3/__http://devicetree.org/schemas/phy/mediatek,csi-phy.yaml*__;Iw!!CTRNKA9wMg0ARbw!mTbIWKpb_vVGXYBKekejuVYU2klIR9-8QPOgiz10q0x3Z6HJDPsRfDQSCeu16k_wvfoHyXxRY0rTScjIpDTpsqc$
> +$schema: 
> https://urldefense.com/v3/__http://devicetree.org/meta-schemas/core.yaml*__;Iw!!CTRNKA9wMg0ARbw!mTbIWKpb_vVGXYBKekejuVYU2klIR9-8QPOgiz10q0x3Z6HJDPsRfDQSCeu16k_wvfoHyXxRY0rTScjIaHVQBOI$
> +
> +title: Mediatek Sensor Interface MIPI CSI CD-PHY
> +
> +maintainers:
> +  - Julien Stephan <jstephan@baylibre.com>
> +  - Andy Hsieh <andy.hsieh@mediatek.com>
> +
> +description: |
> +  The SENINF CD-PHY is a set of CD-PHY connected to the SENINF CSI-2
> +  receivers. The number of PHYs depends on the SoC model.
> +
> +properties:
> +  compatible:
> +    const: mediatek,mt8365-mipi-csi
> +
> +  reg:
> +    minItems: 1
> +
> +  '#phy-cells':
> +    const: 1
Please describe what means for each value

> +
> +required:
> +  - compatible
> +  - reg
> +  - '#phy-cells'
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    phy@10011800 {
> +        compatible = "mediatek,mt8365-mipi-csi";
> +        reg = <0 0x10011800 0 0x60>;
> +        #phy-cells = <1>;
> +    };
> +...
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 6d54f3193075..9308b4bb88bf 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -13098,6 +13098,12 @@
> F:     Documentation/devicetree/bindings/media/mediatek-vpu.txt
>  F:     drivers/media/platform/mediatek/vcodec/
>  F:     drivers/media/platform/mediatek/vpu/
> 
> +MEDIATEK MIPI-CSI CDPHY DRIVER
> +M:     Julien Stephan <jstephan@baylibre.com>
> +M:     Andy Hsieh <andy.hsieh@mediatek.com>
> +S:     Supported
> +F:     Documentation/devicetree/bindings/phy/mediatek,csi-phy.yaml
> +
>  MEDIATEK MMC/SD/SDIO DRIVER
>  M:     Chaotian Jing <chaotian.jing@mediatek.com>
>  S:     Maintained
> --
> 2.40.0
> 
-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

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

* Re: [PATCH 2/2] phy: mtk-mipi-csi: add driver for CSI phy
  2023-04-03  7:19 ` [PATCH 2/2] phy: mtk-mipi-csi: add driver for CSI phy Julien Stephan
                     ` (3 preceding siblings ...)
  2023-04-03 16:36   ` Chun-Kuang Hu
@ 2023-04-07  3:31   ` Chunfeng Yun (云春峰)
  2023-04-07  5:30   ` Chunfeng Yun (云春峰)
  5 siblings, 0 replies; 13+ messages in thread
From: Chunfeng Yun (云春峰) @ 2023-04-07  3:31 UTC (permalink / raw)
  To: jstephan
  Cc: linux-mediatek, robh+dt, linux-kernel, kishon, chunkuang.hu,
	devicetree, p.zabel, dri-devel,
	Andy Hsieh (謝智皓),
	Louis Kuo (郭德寧),
	krzysztof.kozlowski+dt, vkoul, matthias.bgg, linux-phy,
	linux-arm-kernel, angelogioacchino.delregno, pnguyen

On Mon, 2023-04-03 at 09:19 +0200, Julien Stephan wrote:
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> From: Phi-bang Nguyen <pnguyen@baylibre.com>
> 
> This is a new driver that supports the MIPI CSI CD-PHY for mediatek
> mt8365 soc
> 
> Signed-off-by: Louis Kuo <louis.kuo@mediatek.com>
> Signed-off-by: Phi-bang Nguyen <pnguyen@baylibre.com>
> [Julien Stephan: use regmap]
> [Julien Stephan: use GENMASK]
> Co-developed-by: Julien Stephan <jstephan@baylibre.com>
> Signed-off-by: Julien Stephan <jstephan@baylibre.com>
> ---
>  .../bindings/phy/mediatek,csi-phy.yaml        |   9 +-
>  MAINTAINERS                                   |   1 +
>  drivers/phy/mediatek/Kconfig                  |   8 +
>  drivers/phy/mediatek/Makefile                 |   2 +
>  .../phy/mediatek/phy-mtk-mipi-csi-rx-reg.h    | 435
> ++++++++++++++++++
>  drivers/phy/mediatek/phy-mtk-mipi-csi.c       | 392 ++++++++++++++++
>  6 files changed, 845 insertions(+), 2 deletions(-)
>  create mode 100644 drivers/phy/mediatek/phy-mtk-mipi-csi-rx-reg.h
>  create mode 100644 drivers/phy/mediatek/phy-mtk-mipi-csi.c

Please cc linux-mediatek@lists.infradead.org

> 
>  ...
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 9308b4bb88bf..b3077eddd0bf 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -13103,6 +13103,7 @@ M:      Julien Stephan <jstephan@baylibre.com
> > 
> 
>  M:     Andy Hsieh <andy.hsieh@mediatek.com>
>  S:     Supported
>  F:     Documentation/devicetree/bindings/phy/mediatek,csi-phy.yaml
> +F:     drivers/phy/mediatek/phy-mtk-mipi-csi*
> 
>  MEDIATEK MMC/SD/SDIO DRIVER
>  M:     Chaotian Jing <chaotian.jing@mediatek.com>

separate a new patch for MAINTAINERS change?


> diff --git a/drivers/phy/mediatek/Kconfig
> b/drivers/phy/mediatek/Kconfig
> index 3125ecb5d119..63fb0fa77573 100644
> --- a/drivers/phy/mediatek/Kconfig
> +++ b/drivers/phy/mediatek/Kconfig
> @@ -74,3 +74,11 @@ config PHY_MTK_DP
>         select GENERIC_PHY
>         help
>           Support DisplayPort PHY for MediaTek SoCs.
> +
> +config PHY_MTK_MIPI_CSI
> +       tristate "MediaTek CSI CD-PHY Driver"
> +       depends on ARCH_MEDIATEK && OF
> +       select GENERIC_PHY
> +       help
> +         Enable this to support the MIPI CSI CD-PHY receiver.
> +         The driver supports multiple CSI cdphy ports
> simultaneously.
> diff --git a/drivers/phy/mediatek/Makefile
> b/drivers/phy/mediatek/Makefile
> index fb1f8edaffa7..9a178c1c2628 100644
> --- a/drivers/phy/mediatek/Makefile
> +++ b/drivers/phy/mediatek/Makefile
> @@ -18,3 +18,5 @@ phy-mtk-mipi-dsi-drv-y                        :=
> phy-mtk-mipi-dsi.o
>  phy-mtk-mipi-dsi-drv-y                 += phy-mtk-mipi-dsi-mt8173.o
>  phy-mtk-mipi-dsi-drv-y                 += phy-mtk-mipi-dsi-mt8183.o
>  obj-$(CONFIG_PHY_MTK_MIPI_DSI)         += phy-mtk-mipi-dsi-drv.o
> +
> +obj-$(CONFIG_PHY_MTK_MIPI_CSI)         += phy-mtk-mipi-csi.o
> diff --git a/drivers/phy/mediatek/phy-mtk-mipi-csi-rx-reg.h
> b/drivers/phy/mediatek/phy-mtk-mipi-csi-rx-reg.h
> new file mode 100644
> index 000000000000..f360e807e3d1
> --- /dev/null
> +++ b/drivers/phy/mediatek/phy-mtk-mipi-csi-rx-reg.h
> @@ -0,0 +1,435 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +
> +#ifndef __MIPI_CDPHY_RX_REG_H__
> +#define __MIPI_CDPHY_RX_REG_H__
> +
> +/*
> + * CSI1 and CSI2 are identical, and similar to CSI0. All CSIx macros
> are
> + * applicable to the three PHYs. Where differences exist, they are
> denoted by
> + * macro names using CSI0 and CSI1, the latter being applicable to
> CSI1 and
> + * CSI2 alike.
> + */
> +
> +/*
> + * Due to lanes supporting C-PHY mode on CSI0, register fields that
> control the
> + * behaviour of lanes are named differently between CSI0 and
> CSI1/CSI2, even
> + * when they control parameters that are agnostic to the PHY mode.
> In those
> + * cases, the macros below use the CSI0 field names (e.g.
> + * MIPI_RX_ANA08_CSIxA_RG_CSIxA_L0P_T0A_HSRT_CODE_SHIFT).
> + */
> +
> <skip>
> 
> +#define
> MIPI_RX_ANA24_CSIxA_RG_CSIxA_RESERVE_SHIFT                           
>   24
> +#define
> MIPI_RX_ANA24_CSIxA_RG_CSIxA_RESERVE_MASK                            
>   (0xff << 24)

Use GENMASK()


> +
> +/* CSI0-specific register. */
> +#define
> MIPI_RX_ANA28_CSI0A                                                  
>   0x0028
> +#define
> MIPI_RX_ANA28_CSI0A_RG_CSI0A_CPHY_T0_CDR_DIRECT_EN_SHIFT             
>   0
> 
> 
> +#define
> MIPI_RX_ANA48_CSIxA_RGS_CSI1A_DPHY_L2_OS_CAL_CPLT_SHIFT              
>           5
> +#define
> MIPI_RX_ANA48_CSIxA_RGS_CSI1A_DPHY_L2_OS_CAL_CPLT_MASK               
>   BIT(5)
> +/* Common fields. */
> +#define
> MIPI_RX_ANA48_CSIxA_RGS_CSIxA_OS_CAL_CODE_SHIFT                      
>           8
> +#define
> MIPI_RX_ANA48_CSIxA_RGS_CSIxA_OS_CAL_CODE_MASK                       
>   GENMASK(15, 8)
> +
> +#define
> MIPI_RX_WRAPPER80_CSIxA                                              
>           0x0080
> +#define
> MIPI_RX_WRAPPER80_CSIxA_CSR_CSI_CLK_MON_SHIFT                        
>   0
> +#define
> MIPI_RX_WRAPPER80_CSIxA_CSR_CSI_CLK_MON_MASK                         
>   BIT(0)
> +#define
> MIPI_RX_WRAPPER80_CSIxA_CSR_CSI_CLK_EN_SHIFT                         
>   1
> +#define
> MIPI_RX_WRAPPER80_CSIxA_CSR_CSI_CLK_EN_MASK                          
>   BIT(1)
> +#define
> MIPI_RX_WRAPPER80_CSIxA_CSR_CSI_MON_MUX_SHIFT                        
>   8
> +#define
> MIPI_RX_WRAPPER80_CSIxA_CSR_CSI_MON_MUX_MASK                         
>   GENMASK(15, 8)
> +#define
> MIPI_RX_WRAPPER80_CSIxA_CSR_CSI_RST_MODE_SHIFT                       
>   16
> +#define
> MIPI_RX_WRAPPER80_CSIxA_CSR_CSI_RST_MODE_MASK                        
>   GENMASK(17, 16)
> +#define
> MIPI_RX_WRAPPER80_CSIxA_CSR_SW_RST_SHIFT                             
>   24
> +#define
> MIPI_RX_WRAPPER80_CSIxA_CSR_SW_RST_MASK                              
>           GENMASK(27, 24)
> +
> +#define
> MIPI_RX_WRAPPER84_CSIxA                                              
>           0x0084
> +#define
> MIPI_RX_WRAPPER84_CSIxA_CSI_DEBUG_OUT_SHIFT                          
>   0
> +#define
> MIPI_RX_WRAPPER84_CSIxA_CSI_DEBUG_OUT_MASK                           
>   GENMASK(31, 0)
> +
> +#define
> MIPI_RX_WRAPPER88_CSIxA                                              
>           0x0088
> +#define
> MIPI_RX_WRAPPER88_CSIxA_CSR_SW_MODE_0_SHIFT                          
>   0
> +#define
> MIPI_RX_WRAPPER88_CSIxA_CSR_SW_MODE_0_MASK                           
>   GENMASK(31, 0)
> +
> +#define
> MIPI_RX_WRAPPER8C_CSIxA                                              
>           0x008c
> +#define
> MIPI_RX_WRAPPER8C_CSIxA_CSR_SW_MODE_1_SHIFT                          
>   0
> +#define
> MIPI_RX_WRAPPER8C_CSIxA_CSR_SW_MODE_1_MASK                           
>   GENMASK(31, 0)
> +
> +#define
> MIPI_RX_WRAPPER90_CSIxA                                              
>           0x0090
> +#define
> MIPI_RX_WRAPPER90_CSIxA_CSR_SW_MODE_2_SHIFT                          
>   0
> +#define
> MIPI_RX_WRAPPER90_CSIxA_CSR_SW_MODE_2_MASK                           
>   GENMASK(31, 0)
> +
> +#define
> MIPI_RX_WRAPPER94_CSIxA                                              
>           0x0094
> +#define
> MIPI_RX_WRAPPER94_CSIxA_CSR_SW_VALUE_0_SHIFT                         
>   0
> +#define
> MIPI_RX_WRAPPER94_CSIxA_CSR_SW_VALUE_0_MASK                          
>   GENMASK(31, 0)
> +
> +#define
> MIPI_RX_WRAPPER98_CSIxA                                              
>           0x0098
> +#define
> MIPI_RX_WRAPPER98_CSIxA_CSR_SW_VALUE_1_SHIFT                         
>   0
> +#define
> MIPI_RX_WRAPPER98_CSIxA_CSR_SW_VALUE_1_MASK                          
>   GENMASK(31, 0)
> +
> +#define
> MIPI_RX_WRAPPER9C_CSIxA                                              
>           0x009c
> +#define
> MIPI_RX_WRAPPER9C_CSIxA_CSR_SW_VALUE_2_SHIFT                         
>   0
> +#define
> MIPI_RX_WRAPPER9C_CSIxA_CSR_SW_VALUE_2_MASK                          
>   GENMASK(31, 0)
> +
> +#define
> MIPI_RX_ANAA4_CSIxA                                                  
>   0x00a4
> +#define
> MIPI_RX_ANAA4_CSIxA_RG_CSIxA_CDPHY_L0_T0_SYNC_INIT_SEL_SHIFT         
>   0
> +#define
> MIPI_RX_ANAA4_CSIxA_RG_CSIxA_CDPHY_L0_T0_SYNC_INIT_SEL_MASK          
>   BIT(0)
> +#define
> MIPI_RX_ANAA4_CSIxA_RG_CSIxA_CDPHY_L0_T0_FORCE_INIT_SHIFT            
>   1
> +#define
> MIPI_RX_ANAA4_CSIxA_RG_CSIxA_CDPHY_L0_T0_FORCE_INIT_MASK             
>   BIT(1)
> +#define
> MIPI_RX_ANAA4_CSIxA_RG_CSIxA_DPHY_L1_SYNC_INIT_SEL_SHIFT             
>   2
> +#define
> MIPI_RX_ANAA4_CSIxA_RG_CSIxA_DPHY_L1_SYNC_INIT_SEL_MASK              
>           BIT(2)
> +#define
> MIPI_RX_ANAA4_CSIxA_RG_CSIxA_DPHY_L1_FORCE_INIT_SHIFT                
>   3
> +#define
> MIPI_RX_ANAA4_CSIxA_RG_CSIxA_DPHY_L1_FORCE_INIT_MASK                 
>   BIT(3)
> +#define
> MIPI_RX_ANAA4_CSIxA_RG_CSIxA_CDPHY_L2_T2_SYNC_INIT_SEL_SHIFT         
>   4
> +#define
> MIPI_RX_ANAA4_CSIxA_RG_CSIxA_CDPHY_L2_T2_SYNC_INIT_SEL_MASK          
>   BIT(4)
> +#define
> MIPI_RX_ANAA4_CSIxA_RG_CSIxA_CDPHY_L2_T2_FORCE_INIT_SHIFT            
>   5
> +#define
> MIPI_RX_ANAA4_CSIxA_RG_CSIxA_CDPHY_L2_T2_FORCE_INIT_MASK             
>   BIT(5)
> +
> +#define
> MIPI_RX_ANAA8_CSIxA                                                  
>   0x00a8
> +#define
> MIPI_RX_ANAA8_CSIxA_RG_CSIxA_CDPHY_L0_T0_BYTECK_INVERT_SHIFT         
>   0
> +#define
> MIPI_RX_ANAA8_CSIxA_RG_CSIxA_CDPHY_L0_T0_BYTECK_INVERT_MASK          
>   BIT(0)
> +#define
> MIPI_RX_ANAA8_CSIxA_RG_CSIxA_DPHY_L1_BYTECK_INVERT_SHIFT             
>   1
> +#define
> MIPI_RX_ANAA8_CSIxA_RG_CSIxA_DPHY_L1_BYTECK_INVERT_MASK              
>           BIT(1)
> +#define
> MIPI_RX_ANAA8_CSIxA_RG_CSIxA_CDPHY_L2_T1_BYTECK_INVERT_SHIFT         
>   2
> +#define
> MIPI_RX_ANAA8_CSIxA_RG_CSIxA_CDPHY_L2_T1_BYTECK_INVERT_MASK          
>   BIT(2)
> +#define
> MIPI_RX_ANAA8_CSIxA_RG_CSIxA_DPHY_HSDET_LEVEL_MODE_EN_SHIFT          
>   3
> +#define
> MIPI_RX_ANAA8_CSIxA_RG_CSIxA_DPHY_HSDET_LEVEL_MODE_EN_MASK           
>   BIT(3)
> +#define
> MIPI_RX_ANAA8_CSIxA_RG_CSIxA_OS_CAL_SEL_SHIFT                        
>   4
> +#define
> MIPI_RX_ANAA8_CSIxA_RG_CSIxA_OS_CAL_SEL_MASK                         
>   GENMASK(6, 4)
> +#define
> MIPI_RX_ANAA8_CSIxA_RG_CSIxA_DPHY_HSDET_DIG_BACK_EN_SHIFT            
>   7
> +#define
> MIPI_RX_ANAA8_CSIxA_RG_CSIxA_DPHY_HSDET_DIG_BACK_EN_MASK             
>   BIT(7)
> +#define
> MIPI_RX_ANAA8_CSIxA_RG_CSIxA_CDPHY_DELAYCAL_CK_SEL_SHIFT             
>   8
> +#define
> MIPI_RX_ANAA8_CSIxA_RG_CSIxA_CDPHY_DELAYCAL_CK_SEL_MASK              
>           GENMASK(10, 8)
> +#define
> MIPI_RX_ANAA8_CSIxA_RG_CSIxA_OS_CAL_DIV_SHIFT                        
>   11
> +#define
> MIPI_RX_ANAA8_CSIxA_RG_CSIxA_OS_CAL_DIV_MASK                         
>   GENMASK(12, 11)
> +
> +#endif
> diff --git a/drivers/phy/mediatek/phy-mtk-mipi-csi.c
> b/drivers/phy/mediatek/phy-mtk-mipi-csi.c
> new file mode 100644
> index 000000000000..6ce3f95f57bd
> --- /dev/null
> +++ b/drivers/phy/mediatek/phy-mtk-mipi-csi.c
> @@ -0,0 +1,392 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#include <linux/delay.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/phy/phy.h>
> +#include <linux/platform_device.h>
> +#include <linux/slab.h>
> +#include <linux/regmap.h>
> +
> +#include "phy-mtk-mipi-csi-rx-reg.h"
> +
> +#define CSIxB_OFFSET           0x1000
> +
> +struct mtk_mipi_dphy;
> +
> +enum mtk_mipi_dphy_port_id {
> +       MTK_MIPI_PHY_PORT_0 = 0x0, /* 4D1C - CDPHY */
> +       MTK_MIPI_PHY_PORT_1, /* 4D1C - DPHY */
> +       MTK_MIPI_PHY_PORT_2, /* 4D1C - DPHY */
> +       MTK_MIPI_PHY_PORT_0A, /* 2D1C - CDPHY */
> +       MTK_MIPI_PHY_PORT_0B, /* 2D1C - CDPHY */
> +       MTK_MIPI_PHY_PORT_MAX_NUM
> +};
> +
> +struct mtk_mipi_dphy_port {
> +       struct mtk_mipi_dphy *dev;
> +       enum mtk_mipi_dphy_port_id id;
> +       struct regmap *regmap_base;
> +       struct regmap *regmap_4d1c;

Could you avoid using regmap if the registers are only used by this
driver, use phy-mtk-io.h api instead.

> +       struct phy *phy;
> +       bool active;
> +       bool is_cdphy;
> +       bool is_4d1c;
> +};
> +
> +struct mtk_mipi_dphy {
> +       struct device *dev;
> +       void __iomem *rx;
> +       struct mtk_mipi_dphy_port ports[MTK_MIPI_PHY_PORT_MAX_NUM];
> +       struct mutex lock; /* Ports CSI0 and CSI0A/B are mutually
> exclusive */

phy core already provides a mutex, no need provide another one.

Do you switch them at runtime for port 0?

From binding, I guess we use mtk_mipi_dphy_port_id in DTS to determine
which mode is used.

> +};
> +
> +#define REGMAP_BIT(map, reg, field, val) \
> +       regmap_update_bits((map), reg, reg##_##field##_MASK, \
> +                          (val) << reg##_##field##_SHIFT)
> +
> +static int mtk_mipi_phy_power_on(struct phy *phy)
> +{
> +       struct mtk_mipi_dphy_port *port = phy_get_drvdata(phy);
> +       struct mtk_mipi_dphy *priv = port->dev;
> +       struct regmap *regmap_base = port->regmap_base;
> +       struct regmap *regmap_4d1c = port->regmap_4d1c;
> +       int ret = 0;
> +
> +       mutex_lock(&priv->lock);
> +
> +       switch (port->id) {
> +       case MTK_MIPI_PHY_PORT_0:
> +               if (priv->ports[MTK_MIPI_PHY_PORT_0A].active ||
> +                   priv->ports[MTK_MIPI_PHY_PORT_0B].active)
> +                       ret = -EBUSY;
> +               break;
> +
> +       case MTK_MIPI_PHY_PORT_0A:
> +       case MTK_MIPI_PHY_PORT_0B:
> +               if (priv->ports[MTK_MIPI_PHY_PORT_0].active)
> +                       ret = -EBUSY;
> +               break;
> +       }
> +
> +       if (!ret)
> +               port->active = true;
> +
> +       mutex_unlock(&priv->lock);
> +
> +       if (ret < 0)
> +               return ret;
> +
> +       /* Set analog phy mode to DPHY */
> +       if (port->is_cdphy)
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSI0A_CPHY_EN, 0);
> +
> +       if (port->is_4d1c) {
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L0_CKMODE_EN, 0);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L0_CKSEL, 1);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L1_CKMODE_EN, 0);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L1_CKSEL, 1);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L2_CKMODE_EN, 1);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L2_CKSEL, 1);
> +       } else {
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L0_CKMODE_EN, 0);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L0_CKSEL, 0);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L1_CKMODE_EN, 1);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L1_CKSEL, 0);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L2_CKMODE_EN, 0);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L2_CKSEL, 0);
> +       }
> +
> +       if (port->is_4d1c) {
> +               if (port->is_cdphy)
> +                       REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA00_CSIxA,
> +                                  RG_CSI0A_CPHY_EN, 0);
> +
> +               REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L0_CKMODE_EN, 0);
> +               REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L0_CKSEL, 1);
> +               REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L1_CKMODE_EN, 0);
> +               REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L1_CKSEL, 1);
> +               REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L2_CKMODE_EN, 0);
> +               REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L2_CKSEL, 1);
> +       }
> +
> +       /* Byte clock invert */
> +       REGMAP_BIT(regmap_base, MIPI_RX_ANAA8_CSIxA,
> +                  RG_CSIxA_CDPHY_L0_T0_BYTECK_INVERT, 1);
> +       REGMAP_BIT(regmap_base, MIPI_RX_ANAA8_CSIxA,
> +                  RG_CSIxA_DPHY_L1_BYTECK_INVERT, 1);
> +       REGMAP_BIT(regmap_base, MIPI_RX_ANAA8_CSIxA,
> +                  RG_CSIxA_CDPHY_L2_T1_BYTECK_INVERT, 1);
> +
> +       if (port->is_4d1c) {
> +               REGMAP_BIT(regmap_4d1c, MIPI_RX_ANAA8_CSIxA,
> +                          RG_CSIxA_CDPHY_L0_T0_BYTECK_INVERT, 1);
> +               REGMAP_BIT(regmap_4d1c, MIPI_RX_ANAA8_CSIxA,
> +                          RG_CSIxA_DPHY_L1_BYTECK_INVERT, 1);
> +               REGMAP_BIT(regmap_4d1c, MIPI_RX_ANAA8_CSIxA,
> +                          RG_CSIxA_CDPHY_L2_T1_BYTECK_INVERT, 1);
> +       }
> +
> +       /* Start ANA EQ tuning */
> +       if (port->is_cdphy) {
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA18_CSIxA,
> +                          RG_CSI0A_L0_T0AB_EQ_IS, 1);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA18_CSIxA,
> +                          RG_CSI0A_L0_T0AB_EQ_BW, 1);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA1C_CSIxA,
> +                          RG_CSI0A_L1_T1AB_EQ_IS, 1);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA1C_CSIxA,
> +                          RG_CSI0A_L1_T1AB_EQ_BW, 1);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA20_CSI0A,
> +                          RG_CSI0A_L2_T1BC_EQ_IS, 1);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA20_CSI0A,
> +                          RG_CSI0A_L2_T1BC_EQ_BW, 1);
> +
> +               if (port->is_4d1c) {
> +                       REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA18_CSIxA,
> +                                  RG_CSI0A_L0_T0AB_EQ_IS, 1);
> +                       REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA18_CSIxA,
> +                                  RG_CSI0A_L0_T0AB_EQ_BW, 1);
> +                       REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA1C_CSIxA,
> +                                  RG_CSI0A_L1_T1AB_EQ_IS, 1);
> +                       REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA1C_CSIxA,
> +                                  RG_CSI0A_L1_T1AB_EQ_BW, 1);
> +                       REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA20_CSI0A,
> +                                  RG_CSI0A_L2_T1BC_EQ_IS, 1);
> +                       REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA20_CSI0A,
> +                                  RG_CSI0A_L2_T1BC_EQ_BW, 1);
> +               }
> +       } else {
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA18_CSIxA,
> +                          RG_CSI1A_L0_EQ_IS, 1);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA18_CSIxA,
> +                          RG_CSI1A_L0_EQ_BW, 1);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA18_CSIxA,
> +                          RG_CSI1A_L1_EQ_IS, 1);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA18_CSIxA,
> +                          RG_CSI1A_L1_EQ_BW, 1);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA1C_CSIxA,
> +                          RG_CSI1A_L2_EQ_IS, 1);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA1C_CSIxA,
> +                          RG_CSI1A_L2_EQ_BW, 1);
> +
> +               if (port->is_4d1c) {
> +                       REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA18_CSIxA,
> +                                  RG_CSI1A_L0_EQ_IS, 1);
> +                       REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA18_CSIxA,
> +                                  RG_CSI1A_L0_EQ_BW, 1);
> +                       REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA18_CSIxA,
> +                                  RG_CSI1A_L1_EQ_IS, 1);
> +                       REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA18_CSIxA,
> +                                  RG_CSI1A_L1_EQ_BW, 1);
> +                       REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA1C_CSIxA,
> +                                  RG_CSI1A_L2_EQ_IS, 1);
> +                       REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA1C_CSIxA,
> +                                  RG_CSI1A_L2_EQ_BW, 1);
> +               }
> +       }
> +
> +       /* End ANA EQ tuning */
> +       regmap_write(regmap_base, MIPI_RX_ANA40_CSIxA, 0x90);
> +
> +       REGMAP_BIT(regmap_base, MIPI_RX_ANA24_CSIxA,
> +                  RG_CSIxA_RESERVE, 0x40);
> +       if (port->is_4d1c)
> +               REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA24_CSIxA,
> +                          RG_CSIxA_RESERVE, 0x40);
> +       REGMAP_BIT(regmap_base, MIPI_RX_WRAPPER80_CSIxA,
> +                  CSR_CSI_RST_MODE, 0);
> +       if (port->is_4d1c)
> +               REGMAP_BIT(regmap_4d1c, MIPI_RX_WRAPPER80_CSIxA,
> +                          CSR_CSI_RST_MODE, 0);
> +       /* ANA power on */
> +       REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                  RG_CSIxA_BG_CORE_EN, 1);
> +       if (port->is_4d1c)
> +               REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_BG_CORE_EN, 1);
> +       usleep_range(20, 40);
> +       REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                  RG_CSIxA_BG_LPF_EN, 1);
> +       if (port->is_4d1c)
> +               REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_BG_LPF_EN, 1);
> +
> +       return 0;
> +}
> +
> +static int mtk_mipi_phy_power_off(struct phy *phy)
> +{
> +       struct mtk_mipi_dphy_port *port = phy_get_drvdata(phy);
> +       struct regmap *regmap_base = port->regmap_base;
> +       struct regmap *regmap_4d1c = port->regmap_4d1c;
> +
> +       /* Disable MIPI BG. */
> +       REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                  RG_CSIxA_BG_CORE_EN, 0);
> +       REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                  RG_CSIxA_BG_LPF_EN, 0);
> +
> +       if (port->is_4d1c) {
> +               REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_BG_CORE_EN, 0);
> +               REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_BG_LPF_EN, 0);
> +       }
> +
> +       mutex_lock(&port->dev->lock);
> +       port->active = false;
> +       mutex_unlock(&port->dev->lock);
> +
> +       return 0;
> +}
> +
> +static const struct phy_ops mtk_dphy_ops = {
> +       .power_on       = mtk_mipi_phy_power_on,
> +       .power_off      = mtk_mipi_phy_power_off,
> +       .owner          = THIS_MODULE,
> +};
> +
> +static struct phy *mtk_mipi_dphy_xlate(struct device *dev,
> +                                      struct of_phandle_args *args)
> +{
> +       struct mtk_mipi_dphy *priv = dev_get_drvdata(dev);
> +
> +       if (args->args_count != 1)
> +               return ERR_PTR(-EINVAL);
> +
> +       if (args->args[0] >= ARRAY_SIZE(priv->ports))
> +               return ERR_PTR(-ENODEV);
> +
> +       return priv->ports[args->args[0]].phy;
> +}
> +
> +static const struct regmap_config mt8365_phy_regmap_config = {
> +       .reg_bits = 32,
> +       .val_bits = 32,
> +       .reg_stride = 4,
> +       .max_register = 0x700,
> +};
> +
> +static int mtk_mipi_dphy_probe(struct platform_device *pdev)
> +{
> +       static const unsigned int ports_offsets[] = {
> +               [MTK_MIPI_PHY_PORT_0] = 0,
> +               [MTK_MIPI_PHY_PORT_0A] = 0,
> +               [MTK_MIPI_PHY_PORT_0B] = 0x1000,
> +               [MTK_MIPI_PHY_PORT_1] = 0x2000,
> +               [MTK_MIPI_PHY_PORT_2] = 0x4000,
> +       };

How about provide three subnode (p0/p1/p2)in dts like as tphy driver?

for the port 0, it works as three mode (*_0/0A/0B, or 4d1c/2d1c), we
can distinguish it from phy arguments, also the same for port 1/2

> +
> +       struct device *dev = &pdev->dev;
> +       struct phy_provider *phy_provider;
> +       struct mtk_mipi_dphy *priv;
> +       struct resource *res;
> +       unsigned int i;
> +
> +       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> +       if (!priv)
> +               return -ENOMEM;
> +
> +       dev_set_drvdata(dev, priv);
> +       priv->dev = dev;
> +
> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +       priv->rx = devm_ioremap_resource(dev, res);

use devm_platform_ioremap_resource()

> +       if (IS_ERR(priv->rx))
> +               return PTR_ERR(priv->rx);
> +
> +       for (i = 0; i < ARRAY_SIZE(priv->ports); ++i) {
> +               struct mtk_mipi_dphy_port *port = &priv->ports[i];
> +               struct phy *phy;
> +               void __iomem *base;
> +
> +               port->dev = priv;
> +               port->id = i;
> +               base = priv->rx + ports_offsets[i];
> +
> +               port->regmap_base = devm_regmap_init_mmio(port->dev-
> > dev,
> 
> +                                                         base,
> +                                                         &mt8365_phy
> _regmap_config);
> +
> +               port->is_cdphy = i == MTK_MIPI_PHY_PORT_0A ||
> +                                i == MTK_MIPI_PHY_PORT_0B ||
> +                                i == MTK_MIPI_PHY_PORT_0;
> +               port->is_4d1c = i < MTK_MIPI_PHY_PORT_0A;
> +
> +               if (port->is_4d1c)
> +                       port->regmap_4d1c =
> devm_regmap_init_mmio(port->dev->dev,
> +                                                                 bas
> e + CSIxB_OFFSET,
> +                                                                 &mt
> 8365_phy_regmap_config);
> +
> +               phy = devm_phy_create(dev, NULL, &mtk_dphy_ops);
> +               if (IS_ERR(phy)) {
> +                       dev_err(dev, "Failed to create PHY: %ld\n",
> PTR_ERR(phy));
> +                       return PTR_ERR(phy);
> +               }
> +
> +               port->phy = phy;
> +               phy_set_drvdata(phy, port);
> +       }
> +
> +       phy_provider = devm_of_phy_provider_register(dev,
> mtk_mipi_dphy_xlate);
> +       if (IS_ERR(phy_provider)) {
> +               dev_err(dev, "Failed to register PHY provider:
> %ld\n",
> +                       PTR_ERR(phy_provider));
> +               return PTR_ERR(phy_provider);
> +       }
> +
> +       mutex_init(&priv->lock);
> +
> +       return 0;
> +}
> +
> +static int mtk_mipi_dphy_remove(struct platform_device *pdev)
> +{
> +       struct mtk_mipi_dphy *priv = platform_get_drvdata(pdev);
> +
> +       mutex_destroy(&priv->lock);
> +
> +       return 0;
> +}
> +
> +static const struct of_device_id mtk_mipi_dphy_of_match[] = {
> +       {.compatible = "mediatek,mt8365-mipi-csi"},

prefer to provide a generic compatible if not a specific controller
only for mt8365.

Thanks a lot
> +       {},
> +};
> +MODULE_DEVICE_TABLE(of, mtk_mipi_dphy_of_match);


> +
> +static struct platform_driver mipi_dphy_pdrv = {
> +       .probe = mtk_mipi_dphy_probe,
> +       .remove = mtk_mipi_dphy_remove,
> +       .driver = {
> +               .name   = "mtk-mipi-csi",
> +               .of_match_table =
> of_match_ptr(mtk_mipi_dphy_of_match),
> +       },
> +};
> +
> +module_platform_driver(mipi_dphy_pdrv);
> +
> +MODULE_DESCRIPTION("MTK mipi csi cdphy driver");
> +MODULE_AUTHOR("Louis Kuo <louis.kuo@mediatek.com>");
> +MODULE_LICENSE("GPL");
> --
> 2.40.0
> 
-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

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

* Re: [PATCH 2/2] phy: mtk-mipi-csi: add driver for CSI phy
  2023-04-03  7:19 ` [PATCH 2/2] phy: mtk-mipi-csi: add driver for CSI phy Julien Stephan
                     ` (4 preceding siblings ...)
  2023-04-07  3:31   ` Chunfeng Yun (云春峰)
@ 2023-04-07  5:30   ` Chunfeng Yun (云春峰)
  5 siblings, 0 replies; 13+ messages in thread
From: Chunfeng Yun (云春峰) @ 2023-04-07  5:30 UTC (permalink / raw)
  To: jstephan
  Cc: linux-mediatek, robh+dt, linux-kernel, kishon, chunkuang.hu,
	devicetree, p.zabel, dri-devel,
	Andy Hsieh (謝智皓),
	Louis Kuo (郭德寧),
	krzysztof.kozlowski+dt, vkoul, matthias.bgg, linux-phy,
	linux-arm-kernel, angelogioacchino.delregno, pnguyen

On Mon, 2023-04-03 at 09:19 +0200, Julien Stephan wrote:
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> From: Phi-bang Nguyen <pnguyen@baylibre.com>
> 
> This is a new driver that supports the MIPI CSI CD-PHY for mediatek
> mt8365 soc
> 
> Signed-off-by: Louis Kuo <louis.kuo@mediatek.com>
> Signed-off-by: Phi-bang Nguyen <pnguyen@baylibre.com>
> [Julien Stephan: use regmap]
> [Julien Stephan: use GENMASK]
> Co-developed-by: Julien Stephan <jstephan@baylibre.com>
> Signed-off-by: Julien Stephan <jstephan@baylibre.com>
> ---
>  .../bindings/phy/mediatek,csi-phy.yaml        |   9 +-
>  MAINTAINERS                                   |   1 +
>  drivers/phy/mediatek/Kconfig                  |   8 +
>  drivers/phy/mediatek/Makefile                 |   2 +
>  .../phy/mediatek/phy-mtk-mipi-csi-rx-reg.h    | 435
> ++++++++++++++++++
>  drivers/phy/mediatek/phy-mtk-mipi-csi.c       | 392 ++++++++++++++++
>  6 files changed, 845 insertions(+), 2 deletions(-)
>  create mode 100644 drivers/phy/mediatek/phy-mtk-mipi-csi-rx-reg.h
>  create mode 100644 drivers/phy/mediatek/phy-mtk-mipi-csi.c

Please cc linux-mediatek@lists.infradead.org

> 
>  ...
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 9308b4bb88bf..b3077eddd0bf 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -13103,6 +13103,7 @@ M:      Julien Stephan <jstephan@baylibre.com
> >
>  M:     Andy Hsieh <andy.hsieh@mediatek.com>
>  S:     Supported
>  F:     Documentation/devicetree/bindings/phy/mediatek,csi-phy.yaml
> +F:     drivers/phy/mediatek/phy-mtk-mipi-csi*
> 
>  MEDIATEK MMC/SD/SDIO DRIVER
>  M:     Chaotian Jing <chaotian.jing@mediatek.com>

separate a new patch for MAINTAINERS change?


> diff --git a/drivers/phy/mediatek/Kconfig
> b/drivers/phy/mediatek/Kconfig
> index 3125ecb5d119..63fb0fa77573 100644
> --- a/drivers/phy/mediatek/Kconfig
> +++ b/drivers/phy/mediatek/Kconfig
> @@ -74,3 +74,11 @@ config PHY_MTK_DP
>         select GENERIC_PHY
>         help
>           Support DisplayPort PHY for MediaTek SoCs.
> +
> +config PHY_MTK_MIPI_CSI
> +       tristate "MediaTek CSI CD-PHY Driver"
> +       depends on ARCH_MEDIATEK && OF
> +       select GENERIC_PHY
> +       help
> +         Enable this to support the MIPI CSI CD-PHY receiver.
> +         The driver supports multiple CSI cdphy ports
> simultaneously.
> diff --git a/drivers/phy/mediatek/Makefile
> b/drivers/phy/mediatek/Makefile
> index fb1f8edaffa7..9a178c1c2628 100644
> --- a/drivers/phy/mediatek/Makefile
> +++ b/drivers/phy/mediatek/Makefile
> @@ -18,3 +18,5 @@ phy-mtk-mipi-dsi-drv-y                        :=
> phy-mtk-mipi-dsi.o
>  phy-mtk-mipi-dsi-drv-y                 += phy-mtk-mipi-dsi-mt8173.o
>  phy-mtk-mipi-dsi-drv-y                 += phy-mtk-mipi-dsi-mt8183.o
>  obj-$(CONFIG_PHY_MTK_MIPI_DSI)         += phy-mtk-mipi-dsi-drv.o
> +
> +obj-$(CONFIG_PHY_MTK_MIPI_CSI)         += phy-mtk-mipi-csi.o
> diff --git a/drivers/phy/mediatek/phy-mtk-mipi-csi-rx-reg.h
> b/drivers/phy/mediatek/phy-mtk-mipi-csi-rx-reg.h
> new file mode 100644
> index 000000000000..f360e807e3d1
> --- /dev/null
> +++ b/drivers/phy/mediatek/phy-mtk-mipi-csi-rx-reg.h
> @@ -0,0 +1,435 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +
> +#ifndef __MIPI_CDPHY_RX_REG_H__
> +#define __MIPI_CDPHY_RX_REG_H__
> +
> +/*
> + * CSI1 and CSI2 are identical, and similar to CSI0. All CSIx macros
> are
> + * applicable to the three PHYs. Where differences exist, they are
> denoted by
> + * macro names using CSI0 and CSI1, the latter being applicable to
> CSI1 and
> + * CSI2 alike.
> + */
> +
> +/*
> + * Due to lanes supporting C-PHY mode on CSI0, register fields that
> control the
> + * behaviour of lanes are named differently between CSI0 and
> CSI1/CSI2, even
> + * when they control parameters that are agnostic to the PHY mode.
> In those
> + * cases, the macros below use the CSI0 field names (e.g.
> + * MIPI_RX_ANA08_CSIxA_RG_CSIxA_L0P_T0A_HSRT_CODE_SHIFT).
> + */
> +
> <skip>
> 
> +#define
> MIPI_RX_ANA24_CSIxA_RG_CSIxA_RESERVE_SHIFT                           
>   24
> +#define
> MIPI_RX_ANA24_CSIxA_RG_CSIxA_RESERVE_MASK                            
>   (0xff << 24)

Use GENMASK()


> +
> +/* CSI0-specific register. */
> +#define
> MIPI_RX_ANA28_CSI0A                                                  
>   0x0028
> +#define
> MIPI_RX_ANA28_CSI0A_RG_CSI0A_CPHY_T0_CDR_DIRECT_EN_SHIFT             
>   0
> 
> 
> +#define
> MIPI_RX_ANA48_CSIxA_RGS_CSI1A_DPHY_L2_OS_CAL_CPLT_SHIFT              
>           5
> +#define
> MIPI_RX_ANA48_CSIxA_RGS_CSI1A_DPHY_L2_OS_CAL_CPLT_MASK               
>   BIT(5)
> +/* Common fields. */
> +#define
> MIPI_RX_ANA48_CSIxA_RGS_CSIxA_OS_CAL_CODE_SHIFT                      
>           8
> +#define
> MIPI_RX_ANA48_CSIxA_RGS_CSIxA_OS_CAL_CODE_MASK                       
>   GENMASK(15, 8)
> +
> +#define
> MIPI_RX_WRAPPER80_CSIxA                                              
>           0x0080
> +#define
> MIPI_RX_WRAPPER80_CSIxA_CSR_CSI_CLK_MON_SHIFT                        
>   0
> +#define
> MIPI_RX_WRAPPER80_CSIxA_CSR_CSI_CLK_MON_MASK                         
>   BIT(0)
> +#define
> MIPI_RX_WRAPPER80_CSIxA_CSR_CSI_CLK_EN_SHIFT                         
>   1
> +#define
> MIPI_RX_WRAPPER80_CSIxA_CSR_CSI_CLK_EN_MASK                          
>   BIT(1)
> +#define
> MIPI_RX_WRAPPER80_CSIxA_CSR_CSI_MON_MUX_SHIFT                        
>   8
> +#define
> MIPI_RX_WRAPPER80_CSIxA_CSR_CSI_MON_MUX_MASK                         
>   GENMASK(15, 8)
> +#define
> MIPI_RX_WRAPPER80_CSIxA_CSR_CSI_RST_MODE_SHIFT                       
>   16
> +#define
> MIPI_RX_WRAPPER80_CSIxA_CSR_CSI_RST_MODE_MASK                        
>   GENMASK(17, 16)
> +#define
> MIPI_RX_WRAPPER80_CSIxA_CSR_SW_RST_SHIFT                             
>   24
> +#define
> MIPI_RX_WRAPPER80_CSIxA_CSR_SW_RST_MASK                              
>           GENMASK(27, 24)
> +
> +#define
> MIPI_RX_WRAPPER84_CSIxA                                              
>           0x0084
> +#define
> MIPI_RX_WRAPPER84_CSIxA_CSI_DEBUG_OUT_SHIFT                          
>   0
> +#define
> MIPI_RX_WRAPPER84_CSIxA_CSI_DEBUG_OUT_MASK                           
>   GENMASK(31, 0)
> +
> +#define
> MIPI_RX_WRAPPER88_CSIxA                                              
>           0x0088
> +#define
> MIPI_RX_WRAPPER88_CSIxA_CSR_SW_MODE_0_SHIFT                          
>   0
> +#define
> MIPI_RX_WRAPPER88_CSIxA_CSR_SW_MODE_0_MASK                           
>   GENMASK(31, 0)
> +
> +#define
> MIPI_RX_WRAPPER8C_CSIxA                                              
>           0x008c
> +#define
> MIPI_RX_WRAPPER8C_CSIxA_CSR_SW_MODE_1_SHIFT                          
>   0
> +#define
> MIPI_RX_WRAPPER8C_CSIxA_CSR_SW_MODE_1_MASK                           
>   GENMASK(31, 0)
> +
> +#define
> MIPI_RX_WRAPPER90_CSIxA                                              
>           0x0090
> +#define
> MIPI_RX_WRAPPER90_CSIxA_CSR_SW_MODE_2_SHIFT                          
>   0
> +#define
> MIPI_RX_WRAPPER90_CSIxA_CSR_SW_MODE_2_MASK                           
>   GENMASK(31, 0)
> +
> +#define
> MIPI_RX_WRAPPER94_CSIxA                                              
>           0x0094
> +#define
> MIPI_RX_WRAPPER94_CSIxA_CSR_SW_VALUE_0_SHIFT                         
>   0
> +#define
> MIPI_RX_WRAPPER94_CSIxA_CSR_SW_VALUE_0_MASK                          
>   GENMASK(31, 0)
> +
> +#define
> MIPI_RX_WRAPPER98_CSIxA                                              
>           0x0098
> +#define
> MIPI_RX_WRAPPER98_CSIxA_CSR_SW_VALUE_1_SHIFT                         
>   0
> +#define
> MIPI_RX_WRAPPER98_CSIxA_CSR_SW_VALUE_1_MASK                          
>   GENMASK(31, 0)
> +
> +#define
> MIPI_RX_WRAPPER9C_CSIxA                                              
>           0x009c
> +#define
> MIPI_RX_WRAPPER9C_CSIxA_CSR_SW_VALUE_2_SHIFT                         
>   0
> +#define
> MIPI_RX_WRAPPER9C_CSIxA_CSR_SW_VALUE_2_MASK                          
>   GENMASK(31, 0)
> +
> +#define
> MIPI_RX_ANAA4_CSIxA                                                  
>   0x00a4
> +#define
> MIPI_RX_ANAA4_CSIxA_RG_CSIxA_CDPHY_L0_T0_SYNC_INIT_SEL_SHIFT         
>   0
> +#define
> MIPI_RX_ANAA4_CSIxA_RG_CSIxA_CDPHY_L0_T0_SYNC_INIT_SEL_MASK          
>   BIT(0)
> +#define
> MIPI_RX_ANAA4_CSIxA_RG_CSIxA_CDPHY_L0_T0_FORCE_INIT_SHIFT            
>   1
> +#define
> MIPI_RX_ANAA4_CSIxA_RG_CSIxA_CDPHY_L0_T0_FORCE_INIT_MASK             
>   BIT(1)
> +#define
> MIPI_RX_ANAA4_CSIxA_RG_CSIxA_DPHY_L1_SYNC_INIT_SEL_SHIFT             
>   2
> +#define
> MIPI_RX_ANAA4_CSIxA_RG_CSIxA_DPHY_L1_SYNC_INIT_SEL_MASK              
>           BIT(2)
> +#define
> MIPI_RX_ANAA4_CSIxA_RG_CSIxA_DPHY_L1_FORCE_INIT_SHIFT                
>   3
> +#define
> MIPI_RX_ANAA4_CSIxA_RG_CSIxA_DPHY_L1_FORCE_INIT_MASK                 
>   BIT(3)
> +#define
> MIPI_RX_ANAA4_CSIxA_RG_CSIxA_CDPHY_L2_T2_SYNC_INIT_SEL_SHIFT         
>   4
> +#define
> MIPI_RX_ANAA4_CSIxA_RG_CSIxA_CDPHY_L2_T2_SYNC_INIT_SEL_MASK          
>   BIT(4)
> +#define
> MIPI_RX_ANAA4_CSIxA_RG_CSIxA_CDPHY_L2_T2_FORCE_INIT_SHIFT            
>   5
> +#define
> MIPI_RX_ANAA4_CSIxA_RG_CSIxA_CDPHY_L2_T2_FORCE_INIT_MASK             
>   BIT(5)
> +
> +#define
> MIPI_RX_ANAA8_CSIxA                                                  
>   0x00a8
> +#define
> MIPI_RX_ANAA8_CSIxA_RG_CSIxA_CDPHY_L0_T0_BYTECK_INVERT_SHIFT         
>   0
> +#define
> MIPI_RX_ANAA8_CSIxA_RG_CSIxA_CDPHY_L0_T0_BYTECK_INVERT_MASK          
>   BIT(0)
> +#define
> MIPI_RX_ANAA8_CSIxA_RG_CSIxA_DPHY_L1_BYTECK_INVERT_SHIFT             
>   1
> +#define
> MIPI_RX_ANAA8_CSIxA_RG_CSIxA_DPHY_L1_BYTECK_INVERT_MASK              
>           BIT(1)
> +#define
> MIPI_RX_ANAA8_CSIxA_RG_CSIxA_CDPHY_L2_T1_BYTECK_INVERT_SHIFT         
>   2
> +#define
> MIPI_RX_ANAA8_CSIxA_RG_CSIxA_CDPHY_L2_T1_BYTECK_INVERT_MASK          
>   BIT(2)
> +#define
> MIPI_RX_ANAA8_CSIxA_RG_CSIxA_DPHY_HSDET_LEVEL_MODE_EN_SHIFT          
>   3
> +#define
> MIPI_RX_ANAA8_CSIxA_RG_CSIxA_DPHY_HSDET_LEVEL_MODE_EN_MASK           
>   BIT(3)
> +#define
> MIPI_RX_ANAA8_CSIxA_RG_CSIxA_OS_CAL_SEL_SHIFT                        
>   4
> +#define
> MIPI_RX_ANAA8_CSIxA_RG_CSIxA_OS_CAL_SEL_MASK                         
>   GENMASK(6, 4)
> +#define
> MIPI_RX_ANAA8_CSIxA_RG_CSIxA_DPHY_HSDET_DIG_BACK_EN_SHIFT            
>   7
> +#define
> MIPI_RX_ANAA8_CSIxA_RG_CSIxA_DPHY_HSDET_DIG_BACK_EN_MASK             
>   BIT(7)
> +#define
> MIPI_RX_ANAA8_CSIxA_RG_CSIxA_CDPHY_DELAYCAL_CK_SEL_SHIFT             
>   8
> +#define
> MIPI_RX_ANAA8_CSIxA_RG_CSIxA_CDPHY_DELAYCAL_CK_SEL_MASK              
>           GENMASK(10, 8)
> +#define
> MIPI_RX_ANAA8_CSIxA_RG_CSIxA_OS_CAL_DIV_SHIFT                        
>   11
> +#define
> MIPI_RX_ANAA8_CSIxA_RG_CSIxA_OS_CAL_DIV_MASK                         
>   GENMASK(12, 11)
> +
> +#endif
> diff --git a/drivers/phy/mediatek/phy-mtk-mipi-csi.c
> b/drivers/phy/mediatek/phy-mtk-mipi-csi.c
> new file mode 100644
> index 000000000000..6ce3f95f57bd
> --- /dev/null
> +++ b/drivers/phy/mediatek/phy-mtk-mipi-csi.c
> @@ -0,0 +1,392 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#include <linux/delay.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/phy/phy.h>
> +#include <linux/platform_device.h>
> +#include <linux/slab.h>
> +#include <linux/regmap.h>
> +
> +#include "phy-mtk-mipi-csi-rx-reg.h"
> +
> +#define CSIxB_OFFSET           0x1000
> +
> +struct mtk_mipi_dphy;
> +
> +enum mtk_mipi_dphy_port_id {
> +       MTK_MIPI_PHY_PORT_0 = 0x0, /* 4D1C - CDPHY */
> +       MTK_MIPI_PHY_PORT_1, /* 4D1C - DPHY */
> +       MTK_MIPI_PHY_PORT_2, /* 4D1C - DPHY */
> +       MTK_MIPI_PHY_PORT_0A, /* 2D1C - CDPHY */
> +       MTK_MIPI_PHY_PORT_0B, /* 2D1C - CDPHY */
> +       MTK_MIPI_PHY_PORT_MAX_NUM
> +};
> +
> +struct mtk_mipi_dphy_port {
> +       struct mtk_mipi_dphy *dev;
> +       enum mtk_mipi_dphy_port_id id;
> +       struct regmap *regmap_base;
> +       struct regmap *regmap_4d1c;
Could you avoid using regmap if the registers are only used by this
driver, use phy-mtk-io.h api instead.

> +       struct phy *phy;
> +       bool active;
> +       bool is_cdphy;
> +       bool is_4d1c;
> +};
> +
> +struct mtk_mipi_dphy {
> +       struct device *dev;
> +       void __iomem *rx;
> +       struct mtk_mipi_dphy_port ports[MTK_MIPI_PHY_PORT_MAX_NUM];
> +       struct mutex lock; /* Ports CSI0 and CSI0A/B are mutually
> exclusive */
phy core already provides a mutex, no need provide another one.

Do you switch them at runtime for port 0?

From binding, I guess we use mtk_mipi_dphy_port_id in DTS to determine
which mode is used.

> +};
> +
> +#define REGMAP_BIT(map, reg, field, val) \
> +       regmap_update_bits((map), reg, reg##_##field##_MASK, \
> +                          (val) << reg##_##field##_SHIFT)
> +
> +static int mtk_mipi_phy_power_on(struct phy *phy)
> +{
> +       struct mtk_mipi_dphy_port *port = phy_get_drvdata(phy);
> +       struct mtk_mipi_dphy *priv = port->dev;
> +       struct regmap *regmap_base = port->regmap_base;
> +       struct regmap *regmap_4d1c = port->regmap_4d1c;
> +       int ret = 0;
> +
> +       mutex_lock(&priv->lock);
> +
> +       switch (port->id) {
> +       case MTK_MIPI_PHY_PORT_0:
> +               if (priv->ports[MTK_MIPI_PHY_PORT_0A].active ||
> +                   priv->ports[MTK_MIPI_PHY_PORT_0B].active)
> +                       ret = -EBUSY;
> +               break;
> +
> +       case MTK_MIPI_PHY_PORT_0A:
> +       case MTK_MIPI_PHY_PORT_0B:
> +               if (priv->ports[MTK_MIPI_PHY_PORT_0].active)
> +                       ret = -EBUSY;
> +               break;
> +       }
> +
> +       if (!ret)
> +               port->active = true;
> +
> +       mutex_unlock(&priv->lock);
> +
> +       if (ret < 0)
> +               return ret;
> +
> +       /* Set analog phy mode to DPHY */
> +       if (port->is_cdphy)
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSI0A_CPHY_EN, 0);
> +
> +       if (port->is_4d1c) {
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L0_CKMODE_EN, 0);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L0_CKSEL, 1);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L1_CKMODE_EN, 0);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L1_CKSEL, 1);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L2_CKMODE_EN, 1);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L2_CKSEL, 1);
> +       } else {
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L0_CKMODE_EN, 0);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L0_CKSEL, 0);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L1_CKMODE_EN, 1);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L1_CKSEL, 0);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L2_CKMODE_EN, 0);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L2_CKSEL, 0);
> +       }
> +
> +       if (port->is_4d1c) {
> +               if (port->is_cdphy)
> +                       REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA00_CSIxA,
> +                                  RG_CSI0A_CPHY_EN, 0);
> +
> +               REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L0_CKMODE_EN, 0);
> +               REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L0_CKSEL, 1);
> +               REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L1_CKMODE_EN, 0);
> +               REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L1_CKSEL, 1);
> +               REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L2_CKMODE_EN, 0);
> +               REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_DPHY_L2_CKSEL, 1);
> +       }
> +
> +       /* Byte clock invert */
> +       REGMAP_BIT(regmap_base, MIPI_RX_ANAA8_CSIxA,
> +                  RG_CSIxA_CDPHY_L0_T0_BYTECK_INVERT, 1);
> +       REGMAP_BIT(regmap_base, MIPI_RX_ANAA8_CSIxA,
> +                  RG_CSIxA_DPHY_L1_BYTECK_INVERT, 1);
> +       REGMAP_BIT(regmap_base, MIPI_RX_ANAA8_CSIxA,
> +                  RG_CSIxA_CDPHY_L2_T1_BYTECK_INVERT, 1);
> +
> +       if (port->is_4d1c) {
> +               REGMAP_BIT(regmap_4d1c, MIPI_RX_ANAA8_CSIxA,
> +                          RG_CSIxA_CDPHY_L0_T0_BYTECK_INVERT, 1);
> +               REGMAP_BIT(regmap_4d1c, MIPI_RX_ANAA8_CSIxA,
> +                          RG_CSIxA_DPHY_L1_BYTECK_INVERT, 1);
> +               REGMAP_BIT(regmap_4d1c, MIPI_RX_ANAA8_CSIxA,
> +                          RG_CSIxA_CDPHY_L2_T1_BYTECK_INVERT, 1);
> +       }
> +
> +       /* Start ANA EQ tuning */
> +       if (port->is_cdphy) {
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA18_CSIxA,
> +                          RG_CSI0A_L0_T0AB_EQ_IS, 1);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA18_CSIxA,
> +                          RG_CSI0A_L0_T0AB_EQ_BW, 1);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA1C_CSIxA,
> +                          RG_CSI0A_L1_T1AB_EQ_IS, 1);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA1C_CSIxA,
> +                          RG_CSI0A_L1_T1AB_EQ_BW, 1);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA20_CSI0A,
> +                          RG_CSI0A_L2_T1BC_EQ_IS, 1);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA20_CSI0A,
> +                          RG_CSI0A_L2_T1BC_EQ_BW, 1);
> +
> +               if (port->is_4d1c) {
> +                       REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA18_CSIxA,
> +                                  RG_CSI0A_L0_T0AB_EQ_IS, 1);
> +                       REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA18_CSIxA,
> +                                  RG_CSI0A_L0_T0AB_EQ_BW, 1);
> +                       REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA1C_CSIxA,
> +                                  RG_CSI0A_L1_T1AB_EQ_IS, 1);
> +                       REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA1C_CSIxA,
> +                                  RG_CSI0A_L1_T1AB_EQ_BW, 1);
> +                       REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA20_CSI0A,
> +                                  RG_CSI0A_L2_T1BC_EQ_IS, 1);
> +                       REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA20_CSI0A,
> +                                  RG_CSI0A_L2_T1BC_EQ_BW, 1);
> +               }
> +       } else {
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA18_CSIxA,
> +                          RG_CSI1A_L0_EQ_IS, 1);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA18_CSIxA,
> +                          RG_CSI1A_L0_EQ_BW, 1);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA18_CSIxA,
> +                          RG_CSI1A_L1_EQ_IS, 1);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA18_CSIxA,
> +                          RG_CSI1A_L1_EQ_BW, 1);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA1C_CSIxA,
> +                          RG_CSI1A_L2_EQ_IS, 1);
> +               REGMAP_BIT(regmap_base, MIPI_RX_ANA1C_CSIxA,
> +                          RG_CSI1A_L2_EQ_BW, 1);
> +
> +               if (port->is_4d1c) {
> +                       REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA18_CSIxA,
> +                                  RG_CSI1A_L0_EQ_IS, 1);
> +                       REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA18_CSIxA,
> +                                  RG_CSI1A_L0_EQ_BW, 1);
> +                       REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA18_CSIxA,
> +                                  RG_CSI1A_L1_EQ_IS, 1);
> +                       REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA18_CSIxA,
> +                                  RG_CSI1A_L1_EQ_BW, 1);
> +                       REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA1C_CSIxA,
> +                                  RG_CSI1A_L2_EQ_IS, 1);
> +                       REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA1C_CSIxA,
> +                                  RG_CSI1A_L2_EQ_BW, 1);
> +               }
> +       }
> +
> +       /* End ANA EQ tuning */
> +       regmap_write(regmap_base, MIPI_RX_ANA40_CSIxA, 0x90);
> +
> +       REGMAP_BIT(regmap_base, MIPI_RX_ANA24_CSIxA,
> +                  RG_CSIxA_RESERVE, 0x40);
> +       if (port->is_4d1c)
> +               REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA24_CSIxA,
> +                          RG_CSIxA_RESERVE, 0x40);
> +       REGMAP_BIT(regmap_base, MIPI_RX_WRAPPER80_CSIxA,
> +                  CSR_CSI_RST_MODE, 0);
> +       if (port->is_4d1c)
> +               REGMAP_BIT(regmap_4d1c, MIPI_RX_WRAPPER80_CSIxA,
> +                          CSR_CSI_RST_MODE, 0);
> +       /* ANA power on */
> +       REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                  RG_CSIxA_BG_CORE_EN, 1);
> +       if (port->is_4d1c)
> +               REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_BG_CORE_EN, 1);
> +       usleep_range(20, 40);
> +       REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                  RG_CSIxA_BG_LPF_EN, 1);
> +       if (port->is_4d1c)
> +               REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_BG_LPF_EN, 1);
> +
> +       return 0;
> +}
> +
> +static int mtk_mipi_phy_power_off(struct phy *phy)
> +{
> +       struct mtk_mipi_dphy_port *port = phy_get_drvdata(phy);
> +       struct regmap *regmap_base = port->regmap_base;
> +       struct regmap *regmap_4d1c = port->regmap_4d1c;
> +
> +       /* Disable MIPI BG. */
> +       REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                  RG_CSIxA_BG_CORE_EN, 0);
> +       REGMAP_BIT(regmap_base, MIPI_RX_ANA00_CSIxA,
> +                  RG_CSIxA_BG_LPF_EN, 0);
> +
> +       if (port->is_4d1c) {
> +               REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_BG_CORE_EN, 0);
> +               REGMAP_BIT(regmap_4d1c, MIPI_RX_ANA00_CSIxA,
> +                          RG_CSIxA_BG_LPF_EN, 0);
> +       }
> +
> +       mutex_lock(&port->dev->lock);
> +       port->active = false;
> +       mutex_unlock(&port->dev->lock);
> +
> +       return 0;
> +}
> +
> +static const struct phy_ops mtk_dphy_ops = {
> +       .power_on       = mtk_mipi_phy_power_on,
> +       .power_off      = mtk_mipi_phy_power_off,
> +       .owner          = THIS_MODULE,
> +};
> +
> +static struct phy *mtk_mipi_dphy_xlate(struct device *dev,
> +                                      struct of_phandle_args *args)
> +{
> +       struct mtk_mipi_dphy *priv = dev_get_drvdata(dev);
> +
> +       if (args->args_count != 1)
> +               return ERR_PTR(-EINVAL);
> +
> +       if (args->args[0] >= ARRAY_SIZE(priv->ports))
> +               return ERR_PTR(-ENODEV);
> +
> +       return priv->ports[args->args[0]].phy;
> +}
> +
> +static const struct regmap_config mt8365_phy_regmap_config = {
> +       .reg_bits = 32,
> +       .val_bits = 32,
> +       .reg_stride = 4,
> +       .max_register = 0x700,
> +};
> +
> +static int mtk_mipi_dphy_probe(struct platform_device *pdev)
> +{
> +       static const unsigned int ports_offsets[] = {
> +               [MTK_MIPI_PHY_PORT_0] = 0,
> +               [MTK_MIPI_PHY_PORT_0A] = 0,
> +               [MTK_MIPI_PHY_PORT_0B] = 0x1000,
> +               [MTK_MIPI_PHY_PORT_1] = 0x2000,
> +               [MTK_MIPI_PHY_PORT_2] = 0x4000,
> +       };
How about provide three subnode (p0/p1/p2)in dts like as tphy driver?

for the port 0, it works as three mode (*_0/0A/0B, or 4d1c/2d1c), we
can distinguish it from phy arguments, also the same for port 1/2

> +
> +       struct device *dev = &pdev->dev;
> +       struct phy_provider *phy_provider;
> +       struct mtk_mipi_dphy *priv;
> +       struct resource *res;
> +       unsigned int i;
> +
> +       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> +       if (!priv)
> +               return -ENOMEM;
> +
> +       dev_set_drvdata(dev, priv);
> +       priv->dev = dev;
> +
> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +       priv->rx = devm_ioremap_resource(dev, res);
use devm_platform_ioremap_resource()

> +       if (IS_ERR(priv->rx))
> +               return PTR_ERR(priv->rx);
> +
> +       for (i = 0; i < ARRAY_SIZE(priv->ports); ++i) {
> +               struct mtk_mipi_dphy_port *port = &priv->ports[i];
> +               struct phy *phy;
> +               void __iomem *base;
> +
> +               port->dev = priv;
> +               port->id = i;
> +               base = priv->rx + ports_offsets[i];
> +
> +               port->regmap_base = devm_regmap_init_mmio(port->dev-
> >dev,
> +                                                         base,
> +                                                         &mt8365_phy
> _regmap_config);
> +
> +               port->is_cdphy = i == MTK_MIPI_PHY_PORT_0A ||
> +                                i == MTK_MIPI_PHY_PORT_0B ||
> +                                i == MTK_MIPI_PHY_PORT_0;
> +               port->is_4d1c = i < MTK_MIPI_PHY_PORT_0A;
> +
> +               if (port->is_4d1c)
> +                       port->regmap_4d1c =
> devm_regmap_init_mmio(port->dev->dev,
> +                                                                 bas
> e + CSIxB_OFFSET,
> +                                                                 &mt
> 8365_phy_regmap_config);
> +
> +               phy = devm_phy_create(dev, NULL, &mtk_dphy_ops);
> +               if (IS_ERR(phy)) {
> +                       dev_err(dev, "Failed to create PHY: %ld\n",
> PTR_ERR(phy));
> +                       return PTR_ERR(phy);
> +               }
> +
> +               port->phy = phy;
> +               phy_set_drvdata(phy, port);
> +       }
> +
> +       phy_provider = devm_of_phy_provider_register(dev,
> mtk_mipi_dphy_xlate);
> +       if (IS_ERR(phy_provider)) {
> +               dev_err(dev, "Failed to register PHY provider:
> %ld\n",
> +                       PTR_ERR(phy_provider));
> +               return PTR_ERR(phy_provider);
> +       }
> +
> +       mutex_init(&priv->lock);
> +
> +       return 0;
> +}
> +
> +static int mtk_mipi_dphy_remove(struct platform_device *pdev)
> +{
> +       struct mtk_mipi_dphy *priv = platform_get_drvdata(pdev);
> +
> +       mutex_destroy(&priv->lock);
> +
> +       return 0;
> +}
> +
> +static const struct of_device_id mtk_mipi_dphy_of_match[] = {
> +       {.compatible = "mediatek,mt8365-mipi-csi"},
prefer to provide a generic compatible if not a specific controller
only for mt8365.

Thanks a lot
> +       {},
> +};
> +MODULE_DEVICE_TABLE(of, mtk_mipi_dphy_of_match);


> +
> +static struct platform_driver mipi_dphy_pdrv = {
> +       .probe = mtk_mipi_dphy_probe,
> +       .remove = mtk_mipi_dphy_remove,
> +       .driver = {
> +               .name   = "mtk-mipi-csi",
> +               .of_match_table =
> of_match_ptr(mtk_mipi_dphy_of_match),
> +       },
> +};
> +
> +module_platform_driver(mipi_dphy_pdrv);
> +
> +MODULE_DESCRIPTION("MTK mipi csi cdphy driver");
> +MODULE_AUTHOR("Louis Kuo <louis.kuo@mediatek.com>");
> +MODULE_LICENSE("GPL");
> --
> 2.40.0
> 
-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

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

end of thread, other threads:[~2023-04-07  5:31 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20230403071929.360911-1-jstephan@baylibre.com>
2023-04-03  7:19 ` [PATCH 1/2] dt-bindings: phy: add mtk-mipi-csi driver Julien Stephan
2023-04-03  9:49   ` Krzysztof Kozlowski
     [not found]     ` <CAEHHSvYJrCZop8OvTjsLJjr5HHSrG8dsSQ+K_W2cjdKJ4xfodA@mail.gmail.com>
2023-04-03 14:54       ` Krzysztof Kozlowski
2023-04-03 13:10   ` Rob Herring
2023-04-07  2:40   ` Chunfeng Yun (云春峰)
2023-04-03  7:19 ` [PATCH 2/2] phy: mtk-mipi-csi: add driver for CSI phy Julien Stephan
2023-04-03  9:51   ` Krzysztof Kozlowski
2023-04-05  9:27     ` Julien Stephan
2023-04-03 10:15   ` Chun-Kuang Hu
2023-04-03 15:21   ` Chun-Kuang Hu
2023-04-03 16:36   ` Chun-Kuang Hu
2023-04-07  3:31   ` Chunfeng Yun (云春峰)
2023-04-07  5:30   ` Chunfeng Yun (云春峰)

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