Read the USB-C cable orientation from the orientation-gpios
property on the qcom,pmic-glink node and use it when programming
the TypeC port-select mux.
Taken from Linux commit 815891eee668 ("phy: qcom-qmp-combo: Introduce
orientation variable")
Previously the driver always set SW_PORTSELECT_MUX without
accounting for cable orientation, so the SuperSpeed/DP lanes could
be routed to the wrong side of the connector on boards where the
cable was flipped. Now orientation is read once during DT parsing
and SW_PORTSELECT_VAL is added to the mux value when a reversed
orientation is detected.
Tested on QCS6490 RB3 Gen2 board.
Signed-off-by: Balaji Selvanathan <[email protected]>
---
drivers/phy/qcom/phy-qcom-qmp-combo.c | 35 +++++++++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
diff --git a/drivers/phy/qcom/phy-qcom-qmp-combo.c
b/drivers/phy/qcom/phy-qcom-qmp-combo.c
index 0d63e482ee4..615d481513f 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 */
@@ -238,6 +241,7 @@ struct qmp_combo {
struct udevice **vregs;
int num_vregs;
const struct qmp_phy_cfg *cfg;
+ bool orientation_reversed;
};
static inline void qphy_setbits(void __iomem *base, u32 offset, u32 val)
@@ -333,6 +337,8 @@ static int qmp_combo_com_init(struct qmp_combo *qmp)
SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET);
val = SW_PORTSELECT_MUX;
+ if (qmp->orientation_reversed)
+ 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);
@@ -521,6 +527,33 @@ static int qmp_combo_vreg_init(struct qmp_combo *qmp)
return 0;
}
+/*
+ * The orientation of the USB-C connector on this platform is reported by a
+ * single GPIO exposed on the "qcom,pmic-glink" node ("orientation-gpios").
+ * Read it once here so the port-select mux can be programmed to
+ * match physical cable orientation.
+ */
+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;
+
+ val = dm_gpio_get_value(&desc);
+ dm_gpio_free(desc.dev, &desc);
+
+ return val > 0;
+}
+
static int qmp_combo_parse_dt(struct qmp_combo *qmp)
{
const struct qmp_phy_cfg *cfg = qmp->cfg;
@@ -536,6 +569,8 @@ static int qmp_combo_parse_dt(struct qmp_combo *qmp)
if (IS_ERR(base))
return PTR_ERR(base);
+ qmp->orientation_reversed = qmp_combo_read_orientation();
+
qmp->com = base + offs->com;
qmp->serdes = base + offs->usb3_serdes;
qmp->tx = base + offs->txa;
---
base-commit: d7ef23c07b8e34f65b3e15e3b4e7f58d074923c8
change-id: 20260724-kodiak_ss_orientation-b171351c78b7
Best regards,
--
Balaji Selvanathan <[email protected]>