Thread (11 messages) 11 messages, 2 authors, 2025-09-11

Re: [RESEND v4 3/4] extcon: ptn5150: Add Type-C orientation switch support

From: Chanwoo Choi <chanwoo@kernel.org>
Date: 2025-09-09 15:34:54
Also in: imx, lkml

Hi,

Applied it. Thanks.

On Mon, Sep 8, 2025 at 2:34 PM Xu Yang [off-list ref] wrote:
quoted hunk ↗ jump to hunk
PTN5150 is able to detect CC polarity. The field[1:0] of CC status
register (04H) will keep the result.

  00: Cable Not Attached
  01: CC1 is connected (normal orientation)
  10: CC2 is connected (reversed orientation)
  11: Reserved

Add orientation switch support to correctly set orientation of
multiplexer according to CC status.

Reviewed-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Xu Yang <xu.yang_2@nxp.com>

---
Changes in v4:
 - add Rb tag
Changes in v3:
 - no changes
Changes in v2:
 - move "enum typec_orientation orient" ahead
 - improve commit message
---
 drivers/extcon/Kconfig          |  1 +
 drivers/extcon/extcon-ptn5150.c | 40 +++++++++++++++++++++++++++++++++
 2 files changed, 41 insertions(+)
diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig
index a6f6d467aacf..fd4ec5dda0b7 100644
--- a/drivers/extcon/Kconfig
+++ b/drivers/extcon/Kconfig
@@ -145,6 +145,7 @@ config EXTCON_PTN5150
        tristate "NXP PTN5150 CC LOGIC USB EXTCON support"
        depends on I2C && (GPIOLIB || COMPILE_TEST)
        depends on USB_ROLE_SWITCH || !USB_ROLE_SWITCH
+       depends on TYPEC || !TYPEC
        select REGMAP_I2C
        help
          Say Y here to enable support for USB peripheral and USB host
diff --git a/drivers/extcon/extcon-ptn5150.c b/drivers/extcon/extcon-ptn5150.c
index 78ad86c4a3be..768428d306ce 100644
--- a/drivers/extcon/extcon-ptn5150.c
+++ b/drivers/extcon/extcon-ptn5150.c
@@ -18,6 +18,7 @@
 #include <linux/extcon-provider.h>
 #include <linux/gpio/consumer.h>
 #include <linux/usb/role.h>
+#include <linux/usb/typec_mux.h>

 /* PTN5150 registers */
 #define PTN5150_REG_DEVICE_ID                  0x01
@@ -38,7 +39,11 @@
 #define PTN5150_REG_DEVICE_ID_VERSION          GENMASK(7, 3)
 #define PTN5150_REG_DEVICE_ID_VENDOR           GENMASK(2, 0)

+#define PTN5150_POLARITY_CC1                   0x1
+#define PTN5150_POLARITY_CC2                   0x2
+
 #define PTN5150_REG_CC_PORT_ATTACHMENT         GENMASK(4, 2)
+#define PTN5150_REG_CC_POLARITY                        GENMASK(1, 0)
 #define PTN5150_REG_CC_VBUS_DETECTION          BIT(7)
 #define PTN5150_REG_INT_CABLE_ATTACH_MASK      BIT(0)
 #define PTN5150_REG_INT_CABLE_DETACH_MASK      BIT(1)
@@ -53,6 +58,7 @@ struct ptn5150_info {
        int irq;
        struct work_struct irq_work;
        struct mutex mutex;
+       struct typec_switch *orient_sw;
        struct usb_role_switch *role_sw;
 };
@@ -71,6 +77,7 @@ static const struct regmap_config ptn5150_regmap_config = {

 static void ptn5150_check_state(struct ptn5150_info *info)
 {
+       enum typec_orientation orient = TYPEC_ORIENTATION_NONE;
        unsigned int port_status, reg_data, vbus;
        enum usb_role usb_role = USB_ROLE_NONE;
        int ret;
@@ -81,6 +88,23 @@ static void ptn5150_check_state(struct ptn5150_info *info)
                return;
        }

+       orient = FIELD_GET(PTN5150_REG_CC_POLARITY, reg_data);
+       switch (orient) {
+       case PTN5150_POLARITY_CC1:
+               orient = TYPEC_ORIENTATION_NORMAL;
+               break;
+       case PTN5150_POLARITY_CC2:
+               orient = TYPEC_ORIENTATION_REVERSE;
+               break;
+       default:
+               orient = TYPEC_ORIENTATION_NONE;
+               break;
+       }
+
+       ret = typec_switch_set(info->orient_sw, orient);
+       if (ret)
+               dev_err(info->dev, "failed to set orientation: %d\n", ret);
+
        port_status = FIELD_GET(PTN5150_REG_CC_PORT_ATTACHMENT, reg_data);

        switch (port_status) {
@@ -152,6 +176,12 @@ static void ptn5150_irq_work(struct work_struct *work)
                                dev_err(info->dev,
                                        "failed to set none role: %d\n",
                                        ret);
+
+                       ret = typec_switch_set(info->orient_sw,
+                                              TYPEC_ORIENTATION_NONE);
+                       if (ret)
+                               dev_err(info->dev,
+                                       "failed to set orientation: %d\n", ret);
                }
        }
@@ -219,12 +249,14 @@ static void ptn5150_work_sync_and_put(void *data)

        cancel_work_sync(&info->irq_work);
        usb_role_switch_put(info->role_sw);
+       typec_switch_put(info->orient_sw);
 }

 static int ptn5150_i2c_probe(struct i2c_client *i2c)
 {
        struct device *dev = &i2c->dev;
        struct device_node *np = i2c->dev.of_node;
+       struct fwnode_handle *connector;
        struct ptn5150_info *info;
        int ret;
@@ -311,6 +343,14 @@ static int ptn5150_i2c_probe(struct i2c_client *i2c)
        if (ret)
                return -EINVAL;

+       connector = device_get_named_child_node(dev, "connector");
+       if (connector) {
+               info->orient_sw = fwnode_typec_switch_get(connector);
+               if (IS_ERR(info->orient_sw))
+                       return dev_err_probe(info->dev, PTR_ERR(info->orient_sw),
+                                       "failed to get orientation switch\n");
+       }
+
        info->role_sw = usb_role_switch_get(info->dev);
        if (IS_ERR(info->role_sw))
                return dev_err_probe(info->dev, PTR_ERR(info->role_sw),
--
2.34.1

-- 
Best Regards,
Chanwoo Choi
Samsung Electronics
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help