Devicetree
 help / color / mirror / Atom feed
* [PATCH v4 0/7] phy: rockchip-samsung-dcphy: Add the MIPI D-PHY receiver
@ 2026-08-21 12:02 Jason Yang via B4 Relay
  2026-08-21 12:02 ` [PATCH v4 1/7] dt-bindings: phy: Add PHY_TYPE_DSI and PHY_TYPE_CSI definitions Jason Yang via B4 Relay
                   ` (6 more replies)
  0 siblings, 7 replies; 10+ messages in thread
From: Jason Yang via B4 Relay @ 2026-08-21 12:02 UTC (permalink / raw)
  To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Heiko Stuebner, Guochun Huang, Philipp Zabel
  Cc: Michael Riesch, Sebastian Reichel, Bryan O'Donoghue,
	linux-phy, devicetree, linux-arm-kernel, linux-rockchip,
	linux-kernel, Jason Yang

The Samsung MIPI D-/C-PHY block on RK3588 and RK3576 has a transmitter
(DSI) and a receiver (CSI) on the same PHY, and two drivers can use them
at the same time.

Mainline models the block as a single struct phy. The PHY core refcounts
power_on() per struct phy, so the two cannot be powered independently,
and the single devicetree cell selects the mode, so it cannot tell
whether a consumer wants the transmitter or the receiver.

This series registers a struct phy for each of them, adds generic
PHY_TYPE_DSI and PHY_TYPE_CSI constants so that the devicetree can
select between them, and implements the receiver.

  1/7  adds PHY_TYPE_DSI and PHY_TYPE_CSI to the generic header
  2/7  allows a second cell in this binding to select the transmitter
       or the receiver
  3/7  moves the block-level setup to runtime resume
  4/7  names the transmitter helpers and ops (no functional change)
  5/7  factors the transmitter teardown into a helper (no functional
       change)
  6/7  registers the receiver's struct phy and takes the second cell
       in of_xlate()
  7/7  implements the receiver bring-up

First, my apologies for the quality of v3. I sent it too hastily, 
and much of it had not been thought through before it went to
the list.

I have removed the Assisted-by tags from 1/7, 2/7, 3/7 and 5/7. Writing this
code and the commit messages of those patches don't need AI; I only
used an AI to catch typos and to smooth my words(same as this letter).

On the points Krzysztof and Sebastian raised, I have rewritten the
commit messages of 1/7 and 2/7 and the binding text, and the binding
now lists all four combinations, so that it is clear how the mode and
the choice of transmitter or receiver go together. A single cell still
means the transmitter, so existing device trees are unaffected.

On the D-PHY / C-PHY mixing Michael asked about earlier: at the end of
TRM section 22.1 I found the sentence "The TX and RX only support
operate in the same PHY mode." So DSI and CSI can run at the same
time, but both have to be in the same mode. 2/7 says so in the binding
text and in its commit message, and 6/7 rejects one D-PHY consumer 
next to one C-PHY consumer in of_xlate().

Because of that, and because the list pointed out that this is a combo
PHY, I treat the block as one transmitter PHY and one receiver PHY,
each of which can run in D-PHY or C-PHY mode. The transmitter and the
receiver therefore register their own phy_ops, and power_on() only has
to work out which mode the block is in, rather than working out both
the mode and which of the two it is being called for. C-PHY still
returns -EOPNOTSUPP throughout.

I have also moved the block-level setup into runtime resume, so that
the runtime PM usage count does the counting and I do not have to add
a refcount and a lock to protect that count. That needs the point at which
probe enables runtime PM to be fixed first, which I do not think
belongs in this series, so it is sent separately for review: [1]

[1] https://lore.kernel.org/r/20260821-dcphy-rpm-v1-v1-1-a7db728b2539@gmail.com

My apologies again to everyone who spent time on the earlier versions. 
I will look over my own code more carefully before sending from now on, and
take responsibility for it. Thank you.

Testing
=======

Tested on an RK3588 board with two devicetree configurations, one boot
each.

With #phy-cells = <2>, DCPHY0 drives a DSI panel from its transmitter
while an IMX219 camera feeds its receiver; DCPHY1 drives a second DSI
panel through an unchanged single PHY_TYPE_DPHY cell.

  - both panels light from boot; the camera then joins and streams
    with GStreamer, so the transmitter and the receiver run at the
    same time on DCPHY0
  - the transmitter then leaves and rejoins mid-stream: the panel goes
    off and comes back while the capture keeps running
  - no WARNING, underflow, "Internal error" or Oops in dmesg

With dsi0 disabled, DCPHY0 has no transmitter consumer at all for the
whole boot, and the camera still brings the block up and streams. That
path only works because 3/7 moved the block-level setup to runtime
resume.

Not covered: RK3576, which this driver and binding also describe, and
the 3- and 4-lane receiver paths.

The DSI panels only light with the U-Boot SPLL fix [2] applied:
without it the bootloader leaves the SPLL at its 351 MHz bootrom
default while the devicetree describes it as a 702 MHz fixed clock,
halving the rate of both DSI hosts. The receiver path is unaffected;
the camera captures exercise it independently.

[2] https://lore.kernel.org/u-boot/20260804002643.2308515-3-jonas@kwiboo.se/

---
Changes in v4:
- Put the second cell back: the first cell selects the mode, the
  second the transmitter or the receiver.
- Drop the private use count and mutex; the runtime PM usage count
  does the same job.
- New patch 3/7: move the block-level setup to runtime resume.
- Split v3's 3/5 into 4/7 and 5/7.
- of_xlate() rejects a mix of D-PHY and C-PHY consumers.
- The runtime PM probe-order fix is now a separate patch [1] that this
  series applies on top of.
- Bryan O'Donoghue's Reviewed-by from v2 is not carried over; that
  patch was rewritten.
- Link to v3: https://lore.kernel.org/r/20260810-dcphy-rx-v1-v3-0-a2d25c29adfc@gmail.com

---
Jason Yang (7):
      dt-bindings: phy: Add PHY_TYPE_DSI and PHY_TYPE_CSI definitions
      dt-bindings: phy: rockchip,rk3588-mipi-dcphy: Allow DSI and CSI consumers
      phy: rockchip-samsung-dcphy: Move block-level setup to runtime resume
      phy: rockchip-samsung-dcphy: Name the transmitter helpers and ops
      phy: rockchip-samsung-dcphy: Factor the transmitter teardown into a helper
      phy: rockchip-samsung-dcphy: Add a second PHY for the receiver
      phy: rockchip-samsung-dcphy: Add MIPI D-PHY receiver support

 .../bindings/phy/rockchip,rk3588-mipi-dcphy.yaml   |  20 +-
 drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c  | 552 ++++++++++++++++++---
 include/dt-bindings/phy/phy.h                      |   2 +
 3 files changed, 515 insertions(+), 59 deletions(-)
---
base-commit: b828e5a7fb47aa434b8b20636de5d47356314322
change-id: 20260721-dcphy-rx-v1-9af57f3edfd9

Best regards,
-- 
Jason Yang <jason98166@gmail.com>



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

* [PATCH v4 1/7] dt-bindings: phy: Add PHY_TYPE_DSI and PHY_TYPE_CSI definitions
  2026-08-21 12:02 [PATCH v4 0/7] phy: rockchip-samsung-dcphy: Add the MIPI D-PHY receiver Jason Yang via B4 Relay
@ 2026-08-21 12:02 ` Jason Yang via B4 Relay
  2026-08-27 11:45   ` Krzysztof Kozlowski
  2026-08-21 12:02 ` [PATCH v4 2/7] dt-bindings: phy: rockchip,rk3588-mipi-dcphy: Allow DSI and CSI consumers Jason Yang via B4 Relay
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 10+ messages in thread
From: Jason Yang via B4 Relay @ 2026-08-21 12:02 UTC (permalink / raw)
  To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Heiko Stuebner, Guochun Huang, Philipp Zabel
  Cc: Michael Riesch, Sebastian Reichel, Bryan O'Donoghue,
	linux-phy, devicetree, linux-arm-kernel, linux-rockchip,
	linux-kernel, Jason Yang

From: Jason Yang <jason98166@gmail.com>

A MIPI D-PHY or C-PHY can be a transmitter (DSI) or a receiver (CSI),
and in some PHY blocks both work at the same time. The existing
PHY_TYPE_DPHY and PHY_TYPE_CPHY cannot tell whether a consumer wants
the transmitter or the receiver.

Add PHY_TYPE_DSI and PHY_TYPE_CSI, so that a binding can select both
D-PHY or C-PHY and transmitter or receiver. They do not replace
PHY_TYPE_DPHY/PHY_TYPE_CPHY, which remain the right choice where a cell
selects the mode. The first user is the Rockchip RK3588 MIPI DC-PHY
binding.

Suggested-by: Michael Riesch <michael.riesch@collabora.com>
Link: https://lore.kernel.org/r/82da3622-9c3a-454c-87bc-fb4ec7adb68d@collabora.com
Signed-off-by: Jason Yang <jason98166@gmail.com>
---
 include/dt-bindings/phy/phy.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/dt-bindings/phy/phy.h b/include/dt-bindings/phy/phy.h
index 979b5dfd8353..8ee3f88e6d80 100644
--- a/include/dt-bindings/phy/phy.h
+++ b/include/dt-bindings/phy/phy.h
@@ -24,6 +24,8 @@
 #define PHY_TYPE_CPHY		11
 #define PHY_TYPE_USXGMII	12
 #define PHY_TYPE_XAUI		13
+#define PHY_TYPE_DSI		14
+#define PHY_TYPE_CSI		15
 
 #define PHY_POL_NORMAL		0
 #define PHY_POL_INVERT		1

-- 
2.43.0



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

* [PATCH v4 2/7] dt-bindings: phy: rockchip,rk3588-mipi-dcphy: Allow DSI and CSI consumers
  2026-08-21 12:02 [PATCH v4 0/7] phy: rockchip-samsung-dcphy: Add the MIPI D-PHY receiver Jason Yang via B4 Relay
  2026-08-21 12:02 ` [PATCH v4 1/7] dt-bindings: phy: Add PHY_TYPE_DSI and PHY_TYPE_CSI definitions Jason Yang via B4 Relay
@ 2026-08-21 12:02 ` Jason Yang via B4 Relay
  2026-08-27 11:47   ` Krzysztof Kozlowski
  2026-08-21 12:02 ` [PATCH v4 3/7] phy: rockchip-samsung-dcphy: Move block-level setup to runtime resume Jason Yang via B4 Relay
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 10+ messages in thread
From: Jason Yang via B4 Relay @ 2026-08-21 12:02 UTC (permalink / raw)
  To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Heiko Stuebner, Guochun Huang, Philipp Zabel
  Cc: Michael Riesch, Sebastian Reichel, Bryan O'Donoghue,
	linux-phy, devicetree, linux-arm-kernel, linux-rockchip,
	linux-kernel, Jason Yang

From: Jason Yang <jason98166@gmail.com>

The Samsung MIPI D-/C-PHY block on RK3588 and RK3576 has a transmitter
(DSI) and a receiver (CSI) on the same PHY, and two drivers can use them
at the same time. The single cell this binding has selects the mode, so
it cannot tell whether a consumer wants the transmitter or the receiver.

Allow a second cell that selects the transmitter or the receiver. With
D-PHY:

	/* the MIPI DSI host, driving the transmitter */
	phys = <&mipidcphy0 PHY_TYPE_DPHY PHY_TYPE_DSI>;

	/* the MIPI CSI-2 host, driving the receiver */
	phys = <&mipidcphy0 PHY_TYPE_DPHY PHY_TYPE_CSI>;

and with C-PHY:

	phys = <&mipidcphy0 PHY_TYPE_CPHY PHY_TYPE_DSI>;
	phys = <&mipidcphy0 PHY_TYPE_CPHY PHY_TYPE_CSI>;

The transmitter and the receiver cannot operate in different modes [1],
so the first cell must match in both consumers.

A board that wires up both sets '#phy-cells = <2>'. A board that only
wires up the transmitter keeps '#phy-cells = <1>', so existing device
trees are unaffected.

[1] RK3588 TRM: section 22.1 (overview): "The TX and RX only support
    operate in the same PHY mode."

Signed-off-by: Jason Yang <jason98166@gmail.com>
---
 .../bindings/phy/rockchip,rk3588-mipi-dcphy.yaml     | 20 +++++++++++++++++---
 1 file changed, 17 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/phy/rockchip,rk3588-mipi-dcphy.yaml b/Documentation/devicetree/bindings/phy/rockchip,rk3588-mipi-dcphy.yaml
index c8ff5ba22a86..595a71a51ee6 100644
--- a/Documentation/devicetree/bindings/phy/rockchip,rk3588-mipi-dcphy.yaml
+++ b/Documentation/devicetree/bindings/phy/rockchip,rk3588-mipi-dcphy.yaml
@@ -20,11 +20,25 @@ properties:
     maxItems: 1
 
   "#phy-cells":
-    const: 1
+    enum: [1, 2]
     description: |
-      Argument is mode to operate in. Supported modes are:
+      A single cell selects the mode to operate in and refers to the
+      transmitter:
         - PHY_TYPE_DPHY
         - PHY_TYPE_CPHY
+
+      Two cells select the mode and then the transmitter (DSI) or the
+      receiver (CSI), so that both can be described as independent
+      consumers of the same PHY:
+        - PHY_TYPE_DPHY PHY_TYPE_DSI
+        - PHY_TYPE_DPHY PHY_TYPE_CSI
+        - PHY_TYPE_CPHY PHY_TYPE_DSI
+        - PHY_TYPE_CPHY PHY_TYPE_CSI
+
+      The transmitter (DSI) and the receiver (CSI) cannot operate in
+      different modes, so when both are described, the first cell must
+      match in both consumers.
+
       See include/dt-bindings/phy/phy.h for constants.
 
   clocks:
@@ -82,6 +96,6 @@ examples:
                  <&cru SRST_S_MIPI_DCPHY0>;
         reset-names = "m_phy", "apb", "grf", "s_phy";
         rockchip,grf = <&mipidcphy0_grf>;
-        #phy-cells = <1>;
+        #phy-cells = <2>;
       };
     };

-- 
2.43.0



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

* [PATCH v4 3/7] phy: rockchip-samsung-dcphy: Move block-level setup to runtime resume
  2026-08-21 12:02 [PATCH v4 0/7] phy: rockchip-samsung-dcphy: Add the MIPI D-PHY receiver Jason Yang via B4 Relay
  2026-08-21 12:02 ` [PATCH v4 1/7] dt-bindings: phy: Add PHY_TYPE_DSI and PHY_TYPE_CSI definitions Jason Yang via B4 Relay
  2026-08-21 12:02 ` [PATCH v4 2/7] dt-bindings: phy: rockchip,rk3588-mipi-dcphy: Allow DSI and CSI consumers Jason Yang via B4 Relay
@ 2026-08-21 12:02 ` Jason Yang via B4 Relay
  2026-08-21 12:02 ` [PATCH v4 4/7] phy: rockchip-samsung-dcphy: Name the transmitter helpers and ops Jason Yang via B4 Relay
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Jason Yang via B4 Relay @ 2026-08-21 12:02 UTC (permalink / raw)
  To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Heiko Stuebner, Guochun Huang, Philipp Zabel
  Cc: Michael Riesch, Sebastian Reichel, Bryan O'Donoghue,
	linux-phy, devicetree, linux-arm-kernel, linux-rockchip,
	linux-kernel, Jason Yang

From: Jason Yang <jason98166@gmail.com>

The APB reset and the BIAS references have to be treated as block-level
[1]: both the transmitter and the receiver need them, and they only have
to be programmed once. They are programmed from the transmitter's
power-on path today. A later change registers one struct phy for each of
them, and a second consumer coming up would then reset the block
underneath a PHY that is already running.

Program them from runtime resume instead, where whichever of the two
comes up first brings the block up and a second one no longer resets it.
This puts the BIAS writes ahead of the per-PHY reset assert, where the
TRM's worked example has them after [1]. That is safe: neither M_RESETN
nor S_RESETN covers the BIAS registers, and the values written are those
registers' reset defaults.

The output level select in BIAS_CON4 stays on the power-on path: it
selects 400mV for D-PHY and 530mV for C-PHY, and the driver core resumes
a runtime-PM supplier before the consumer's probe runs, so runtime resume
cannot yet know which of the two applies.

[1] RK3588 TRM: sections 22.4.1 (address map), 22.4.2 (reset values),
    22.6.1.2 (reset) and 22.6.4.1 (D-PHY transmitter start-up)

Signed-off-by: Jason Yang <jason98166@gmail.com>
---
 drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c | 25 ++++++++++++-----------
 1 file changed, 13 insertions(+), 12 deletions(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c b/drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c
index 11e872cc6611..459ce882b369 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c
@@ -980,13 +980,6 @@ static void samsung_mipi_dcphy_bias_block_enable(struct samsung_mipi_dcphy *sams
 						 I_LADDER_1_00V);
 	regmap_write(samsung->regmap, BIAS_CON2, REG_325M_325MV | REG_LP_400M_400MV |
 						 REG_400M_400MV | REG_645M_645MV);
-
-	/* default output voltage select:
-	 * dphy: 400mv
-	 * cphy: 530mv
-	 */
-	regmap_update_bits(samsung->regmap, BIAS_CON4,
-			   I_MUX_SEL_MASK, I_MUX_400MV);
 }
 
 static void samsung_mipi_dphy_lane_enable(struct samsung_mipi_dcphy *samsung)
@@ -1338,7 +1331,13 @@ static int samsung_mipi_dphy_power_on(struct samsung_mipi_dcphy *samsung)
 
 	reset_control_assert(samsung->m_phy_rst);
 
-	samsung_mipi_dcphy_bias_block_enable(samsung);
+	/* default output voltage select:
+	 * dphy: 400mv
+	 * cphy: 530mv
+	 */
+	regmap_update_bits(samsung->regmap, BIAS_CON4,
+			   I_MUX_SEL_MASK, I_MUX_400MV);
+
 	samsung_mipi_dcphy_pll_configure(samsung);
 	samsung_mipi_dphy_clk_lane_timing_init(samsung);
 	samsung_mipi_dphy_data_lane_timing_init(samsung);
@@ -1362,10 +1361,6 @@ static int samsung_mipi_dcphy_power_on(struct phy *phy)
 {
 	struct samsung_mipi_dcphy *samsung = phy_get_drvdata(phy);
 
-	reset_control_assert(samsung->apb_rst);
-	udelay(1);
-	reset_control_deassert(samsung->apb_rst);
-
 	switch (samsung->type) {
 	case PHY_TYPE_DPHY:
 		return samsung_mipi_dphy_power_on(samsung);
@@ -1656,6 +1651,12 @@ static __maybe_unused int samsung_mipi_dcphy_runtime_resume(struct device *dev)
 		return ret;
 	}
 
+	reset_control_assert(samsung->apb_rst);
+	udelay(1);
+	reset_control_deassert(samsung->apb_rst);
+
+	samsung_mipi_dcphy_bias_block_enable(samsung);
+
 	return 0;
 }
 

-- 
2.43.0



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

* [PATCH v4 4/7] phy: rockchip-samsung-dcphy: Name the transmitter helpers and ops
  2026-08-21 12:02 [PATCH v4 0/7] phy: rockchip-samsung-dcphy: Add the MIPI D-PHY receiver Jason Yang via B4 Relay
                   ` (2 preceding siblings ...)
  2026-08-21 12:02 ` [PATCH v4 3/7] phy: rockchip-samsung-dcphy: Move block-level setup to runtime resume Jason Yang via B4 Relay
@ 2026-08-21 12:02 ` Jason Yang via B4 Relay
  2026-08-21 12:02 ` [PATCH v4 5/7] phy: rockchip-samsung-dcphy: Factor the transmitter teardown into a helper Jason Yang via B4 Relay
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Jason Yang via B4 Relay @ 2026-08-21 12:02 UTC (permalink / raw)
  To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Heiko Stuebner, Guochun Huang, Philipp Zabel
  Cc: Michael Riesch, Sebastian Reichel, Bryan O'Donoghue,
	linux-phy, devicetree, linux-arm-kernel, linux-rockchip,
	linux-kernel, Jason Yang

From: Jason Yang <jason98166@gmail.com>

The block is a combo PHY: it exposes a transmitter and a receiver, and a
later change registers one struct phy for each. Prepare for that. Give
every helper that programs the master lanes a tx_ prefix, and move the
phy pointer and the lane count, which only the transmitter uses, into a
struct samsung_mipi_phy that the receiver can have one of too.

Name the phy_ops and its callbacks after the transmitter as well, so
that the receiver can bring its own rather than share these.

The BIAS block and the PLL keep their names: the TRM puts both in the
part common to the whole block [1], so neither belongs to one PHY even
though only the transmitter drives the PLL.

No functional change intended.

[1] RK3588 TRM: sections 22.3.1 (bias generator), 22.3.2 (PLL) and
    22.4.1 (address map)

Assisted-by: Claude:claude-fable-5
Signed-off-by: Jason Yang <jason98166@gmail.com>
---
 drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c | 67 ++++++++++++-----------
 1 file changed, 36 insertions(+), 31 deletions(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c b/drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c
index 459ce882b369..f58907dec733 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c
@@ -280,6 +280,11 @@ struct samsung_mipi_dcphy_plat_data {
 	u32 dphy_tx_max_lane_kbps;
 };
 
+struct samsung_mipi_phy {
+	struct phy *phy;
+	unsigned int lanes;
+};
+
 struct samsung_mipi_dcphy {
 	struct device *dev;
 	struct clk *ref_clk;
@@ -290,8 +295,7 @@ struct samsung_mipi_dcphy {
 	struct reset_control *s_phy_rst;
 	struct reset_control *apb_rst;
 	struct reset_control *grf_apb_rst;
-	unsigned int lanes;
-	struct phy *phy;
+	struct samsung_mipi_phy tx;
 	u8 type;
 
 	const struct samsung_mipi_dcphy_plat_data *pdata;
@@ -982,13 +986,13 @@ static void samsung_mipi_dcphy_bias_block_enable(struct samsung_mipi_dcphy *sams
 						 REG_400M_400MV | REG_645M_645MV);
 }
 
-static void samsung_mipi_dphy_lane_enable(struct samsung_mipi_dcphy *samsung)
+static void samsung_mipi_dphy_tx_lane_enable(struct samsung_mipi_dcphy *samsung)
 {
 	regmap_write(samsung->regmap, DPHY_MC_GNR_CON1, T_PHY_READY(0x2000));
 	regmap_update_bits(samsung->regmap, DPHY_MC_GNR_CON0,
 			   PHY_ENABLE, PHY_ENABLE);
 
-	switch (samsung->lanes) {
+	switch (samsung->tx.lanes) {
 	case 4:
 		regmap_write(samsung->regmap, DPHY_MD3_GNR_CON1,
 			     T_PHY_READY(0x2000));
@@ -1017,9 +1021,9 @@ static void samsung_mipi_dphy_lane_enable(struct samsung_mipi_dcphy *samsung)
 	}
 }
 
-static void samsung_mipi_dphy_lane_disable(struct samsung_mipi_dcphy *samsung)
+static void samsung_mipi_dphy_tx_lane_disable(struct samsung_mipi_dcphy *samsung)
 {
-	switch (samsung->lanes) {
+	switch (samsung->tx.lanes) {
 	case 4:
 		regmap_update_bits(samsung->regmap, DPHY_MD3_GNR_CON0,
 				   PHY_ENABLE, 0);
@@ -1094,7 +1098,7 @@ static void samsung_mipi_dcphy_pll_disable(struct samsung_mipi_dcphy *samsung)
 }
 
 static const struct samsung_mipi_dphy_timing *
-samsung_mipi_dphy_get_timing(struct samsung_mipi_dcphy *samsung)
+samsung_mipi_dphy_tx_get_timing(struct samsung_mipi_dcphy *samsung)
 {
 	const struct samsung_mipi_dphy_timing *timings;
 	unsigned int num_timings;
@@ -1201,13 +1205,13 @@ samsung_mipi_dcphy_pll_round_rate(struct samsung_mipi_dcphy *samsung,
 }
 
 static void
-samsung_mipi_dphy_clk_lane_timing_init(struct samsung_mipi_dcphy *samsung)
+samsung_mipi_dphy_tx_clk_lane_timing_init(struct samsung_mipi_dcphy *samsung)
 {
 	const struct samsung_mipi_dphy_timing *timing;
 	unsigned int lane_hs_rate = div64_ul(samsung->pll.rate, USEC_PER_SEC);
 	u32 val, res_up, res_down;
 
-	timing = samsung_mipi_dphy_get_timing(samsung);
+	timing = samsung_mipi_dphy_tx_get_timing(samsung);
 	regmap_write(samsung->regmap, DPHY_MC_GNR_CON0, 0xf000);
 
 	/*
@@ -1256,13 +1260,13 @@ samsung_mipi_dphy_clk_lane_timing_init(struct samsung_mipi_dcphy *samsung)
 }
 
 static void
-samsung_mipi_dphy_data_lane_timing_init(struct samsung_mipi_dcphy *samsung)
+samsung_mipi_dphy_tx_data_lane_timing_init(struct samsung_mipi_dcphy *samsung)
 {
 	const struct samsung_mipi_dphy_timing *timing;
 	unsigned int lane_hs_rate = div64_ul(samsung->pll.rate, USEC_PER_SEC);
 	u32 val, res_up, res_down;
 
-	timing = samsung_mipi_dphy_get_timing(samsung);
+	timing = samsung_mipi_dphy_tx_get_timing(samsung);
 
 	/*
 	 * The Drive-Strength / Voltage-Amplitude is adjusted by adjusting the
@@ -1325,7 +1329,7 @@ samsung_mipi_dphy_data_lane_timing_init(struct samsung_mipi_dcphy *samsung)
 	regmap_write(samsung->regmap, DPHY_MD3_TIME_CON4, 0x1f4);
 }
 
-static int samsung_mipi_dphy_power_on(struct samsung_mipi_dcphy *samsung)
+static int samsung_mipi_dphy_tx_power_on(struct samsung_mipi_dcphy *samsung)
 {
 	int ret;
 
@@ -1339,13 +1343,13 @@ static int samsung_mipi_dphy_power_on(struct samsung_mipi_dcphy *samsung)
 			   I_MUX_SEL_MASK, I_MUX_400MV);
 
 	samsung_mipi_dcphy_pll_configure(samsung);
-	samsung_mipi_dphy_clk_lane_timing_init(samsung);
-	samsung_mipi_dphy_data_lane_timing_init(samsung);
+	samsung_mipi_dphy_tx_clk_lane_timing_init(samsung);
+	samsung_mipi_dphy_tx_data_lane_timing_init(samsung);
 	ret = samsung_mipi_dcphy_pll_enable(samsung);
 	if (ret < 0)
 		return ret;
 
-	samsung_mipi_dphy_lane_enable(samsung);
+	samsung_mipi_dphy_tx_lane_enable(samsung);
 
 	reset_control_deassert(samsung->m_phy_rst);
 
@@ -1357,13 +1361,13 @@ static int samsung_mipi_dphy_power_on(struct samsung_mipi_dcphy *samsung)
 	return 0;
 }
 
-static int samsung_mipi_dcphy_power_on(struct phy *phy)
+static int samsung_mipi_dcphy_tx_power_on(struct phy *phy)
 {
 	struct samsung_mipi_dcphy *samsung = phy_get_drvdata(phy);
 
 	switch (samsung->type) {
 	case PHY_TYPE_DPHY:
-		return samsung_mipi_dphy_power_on(samsung);
+		return samsung_mipi_dphy_tx_power_on(samsung);
 	default:
 		/* CPHY part to be implemented later */
 		return -EOPNOTSUPP;
@@ -1372,13 +1376,13 @@ static int samsung_mipi_dcphy_power_on(struct phy *phy)
 	return 0;
 }
 
-static int samsung_mipi_dcphy_power_off(struct phy *phy)
+static int samsung_mipi_dcphy_tx_power_off(struct phy *phy)
 {
 	struct samsung_mipi_dcphy *samsung = phy_get_drvdata(phy);
 
 	switch (samsung->type) {
 	case PHY_TYPE_DPHY:
-		samsung_mipi_dphy_lane_disable(samsung);
+		samsung_mipi_dphy_tx_lane_disable(samsung);
 		break;
 	default:
 		/* CPHY part to be implemented later */
@@ -1477,13 +1481,13 @@ samsung_mipi_dcphy_pll_calc_rate(struct samsung_mipi_dcphy *samsung,
 	}
 }
 
-static int samsung_mipi_dcphy_configure(struct phy *phy,
-					union phy_configure_opts *opts)
+static int samsung_mipi_dcphy_tx_configure(struct phy *phy,
+					   union phy_configure_opts *opts)
 {
 	struct samsung_mipi_dcphy *samsung = phy_get_drvdata(phy);
 	unsigned long long target_rate = opts->mipi_dphy.hs_clk_rate;
 
-	samsung->lanes = opts->mipi_dphy.lanes > 4 ? 4 : opts->mipi_dphy.lanes;
+	samsung->tx.lanes = opts->mipi_dphy.lanes > 4 ? 4 : opts->mipi_dphy.lanes;
 
 	samsung_mipi_dcphy_pll_calc_rate(samsung, target_rate);
 	opts->mipi_dphy.hs_clk_rate = samsung->pll.rate;
@@ -1507,10 +1511,10 @@ static int samsung_mipi_dcphy_exit(struct phy *phy)
 	return 0;
 }
 
-static const struct phy_ops samsung_mipi_dcphy_ops = {
-	.configure = samsung_mipi_dcphy_configure,
-	.power_on  = samsung_mipi_dcphy_power_on,
-	.power_off = samsung_mipi_dcphy_power_off,
+static const struct phy_ops samsung_mipi_dcphy_tx_ops = {
+	.configure = samsung_mipi_dcphy_tx_configure,
+	.power_on  = samsung_mipi_dcphy_tx_power_on,
+	.power_off = samsung_mipi_dcphy_tx_power_off,
 	.init = samsung_mipi_dcphy_init,
 	.exit = samsung_mipi_dcphy_exit,
 	.owner	   = THIS_MODULE,
@@ -1540,7 +1544,7 @@ static struct phy *samsung_mipi_dcphy_xlate(struct device *dev,
 
 	samsung->type = args->args[0];
 
-	return samsung->phy;
+	return samsung->tx.phy;
 }
 
 static int samsung_mipi_dcphy_probe(struct platform_device *pdev)
@@ -1609,11 +1613,12 @@ static int samsung_mipi_dcphy_probe(struct platform_device *pdev)
 	if (ret)
 		return dev_err_probe(dev, ret, "Failed to enable runtime PM\n");
 
-	samsung->phy = devm_phy_create(dev, NULL, &samsung_mipi_dcphy_ops);
-	if (IS_ERR(samsung->phy))
-		return dev_err_probe(dev, PTR_ERR(samsung->phy), "Failed to create MIPI DC-PHY\n");
+	samsung->tx.phy = devm_phy_create(dev, NULL, &samsung_mipi_dcphy_tx_ops);
+	if (IS_ERR(samsung->tx.phy))
+		return dev_err_probe(dev, PTR_ERR(samsung->tx.phy),
+				     "Failed to create MIPI DC-PHY transmitter\n");
 
-	phy_set_drvdata(samsung->phy, samsung);
+	phy_set_drvdata(samsung->tx.phy, samsung);
 
 	phy_provider = devm_of_phy_provider_register(dev, samsung_mipi_dcphy_xlate);
 	if (IS_ERR(phy_provider))

-- 
2.43.0



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

* [PATCH v4 5/7] phy: rockchip-samsung-dcphy: Factor the transmitter teardown into a helper
  2026-08-21 12:02 [PATCH v4 0/7] phy: rockchip-samsung-dcphy: Add the MIPI D-PHY receiver Jason Yang via B4 Relay
                   ` (3 preceding siblings ...)
  2026-08-21 12:02 ` [PATCH v4 4/7] phy: rockchip-samsung-dcphy: Name the transmitter helpers and ops Jason Yang via B4 Relay
@ 2026-08-21 12:02 ` Jason Yang via B4 Relay
  2026-08-21 12:02 ` [PATCH v4 6/7] phy: rockchip-samsung-dcphy: Add a second PHY for the receiver Jason Yang via B4 Relay
  2026-08-21 12:02 ` [PATCH v4 7/7] phy: rockchip-samsung-dcphy: Add MIPI D-PHY receiver support Jason Yang via B4 Relay
  6 siblings, 0 replies; 10+ messages in thread
From: Jason Yang via B4 Relay @ 2026-08-21 12:02 UTC (permalink / raw)
  To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Heiko Stuebner, Guochun Huang, Philipp Zabel
  Cc: Michael Riesch, Sebastian Reichel, Bryan O'Donoghue,
	linux-phy, devicetree, linux-arm-kernel, linux-rockchip,
	linux-kernel, Jason Yang

From: Jason Yang <jason98166@gmail.com>

The transmitter's power-on path is in samsung_mipi_dphy_tx_power_on(),
but the power_off callback still does the teardown itself.

Move the teardown into samsung_mipi_dphy_tx_power_off(), so that
power-on and power-off are a matching pair. Both callbacks then have a
type switch whose arms are plain returns. Turn each into an early guard
for the not yet supported C-PHY and drop the unreachable trailing
return.

No functional change intended.

Signed-off-by: Jason Yang <jason98166@gmail.com>
---
 drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c | 31 ++++++++++-------------
 1 file changed, 14 insertions(+), 17 deletions(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c b/drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c
index f58907dec733..5d9d44a1d6a2 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c
@@ -1361,37 +1361,34 @@ static int samsung_mipi_dphy_tx_power_on(struct samsung_mipi_dcphy *samsung)
 	return 0;
 }
 
+static int samsung_mipi_dphy_tx_power_off(struct samsung_mipi_dcphy *samsung)
+{
+	samsung_mipi_dphy_tx_lane_disable(samsung);
+	samsung_mipi_dcphy_pll_disable(samsung);
+
+	return 0;
+}
+
 static int samsung_mipi_dcphy_tx_power_on(struct phy *phy)
 {
 	struct samsung_mipi_dcphy *samsung = phy_get_drvdata(phy);
 
-	switch (samsung->type) {
-	case PHY_TYPE_DPHY:
-		return samsung_mipi_dphy_tx_power_on(samsung);
-	default:
-		/* CPHY part to be implemented later */
+	/* CPHY part to be implemented later */
+	if (samsung->type != PHY_TYPE_DPHY)
 		return -EOPNOTSUPP;
-	}
 
-	return 0;
+	return samsung_mipi_dphy_tx_power_on(samsung);
 }
 
 static int samsung_mipi_dcphy_tx_power_off(struct phy *phy)
 {
 	struct samsung_mipi_dcphy *samsung = phy_get_drvdata(phy);
 
-	switch (samsung->type) {
-	case PHY_TYPE_DPHY:
-		samsung_mipi_dphy_tx_lane_disable(samsung);
-		break;
-	default:
-		/* CPHY part to be implemented later */
+	/* CPHY part to be implemented later */
+	if (samsung->type != PHY_TYPE_DPHY)
 		return -EOPNOTSUPP;
-	}
 
-	samsung_mipi_dcphy_pll_disable(samsung);
-
-	return 0;
+	return samsung_mipi_dphy_tx_power_off(samsung);
 }
 
 static int

-- 
2.43.0



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

* [PATCH v4 6/7] phy: rockchip-samsung-dcphy: Add a second PHY for the receiver
  2026-08-21 12:02 [PATCH v4 0/7] phy: rockchip-samsung-dcphy: Add the MIPI D-PHY receiver Jason Yang via B4 Relay
                   ` (4 preceding siblings ...)
  2026-08-21 12:02 ` [PATCH v4 5/7] phy: rockchip-samsung-dcphy: Factor the transmitter teardown into a helper Jason Yang via B4 Relay
@ 2026-08-21 12:02 ` Jason Yang via B4 Relay
  2026-08-21 12:02 ` [PATCH v4 7/7] phy: rockchip-samsung-dcphy: Add MIPI D-PHY receiver support Jason Yang via B4 Relay
  6 siblings, 0 replies; 10+ messages in thread
From: Jason Yang via B4 Relay @ 2026-08-21 12:02 UTC (permalink / raw)
  To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Heiko Stuebner, Guochun Huang, Philipp Zabel
  Cc: Michael Riesch, Sebastian Reichel, Bryan O'Donoghue,
	linux-phy, devicetree, linux-arm-kernel, linux-rockchip,
	linux-kernel, Jason Yang

From: Jason Yang <jason98166@gmail.com>

Give the receiver a struct phy of its own, with its own phy_ops and its
own samsung_mipi_phy for the state the two do not share.

of_xlate() takes the second cell, PHY_TYPE_DSI selecting the transmitter
and PHY_TYPE_CSI the receiver, and falls back to the transmitter for a
single-cell provider, so existing device trees keep working. It now
rejects an unknown value in either cell, and a mix of D-PHY and C-PHY
consumers, which the TRM does not support [1].

The receiver's callbacks return -EOPNOTSUPP until its bring-up is added
in the next change.

[1] RK3588 TRM: section 22.1 (overview)

Assisted-by: Claude:claude-fable-5
Signed-off-by: Jason Yang <jason98166@gmail.com>
---
 drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c | 69 +++++++++++++++++++++--
 1 file changed, 63 insertions(+), 6 deletions(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c b/drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c
index 5d9d44a1d6a2..d27a5916bd40 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c
@@ -296,6 +296,8 @@ struct samsung_mipi_dcphy {
 	struct reset_control *apb_rst;
 	struct reset_control *grf_apb_rst;
 	struct samsung_mipi_phy tx;
+	struct samsung_mipi_phy rx;
+	/* PHY mode, PHY_TYPE_DPHY or PHY_TYPE_CPHY. */
 	u8 type;
 
 	const struct samsung_mipi_dcphy_plat_data *pdata;
@@ -1508,6 +1510,22 @@ static int samsung_mipi_dcphy_exit(struct phy *phy)
 	return 0;
 }
 
+static int samsung_mipi_dcphy_rx_configure(struct phy *phy,
+					   union phy_configure_opts *opts)
+{
+	return -EOPNOTSUPP;
+}
+
+static int samsung_mipi_dcphy_rx_power_on(struct phy *phy)
+{
+	return -EOPNOTSUPP;
+}
+
+static int samsung_mipi_dcphy_rx_power_off(struct phy *phy)
+{
+	return -EOPNOTSUPP;
+}
+
 static const struct phy_ops samsung_mipi_dcphy_tx_ops = {
 	.configure = samsung_mipi_dcphy_tx_configure,
 	.power_on  = samsung_mipi_dcphy_tx_power_on,
@@ -1517,6 +1535,15 @@ static const struct phy_ops samsung_mipi_dcphy_tx_ops = {
 	.owner	   = THIS_MODULE,
 };
 
+static const struct phy_ops samsung_mipi_dcphy_rx_ops = {
+	.configure = samsung_mipi_dcphy_rx_configure,
+	.power_on  = samsung_mipi_dcphy_rx_power_on,
+	.power_off = samsung_mipi_dcphy_rx_power_off,
+	.init = samsung_mipi_dcphy_init,
+	.exit = samsung_mipi_dcphy_exit,
+	.owner	   = THIS_MODULE,
+};
+
 static const struct regmap_config samsung_mipi_dcphy_regmap_config = {
 	.name = "dcphy",
 	.reg_bits = 32,
@@ -1529,19 +1556,42 @@ static struct phy *samsung_mipi_dcphy_xlate(struct device *dev,
 					    const struct of_phandle_args *args)
 {
 	struct samsung_mipi_dcphy *samsung = dev_get_drvdata(dev);
+	/* Device trees without the second cell describe the transmitter. */
+	u32 protocol = PHY_TYPE_DSI;
+	u32 type;
 
-	if (args->args_count != 1) {
+	if (args->args_count < 1 || args->args_count > 2) {
 		dev_err(dev, "invalid number of arguments\n");
 		return ERR_PTR(-EINVAL);
 	}
 
-	if (samsung->type != PHY_NONE && samsung->type != args->args[0])
-		dev_warn(dev, "phy type select %d overwriting type %d\n",
-			 args->args[0], samsung->type);
+	type = args->args[0];
+	if (type != PHY_TYPE_DPHY && type != PHY_TYPE_CPHY) {
+		dev_err(dev, "invalid phy type %u\n", type);
+		return ERR_PTR(-EINVAL);
+	}
 
-	samsung->type = args->args[0];
+	if (args->args_count == 2)
+		protocol = args->args[1];
 
-	return samsung->tx.phy;
+	if (protocol != PHY_TYPE_DSI && protocol != PHY_TYPE_CSI) {
+		dev_err(dev, "invalid protocol %u\n", protocol);
+		return ERR_PTR(-EINVAL);
+	}
+
+	/*
+	 * The TRM (section 22.1) does not support the transmitter and the
+	 * receiver running in different modes, so the mode belongs to the
+	 * block.
+	 */
+	if (samsung->type != PHY_NONE && samsung->type != type) {
+		dev_err(dev, "phy type %u conflicts with type %u already selected\n",
+			type, samsung->type);
+		return ERR_PTR(-EINVAL);
+	}
+	samsung->type = type;
+
+	return protocol == PHY_TYPE_CSI ? samsung->rx.phy : samsung->tx.phy;
 }
 
 static int samsung_mipi_dcphy_probe(struct platform_device *pdev)
@@ -1617,6 +1667,13 @@ static int samsung_mipi_dcphy_probe(struct platform_device *pdev)
 
 	phy_set_drvdata(samsung->tx.phy, samsung);
 
+	samsung->rx.phy = devm_phy_create(dev, NULL, &samsung_mipi_dcphy_rx_ops);
+	if (IS_ERR(samsung->rx.phy))
+		return dev_err_probe(dev, PTR_ERR(samsung->rx.phy),
+				     "Failed to create MIPI DC-PHY receiver\n");
+
+	phy_set_drvdata(samsung->rx.phy, samsung);
+
 	phy_provider = devm_of_phy_provider_register(dev, samsung_mipi_dcphy_xlate);
 	if (IS_ERR(phy_provider))
 		return dev_err_probe(dev, PTR_ERR(phy_provider),

-- 
2.43.0



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

* [PATCH v4 7/7] phy: rockchip-samsung-dcphy: Add MIPI D-PHY receiver support
  2026-08-21 12:02 [PATCH v4 0/7] phy: rockchip-samsung-dcphy: Add the MIPI D-PHY receiver Jason Yang via B4 Relay
                   ` (5 preceding siblings ...)
  2026-08-21 12:02 ` [PATCH v4 6/7] phy: rockchip-samsung-dcphy: Add a second PHY for the receiver Jason Yang via B4 Relay
@ 2026-08-21 12:02 ` Jason Yang via B4 Relay
  6 siblings, 0 replies; 10+ messages in thread
From: Jason Yang via B4 Relay @ 2026-08-21 12:02 UTC (permalink / raw)
  To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Heiko Stuebner, Guochun Huang, Philipp Zabel
  Cc: Michael Riesch, Sebastian Reichel, Bryan O'Donoghue,
	linux-phy, devicetree, linux-arm-kernel, linux-rockchip,
	linux-kernel, Jason Yang

From: Jason Yang <jason98166@gmail.com>

Add the receiver (CSI) half of the block, so a MIPI CSI-2 camera can use
the same PHY that already drives a MIPI DSI output on RK3588. It follows
the receiver start-up sequence in the RK3588 TRM [1]. The HS-RX settle
values come from the RK3588 vendor kernel.

The initial deskew calibration that the D-PHY specification asks for
above 1.5 Gbps is not implemented; the vendor kernel programs it from
RK3576 onwards only.

Tested on RK3588 with an IMX219 on the receiver and a DSI panel on the
transmitter of the same PHY.

[1] RK3588 TRM: sections 22.6.3 (receiver start-up) and 22.6.4.3
    (worked receiver example)

Assisted-by: Claude:claude-fable-5
Signed-off-by: Jason Yang <jason98166@gmail.com>
---
 drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c | 386 +++++++++++++++++++++-
 1 file changed, 383 insertions(+), 3 deletions(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c b/drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c
index d27a5916bd40..947ce7a09c7c 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c
@@ -244,6 +244,63 @@
 #define T_TA_GET(x)		FIELD_PREP(GENMASK(7, 4), x)
 #define T_TA_GO(x)		FIELD_PREP(GENMASK(3, 0), x)
 
+/* D-PHY receiver registers (clock lane + four data lanes) */
+#define DPHY_SC_GNR_CON0	0x0b00
+#define DPHY_SC_GNR_CON1	0x0b04
+#define DPHY_SC_ANA_CON1	0x0b0c
+#define HS_RX_BIAS_CON(x)	FIELD_PREP(GENMASK(15, 11), x)
+#define DPHY_SC_ANA_CON2	0x0b10
+#define HS_TERM_SW(x)		FIELD_PREP(GENMASK(2, 0), x)
+#define DPHY_SC_ANA_CON3	0x0b14
+#define ULPS_HYS_SW_DPHY(x)	FIELD_PREP(GENMASK(10, 8), x)
+#define DPHY_SC_TIME_CON0	0x0b30
+#define T_CLK_SETTLE(x)		FIELD_PREP(GENMASK(7, 0), x)
+#define T_CLK_MISS(x)		FIELD_PREP(GENMASK(11, 8), x)
+#define COMBO_SD0_GNR_CON0	0x0c00
+#define COMBO_SD0_GNR_CON1	0x0c04
+#define COMBO_SD0_ANA_CON1	0x0c0c
+#define COMBO_SD0_ANA_CON2	0x0c10
+#define SKEW_DLYSEL(x)		FIELD_PREP(GENMASK(9, 8), x)
+#define RX_TERM_SW(x)		FIELD_PREP(GENMASK(2, 0), x)
+#define COMBO_SD0_ANA_CON3	0x0c14
+#define SEL_ESCPOL		BIT(11)
+#define LP_HYS_SW(x)		FIELD_PREP(GENMASK(5, 4), x)
+#define COMBO_SD0_ANA_CON7	0x0c24
+#define CLK_DBL_CTRL(x)		FIELD_PREP(GENMASK(7, 6), x)
+#define COMBO_SD0_TIME_CON0	0x0c30
+#define T_HS_SETTLE(x)		FIELD_PREP(GENMASK(7, 0), x)
+#define SETTLE_CLK_SEL		BIT(8)
+#define COMBO_SD0_TIME_CON1	0x0c34
+#define T_ERR_SOT_SYNC(x)	FIELD_PREP(GENMASK(7, 0), x)
+#define COMBO_SD0_DESKEW_CON2	0x0c48
+#define SKEW_CAL_CLK_COARSE_SET(x) FIELD_PREP(GENMASK(4, 0), x)
+#define COMBO_SD1_GNR_CON0	0x0d00
+#define COMBO_SD1_GNR_CON1	0x0d04
+#define COMBO_SD1_ANA_CON1	0x0d0c
+#define COMBO_SD1_ANA_CON2	0x0d10
+#define COMBO_SD1_ANA_CON3	0x0d14
+#define COMBO_SD1_ANA_CON7	0x0d24
+#define COMBO_SD1_TIME_CON0	0x0d30
+#define COMBO_SD1_TIME_CON1	0x0d34
+#define COMBO_SD1_DESKEW_CON2	0x0d48
+#define COMBO_SD2_GNR_CON0	0x0e00
+#define COMBO_SD2_GNR_CON1	0x0e04
+#define COMBO_SD2_ANA_CON1	0x0e0c
+#define COMBO_SD2_ANA_CON2	0x0e10
+#define COMBO_SD2_ANA_CON3	0x0e14
+#define COMBO_SD2_ANA_CON7	0x0e24
+#define COMBO_SD2_TIME_CON0	0x0e30
+#define COMBO_SD2_TIME_CON1	0x0e34
+#define COMBO_SD2_DESKEW_CON2	0x0e48
+#define DPHY_SD3_GNR_CON0	0x0f00
+#define DPHY_SD3_GNR_CON1	0x0f04
+#define DPHY_SD3_ANA_CON1	0x0f0c
+#define DPHY_SD3_ANA_CON2	0x0f10
+#define DPHY_SD3_ANA_CON3	0x0f14
+#define DPHY_SD3_TIME_CON0	0x0f30
+#define DPHY_SD3_TIME_CON1	0x0f34
+#define DPHY_SD3_DESKEW_CON2	0x0f48
+
 /* MIPI_CDPHY_GRF registers */
 #define MIPI_DCPHY_GRF_CON0		0x0000
 #define S_CPHY_MODE			FIELD_PREP_WM16(BIT(3), 1)
@@ -283,6 +340,7 @@ struct samsung_mipi_dcphy_plat_data {
 struct samsung_mipi_phy {
 	struct phy *phy;
 	unsigned int lanes;
+	unsigned long long hs_clk_rate;
 };
 
 struct samsung_mipi_dcphy {
@@ -979,6 +1037,260 @@ struct samsung_mipi_dphy_timing samsung_mipi_dphy_timing_table[] = {
 	{  80,  2,   0,  0, 28,  5,  0, 22,  2,  0,  5},
 };
 
+/* D-PHY receiver HS-RX configuration lookup */
+struct samsung_mipi_dphy_rx_hsfreq_range {
+	u32 range_h_mbps;
+	u16 cfg_bit;
+};
+
+/*
+ * HS RX settle values taken verbatim from the rk3588 vendor kernel.
+ * The TRM defines these fields but defers the per-data-rate table to a
+ * timing supplement. Each cfg_bit is a pre-combined SETTLE_CLK_SEL |
+ * T_HS_SETTLE value for the data-lane TIME_CON0: bit 8 selects the
+ * divide-by-2 settle clock below 1500 Mbps per the TRM (the vendor
+ * table switches one bucket early, at 1490 Mbps, and is kept
+ * unchanged). The TRM marks bit 8 read-only, but the vendor kernel has
+ * always programmed it. Sorted by .range_h_mbps ascending.
+ */
+static const struct samsung_mipi_dphy_rx_hsfreq_range samsung_mipi_dphy_rx_hsfreq_ranges[] = {
+	{   80, 0x105 }, {  100, 0x106 }, {  120, 0x107 }, {  140, 0x108 },
+	{  160, 0x109 }, {  180, 0x10a }, {  200, 0x10b }, {  220, 0x10c },
+	{  240, 0x10d }, {  270, 0x10e }, {  290, 0x10f }, {  310, 0x110 },
+	{  330, 0x111 }, {  350, 0x112 }, {  370, 0x113 }, {  390, 0x114 },
+	{  410, 0x115 }, {  430, 0x116 }, {  450, 0x117 }, {  470, 0x118 },
+	{  490, 0x119 }, {  510, 0x11a }, {  540, 0x11b }, {  560, 0x11c },
+	{  580, 0x11d }, {  600, 0x11e }, {  620, 0x11f }, {  640, 0x120 },
+	{  660, 0x121 }, {  680, 0x122 }, {  700, 0x123 }, {  720, 0x124 },
+	{  740, 0x125 }, {  760, 0x126 }, {  790, 0x127 }, {  810, 0x128 },
+	{  830, 0x129 }, {  850, 0x12a }, {  870, 0x12b }, {  890, 0x12c },
+	{  910, 0x12d }, {  930, 0x12e }, {  950, 0x12f }, {  970, 0x130 },
+	{  990, 0x131 }, { 1010, 0x132 }, { 1030, 0x133 }, { 1060, 0x134 },
+	{ 1080, 0x135 }, { 1100, 0x136 }, { 1120, 0x137 }, { 1140, 0x138 },
+	{ 1160, 0x139 }, { 1180, 0x13a }, { 1200, 0x13b }, { 1220, 0x13c },
+	{ 1240, 0x13d }, { 1260, 0x13e }, { 1280, 0x13f }, { 1310, 0x140 },
+	{ 1330, 0x141 }, { 1350, 0x142 }, { 1370, 0x143 }, { 1390, 0x144 },
+	{ 1410, 0x145 }, { 1430, 0x146 }, { 1450, 0x147 }, { 1470, 0x148 },
+	{ 1490, 0x149 }, { 1580, 0x007 }, { 1740, 0x008 }, { 1910, 0x009 },
+	{ 2070, 0x00a }, { 2240, 0x00b }, { 2410, 0x00c }, { 2570, 0x00d },
+	{ 2740, 0x00e }, { 2910, 0x00f }, { 3070, 0x010 }, { 3240, 0x011 },
+	{ 3410, 0x012 }, { 3570, 0x013 }, { 3740, 0x014 }, { 3890, 0x015 },
+	{ 4070, 0x016 }, { 4240, 0x017 }, { 4400, 0x018 }, { 4500, 0x019 },
+};
+
+static int samsung_mipi_dphy_rx_lookup_hsfreq(u32 lane_mbps, u16 *cfg_bit)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(samsung_mipi_dphy_rx_hsfreq_ranges); i++) {
+		if (lane_mbps <= samsung_mipi_dphy_rx_hsfreq_ranges[i].range_h_mbps) {
+			*cfg_bit = samsung_mipi_dphy_rx_hsfreq_ranges[i].cfg_bit;
+			return 0;
+		}
+	}
+
+	return -ERANGE;
+}
+
+/* SKEW_DLYSEL per data rate, from the RK3588 TRM ANA_CON2 description */
+static u32 samsung_mipi_dphy_rx_data_lane_dlysel(u32 lane_mbps)
+{
+	if (lane_mbps < 1500)
+		return 0;
+	if (lane_mbps < 2000)
+		return SKEW_DLYSEL(3);
+	if (lane_mbps < 3000)
+		return SKEW_DLYSEL(2);
+	if (lane_mbps < 4000)
+		return SKEW_DLYSEL(1);
+	return 0;
+}
+
+/*
+ * Per-data-lane register bases, indexed by lane number. The clock lane
+ * shares the same block spacing but is programmed separately: its
+ * TIME_CON0 holds T_CLK_SETTLE/T_CLK_MISS rather than the per-rate
+ * T_HS_SETTLE/SETTLE_CLK_SEL, and it has no deskew configuration.
+ */
+static const u32 rx_data_lane_gnr_con0[] = {
+	COMBO_SD0_GNR_CON0, COMBO_SD1_GNR_CON0,
+	COMBO_SD2_GNR_CON0, DPHY_SD3_GNR_CON0,
+};
+
+static const u32 rx_data_lane_gnr_con1[] = {
+	COMBO_SD0_GNR_CON1, COMBO_SD1_GNR_CON1,
+	COMBO_SD2_GNR_CON1, DPHY_SD3_GNR_CON1,
+};
+
+static const u32 rx_lane_time_con0[] = {
+	COMBO_SD0_TIME_CON0, COMBO_SD1_TIME_CON0,
+	COMBO_SD2_TIME_CON0, DPHY_SD3_TIME_CON0,
+};
+
+static const u32 rx_lane_time_con1[] = {
+	COMBO_SD0_TIME_CON1, COMBO_SD1_TIME_CON1,
+	COMBO_SD2_TIME_CON1, DPHY_SD3_TIME_CON1,
+};
+
+/*
+ * These RX analog tuning values come from the vendor kernel. The
+ * termination (RX_TERM_SW/HS_TERM_SW = 2) is the 96.6 ohm setting the
+ * TRM ANA_CON2 value list annotates as the default, although the
+ * register itself resets to 102 ohm. Data lane 0 differs on purpose:
+ * the vendor's default receive profile applies the LP hysteresis and
+ * the swapped escape clock polarity to lane 0 only, and no manual
+ * skew-calibration delay there against three 30 ps steps on the other
+ * lanes. Data lane 3 is a plain D-PHY lane with no ANA_CON7, so it
+ * gets no CLK_DBL_CTRL write.
+ */
+static void samsung_mipi_dphy_rx_config_common(struct samsung_mipi_dcphy *samsung)
+{
+	struct samsung_mipi_phy *rx = &samsung->rx;
+	u32 dlysel = samsung_mipi_dphy_rx_data_lane_dlysel(div_u64(rx->hs_clk_rate,
+								   1000000));
+	u32 ana_con2_common = dlysel | RX_TERM_SW(2);
+
+	/* Clock lane */
+	regmap_write(samsung->regmap, DPHY_SC_ANA_CON1, HS_RX_BIAS_CON(0x10));
+	regmap_write(samsung->regmap, DPHY_SC_ANA_CON2, HS_TERM_SW(2));
+	regmap_write(samsung->regmap, DPHY_SC_ANA_CON3, ULPS_HYS_SW_DPHY(6));
+
+	/* Data lane 0; a zero lane count is rejected at power-on */
+	regmap_write(samsung->regmap, COMBO_SD0_ANA_CON1, HS_RX_BIAS_CON(0x10));
+	regmap_write(samsung->regmap, COMBO_SD0_ANA_CON2, ana_con2_common);
+	regmap_write(samsung->regmap, COMBO_SD0_ANA_CON3,
+		     ULPS_HYS_SW_DPHY(6) | LP_HYS_SW(3) | SEL_ESCPOL);
+	regmap_write(samsung->regmap, COMBO_SD0_ANA_CON7, CLK_DBL_CTRL(1));
+	regmap_write(samsung->regmap, COMBO_SD0_DESKEW_CON2,
+		     SKEW_CAL_CLK_COARSE_SET(0));
+
+	/* Data lane 1 */
+	if (rx->lanes > 1) {
+		regmap_write(samsung->regmap, COMBO_SD1_ANA_CON1,
+			     HS_RX_BIAS_CON(0x10));
+		regmap_write(samsung->regmap, COMBO_SD1_ANA_CON2,
+			     ana_con2_common);
+		regmap_write(samsung->regmap, COMBO_SD1_ANA_CON3,
+			     ULPS_HYS_SW_DPHY(6));
+		regmap_write(samsung->regmap, COMBO_SD1_ANA_CON7,
+			     CLK_DBL_CTRL(1));
+		regmap_write(samsung->regmap, COMBO_SD1_DESKEW_CON2,
+			     SKEW_CAL_CLK_COARSE_SET(3));
+	}
+
+	/* Data lane 2 */
+	if (rx->lanes > 2) {
+		regmap_write(samsung->regmap, COMBO_SD2_ANA_CON1,
+			     HS_RX_BIAS_CON(0x10));
+		regmap_write(samsung->regmap, COMBO_SD2_ANA_CON2,
+			     ana_con2_common);
+		regmap_write(samsung->regmap, COMBO_SD2_ANA_CON3,
+			     ULPS_HYS_SW_DPHY(6));
+		regmap_write(samsung->regmap, COMBO_SD2_ANA_CON7,
+			     CLK_DBL_CTRL(1));
+		regmap_write(samsung->regmap, COMBO_SD2_DESKEW_CON2,
+			     SKEW_CAL_CLK_COARSE_SET(3));
+	}
+
+	/* Data lane 3 */
+	if (rx->lanes > 3) {
+		regmap_write(samsung->regmap, DPHY_SD3_ANA_CON1,
+			     HS_RX_BIAS_CON(0x10));
+		regmap_write(samsung->regmap, DPHY_SD3_ANA_CON2,
+			     ana_con2_common);
+		regmap_write(samsung->regmap, DPHY_SD3_ANA_CON3,
+			     ULPS_HYS_SW_DPHY(6));
+		regmap_write(samsung->regmap, DPHY_SD3_DESKEW_CON2,
+			     SKEW_CAL_CLK_COARSE_SET(3));
+	}
+}
+
+static int samsung_mipi_dphy_rx_config_settle(struct samsung_mipi_dcphy *samsung)
+{
+	struct samsung_mipi_phy *rx = &samsung->rx;
+	u32 lane_mbps = div_u64(rx->hs_clk_rate, 1000000);
+	unsigned int i;
+	u16 cfg_bit;
+	int ret;
+
+	ret = samsung_mipi_dphy_rx_lookup_hsfreq(lane_mbps, &cfg_bit);
+	if (ret) {
+		dev_err(samsung->dev, "no RX hsfreq cfg for %u Mbps\n",
+			lane_mbps);
+		return ret;
+	}
+
+	/*
+	 * Clock-lane settle uses the fixed value from the TRM RX bring-up
+	 * example, unlike the per-rate data-lane settle below.
+	 */
+	regmap_write(samsung->regmap, DPHY_SC_TIME_CON0,
+		     T_CLK_SETTLE(0x01) | T_CLK_MISS(0x03));
+
+	for (i = 0; i < rx->lanes; i++) {
+		regmap_update_bits(samsung->regmap, rx_lane_time_con0[i],
+				   T_HS_SETTLE(0xff) | SETTLE_CLK_SEL, cfg_bit);
+		regmap_update_bits(samsung->regmap, rx_lane_time_con1[i],
+				   T_ERR_SOT_SYNC(0xff), T_ERR_SOT_SYNC(0x03));
+	}
+
+	return 0;
+}
+
+static void samsung_mipi_dphy_rx_lane_disable(struct samsung_mipi_dcphy *samsung)
+{
+	struct samsung_mipi_phy *rx = &samsung->rx;
+	unsigned int i;
+
+	regmap_update_bits(samsung->regmap, DPHY_SC_GNR_CON0, PHY_ENABLE, 0);
+	for (i = 0; i < rx->lanes; i++)
+		regmap_update_bits(samsung->regmap, rx_data_lane_gnr_con0[i],
+				   PHY_ENABLE, 0);
+}
+
+static int samsung_mipi_dphy_rx_lane_enable(struct samsung_mipi_dcphy *samsung)
+{
+	struct samsung_mipi_phy *rx = &samsung->rx;
+	unsigned int i;
+	u32 sts;
+	int ret;
+
+	regmap_write(samsung->regmap, DPHY_SC_GNR_CON1, T_PHY_READY(0x1450));
+	regmap_update_bits(samsung->regmap, DPHY_SC_GNR_CON0,
+			   PHY_ENABLE, PHY_ENABLE);
+
+	for (i = 0; i < rx->lanes; i++) {
+		regmap_write(samsung->regmap, rx_data_lane_gnr_con1[i],
+			     T_PHY_READY(0x1450));
+		regmap_update_bits(samsung->regmap, rx_data_lane_gnr_con0[i],
+				   PHY_ENABLE, PHY_ENABLE);
+	}
+
+	ret = regmap_read_poll_timeout(samsung->regmap, DPHY_SC_GNR_CON0,
+				       sts, sts & PHY_READY, 200, 4000);
+	if (ret) {
+		dev_err(samsung->dev, "RX clock lane not ready\n");
+		goto err_lane_disable;
+	}
+
+	for (i = 0; i < rx->lanes; i++) {
+		ret = regmap_read_poll_timeout(samsung->regmap,
+					       rx_data_lane_gnr_con0[i],
+					       sts, sts & PHY_READY,
+					       200, 2000);
+		if (ret) {
+			dev_err(samsung->dev, "RX data lane %u not ready\n", i);
+			goto err_lane_disable;
+		}
+	}
+
+	return 0;
+
+err_lane_disable:
+	samsung_mipi_dphy_rx_lane_disable(samsung);
+	return ret;
+}
+
 static void samsung_mipi_dcphy_bias_block_enable(struct samsung_mipi_dcphy *samsung)
 {
 	regmap_write(samsung->regmap, BIAS_CON0, I_DEV_DIV_6 | I_RES_100_2UA);
@@ -988,6 +1300,55 @@ static void samsung_mipi_dcphy_bias_block_enable(struct samsung_mipi_dcphy *sams
 						 REG_400M_400MV | REG_645M_645MV);
 }
 
+static int samsung_mipi_dphy_rx_power_on(struct samsung_mipi_dcphy *samsung)
+{
+	struct samsung_mipi_phy *rx = &samsung->rx;
+	int ret;
+
+	if (!rx->hs_clk_rate || !rx->lanes)
+		return -EINVAL;
+
+	reset_control_assert(samsung->s_phy_rst);
+
+	/* default output voltage select:
+	 * dphy: 400mv
+	 * cphy: 530mv
+	 */
+	regmap_update_bits(samsung->regmap, BIAS_CON4,
+			   I_MUX_SEL_MASK, I_MUX_400MV);
+
+	samsung_mipi_dphy_rx_config_common(samsung);
+
+	ret = samsung_mipi_dphy_rx_config_settle(samsung);
+	if (ret)
+		goto out_deassert;
+
+	ret = samsung_mipi_dphy_rx_lane_enable(samsung);
+
+out_deassert:
+	reset_control_deassert(samsung->s_phy_rst);
+
+	return ret;
+}
+
+static int samsung_mipi_dphy_rx_power_off(struct samsung_mipi_dcphy *samsung)
+{
+	reset_control_assert(samsung->s_phy_rst);
+
+	samsung_mipi_dphy_rx_lane_disable(samsung);
+
+	reset_control_deassert(samsung->s_phy_rst);
+
+	/*
+	 * Let the lanes settle out of reset before the receiver may be
+	 * brought up again. The delay follows the vendor driver; the TRM
+	 * does not document a teardown sequence.
+	 */
+	usleep_range(500, 1000);
+
+	return 0;
+}
+
 static void samsung_mipi_dphy_tx_lane_enable(struct samsung_mipi_dcphy *samsung)
 {
 	regmap_write(samsung->regmap, DPHY_MC_GNR_CON1, T_PHY_READY(0x2000));
@@ -1513,17 +1874,36 @@ static int samsung_mipi_dcphy_exit(struct phy *phy)
 static int samsung_mipi_dcphy_rx_configure(struct phy *phy,
 					   union phy_configure_opts *opts)
 {
-	return -EOPNOTSUPP;
+	struct samsung_mipi_dcphy *samsung = phy_get_drvdata(phy);
+
+	samsung->rx.lanes = opts->mipi_dphy.lanes > 4 ? 4 : opts->mipi_dphy.lanes;
+
+	/* The sensor supplies the link clock, so the PLL stays off. */
+	samsung->rx.hs_clk_rate = opts->mipi_dphy.hs_clk_rate;
+
+	return 0;
 }
 
 static int samsung_mipi_dcphy_rx_power_on(struct phy *phy)
 {
-	return -EOPNOTSUPP;
+	struct samsung_mipi_dcphy *samsung = phy_get_drvdata(phy);
+
+	/* CPHY part to be implemented later */
+	if (samsung->type != PHY_TYPE_DPHY)
+		return -EOPNOTSUPP;
+
+	return samsung_mipi_dphy_rx_power_on(samsung);
 }
 
 static int samsung_mipi_dcphy_rx_power_off(struct phy *phy)
 {
-	return -EOPNOTSUPP;
+	struct samsung_mipi_dcphy *samsung = phy_get_drvdata(phy);
+
+	/* CPHY part to be implemented later */
+	if (samsung->type != PHY_TYPE_DPHY)
+		return -EOPNOTSUPP;
+
+	return samsung_mipi_dphy_rx_power_off(samsung);
 }
 
 static const struct phy_ops samsung_mipi_dcphy_tx_ops = {

-- 
2.43.0



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

* Re: [PATCH v4 1/7] dt-bindings: phy: Add PHY_TYPE_DSI and PHY_TYPE_CSI definitions
  2026-08-21 12:02 ` [PATCH v4 1/7] dt-bindings: phy: Add PHY_TYPE_DSI and PHY_TYPE_CSI definitions Jason Yang via B4 Relay
@ 2026-08-27 11:45   ` Krzysztof Kozlowski
  0 siblings, 0 replies; 10+ messages in thread
From: Krzysztof Kozlowski @ 2026-08-27 11:45 UTC (permalink / raw)
  To: Jason Yang
  Cc: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Heiko Stuebner, Guochun Huang, Philipp Zabel,
	Michael Riesch, Sebastian Reichel, Bryan O'Donoghue,
	linux-phy, devicetree, linux-arm-kernel, linux-rockchip,
	linux-kernel

On Fri, Aug 21, 2026 at 08:02:29PM +0800, Jason Yang wrote:
> A MIPI D-PHY or C-PHY can be a transmitter (DSI) or a receiver (CSI),
> and in some PHY blocks both work at the same time. The existing
> PHY_TYPE_DPHY and PHY_TYPE_CPHY cannot tell whether a consumer wants
> the transmitter or the receiver.

The consumer knows this already, no? Imagine consumer of the phy is some
ISP receiving data over CSI for given port, thus consumer cannot
transmit over that link.

All this seems redundant.

> 
> Add PHY_TYPE_DSI and PHY_TYPE_CSI, so that a binding can select both
> D-PHY or C-PHY and transmitter or receiver. They do not replace
> PHY_TYPE_DPHY/PHY_TYPE_CPHY, which remain the right choice where a cell
> selects the mode. The first user is the Rockchip RK3588 MIPI DC-PHY
> binding.
> 
> Suggested-by: Michael Riesch <michael.riesch@collabora.com>
> Link: https://lore.kernel.org/r/82da3622-9c3a-454c-87bc-fb4ec7adb68d@collabora.com
> Signed-off-by: Jason Yang <jason98166@gmail.com>

Where is any DTS using it? I did a search and no results of upstream
posting.

> ---
>  include/dt-bindings/phy/phy.h | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/include/dt-bindings/phy/phy.h b/include/dt-bindings/phy/phy.h
> index 979b5dfd8353..8ee3f88e6d80 100644
> --- a/include/dt-bindings/phy/phy.h
> +++ b/include/dt-bindings/phy/phy.h
> @@ -24,6 +24,8 @@
>  #define PHY_TYPE_CPHY		11
>  #define PHY_TYPE_USXGMII	12
>  #define PHY_TYPE_XAUI		13
> +#define PHY_TYPE_DSI		14
> +#define PHY_TYPE_CSI		15

DSI and CSI does not look like types of PHY...

Best regards,
Krzysztof


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

* Re: [PATCH v4 2/7] dt-bindings: phy: rockchip,rk3588-mipi-dcphy: Allow DSI and CSI consumers
  2026-08-21 12:02 ` [PATCH v4 2/7] dt-bindings: phy: rockchip,rk3588-mipi-dcphy: Allow DSI and CSI consumers Jason Yang via B4 Relay
@ 2026-08-27 11:47   ` Krzysztof Kozlowski
  0 siblings, 0 replies; 10+ messages in thread
From: Krzysztof Kozlowski @ 2026-08-27 11:47 UTC (permalink / raw)
  To: Jason Yang
  Cc: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Heiko Stuebner, Guochun Huang, Philipp Zabel,
	Michael Riesch, Sebastian Reichel, Bryan O'Donoghue,
	linux-phy, devicetree, linux-arm-kernel, linux-rockchip,
	linux-kernel

On Fri, Aug 21, 2026 at 08:02:30PM +0800, Jason Yang wrote:
> The Samsung MIPI D-/C-PHY block on RK3588 and RK3576 has a transmitter
> (DSI) and a receiver (CSI) on the same PHY, and two drivers can use them

Please link/show the upstream DTS using simultaneously transmitter and
receiver, where the consumer does not know with whom is it talking to.

Best regards,
Krzysztof


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

end of thread, other threads:[~2026-08-27 11:47 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-21 12:02 [PATCH v4 0/7] phy: rockchip-samsung-dcphy: Add the MIPI D-PHY receiver Jason Yang via B4 Relay
2026-08-21 12:02 ` [PATCH v4 1/7] dt-bindings: phy: Add PHY_TYPE_DSI and PHY_TYPE_CSI definitions Jason Yang via B4 Relay
2026-08-27 11:45   ` Krzysztof Kozlowski
2026-08-21 12:02 ` [PATCH v4 2/7] dt-bindings: phy: rockchip,rk3588-mipi-dcphy: Allow DSI and CSI consumers Jason Yang via B4 Relay
2026-08-27 11:47   ` Krzysztof Kozlowski
2026-08-21 12:02 ` [PATCH v4 3/7] phy: rockchip-samsung-dcphy: Move block-level setup to runtime resume Jason Yang via B4 Relay
2026-08-21 12:02 ` [PATCH v4 4/7] phy: rockchip-samsung-dcphy: Name the transmitter helpers and ops Jason Yang via B4 Relay
2026-08-21 12:02 ` [PATCH v4 5/7] phy: rockchip-samsung-dcphy: Factor the transmitter teardown into a helper Jason Yang via B4 Relay
2026-08-21 12:02 ` [PATCH v4 6/7] phy: rockchip-samsung-dcphy: Add a second PHY for the receiver Jason Yang via B4 Relay
2026-08-21 12:02 ` [PATCH v4 7/7] phy: rockchip-samsung-dcphy: Add MIPI D-PHY receiver support Jason Yang via B4 Relay

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