On 10/13/26 19:08, Balaji Selvanathan wrote:
The TypeC port-select mux was always programmed with SW_PORTSELECT_MUX
set and SW_PORTSELECT_VAL left clear, regardless of which way the
USB-C cable was inserted. On a board where the cable goes in reversed,
the SuperSpeed/DP lanes end up routed to the wrong side of the
connector, so USB3/DP never comes up correctly.

Cable orientation is reported by a GPIO on the qcom,pmic-glink node
("orientation-gpios"), and is now sampled each time the PHY is
enabled to check for the orientation.

Taken from Linux commit 815891eee668 ("phy: qcom-qmp-combo: Introduce
orientation variable").

Tested on QCS6490 RB3 Gen2 board.

Signed-off-by: Balaji Selvanathan <[email protected]>
---
Changes in v2:
- Instead of reading the orientation at probe, read it only during the PHY init
- Updated the commit message to better explain why this change is required
- Link to v1: 
https://lore.kernel.org/u-boot/20260724-kodiak_ss_orientation-v1-1-d9d8fd271...@oss.qualcomm.com/
---
  drivers/phy/qcom/phy-qcom-qmp-combo.c | 26 ++++++++++++++++++++++++++
  1 file changed, 26 insertions(+)

diff --git a/drivers/phy/qcom/phy-qcom-qmp-combo.c 
b/drivers/phy/qcom/phy-qcom-qmp-combo.c
index 0d63e482ee4..65141489d51 100644
--- a/drivers/phy/qcom/phy-qcom-qmp-combo.c
+++ b/drivers/phy/qcom/phy-qcom-qmp-combo.c
@@ -7,10 +7,12 @@
  #include <dm.h>
  #include <dm/device_compat.h>
  #include <dm/devres.h>
+#include <dm/ofnode.h>
  #include <generic-phy.h>
  #include <reset.h>
  #include <power/regulator.h>
  #include <asm/io.h>
+#include <asm-generic/gpio.h>
  #include <linux/bitops.h>
  #include <linux/compat.h>
  #include <linux/delay.h>
@@ -39,6 +41,7 @@
  #define DP_MODE                                 BIT(1) /* enables DP mode */
/* QPHY_V3_DP_COM_TYPEC_CTRL register bits */
+#define SW_PORTSELECT_VAL                       BIT(0)
  #define SW_PORTSELECT_MUX                       BIT(1)
/* PHY slot identifiers for device tree phandle arguments */
@@ -283,6 +286,27 @@ static int qmp_combo_com_exit(struct qmp_combo *qmp)
        return 0;
  }
+static bool qmp_combo_read_orientation(void)
+{
+       ofnode node;
+       struct gpio_desc desc;
+       int ret, val;
+
+       node = ofnode_by_compatible(ofnode_null(), "qcom,pmic-glink");
+       if (!ofnode_valid(node))
+               return false;
+
+       ret = gpio_request_by_name_nodev(node, "orientation-gpios", 0,
+                                        &desc, GPIOD_IS_IN);
+       if (ret)
+               return false;

So yes it will work with single-usb platforms, but will severely break
the other platforms with multiple controllers (X1, ...).

The real way to fix this is by following the graph to the pmic-glink,
not the simplest but not the hardest, and there's all the required functions
to do that in dm/ofnode_graph.h

The path is:
qmp-combo/port0 -> redriver/port@1 -> redriver/port@0 -> connector@0/port@0

get the connector reg and use this as index of the orientation-gpios.

Neil

+
+       val = dm_gpio_get_value(&desc);
+       dm_gpio_free(desc.dev, &desc);
+
+       return val > 0;
+}
+
  static int qmp_combo_com_init(struct qmp_combo *qmp)
  {
        void __iomem *com = qmp->com;
@@ -333,6 +357,8 @@ static int qmp_combo_com_init(struct qmp_combo *qmp)
                     SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET);
val = SW_PORTSELECT_MUX;
+       if (qmp_combo_read_orientation())
+               val |= SW_PORTSELECT_VAL;
        writel(val, com + QPHY_V3_DP_COM_TYPEC_CTRL);
writel(USB3_MODE | DP_MODE, com + QPHY_V3_DP_COM_PHY_MODE_CTRL);

---
base-commit: fed92546960a92177d67c0b8d7b22385f50fed29
change-id: 20261013-ss-orientation-d85a156e806a

Best regards,

Reply via email to