diff options
| author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2026-04-07 10:03:56 +0200 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2026-04-07 10:03:56 +0200 |
| commit | 8aeea2311a5f10451968a0707f23e554a29a6737 (patch) | |
| tree | 4d2328919ef50618aee862a84df2f96a138d50e6 | |
| parent | a0a316f7683988463fc9417498292538055acb8f (diff) | |
| parent | 1bf0ba46d9d2c784120fd9cb235c08add3a6e7be (diff) | |
Merge tag 'extcon-next-for-7.1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/chanwoo/extcon into char-misc-next
Chanwoo writes:
Update extcon next for v7.1
Detailed description for this pull request:
- Fix sysfs duplicate filename issue on extcon core
: Adjust ida_free timing after device_unregister
to prevent duplicate filename error when re-allocating id
- Update NXP PTN5150 extcon driver and dt-binding document
: Handle pending IRQ events during system resume
: Allow "connector" node to present in devicetree
: Add Type-C orientation switch support to correctly
set orientation of multiplexer according to CC status
: Support USB role switch via connector fwnode
- Replace use of system_wq with system_percpu_wq on int3496 driver
- Make typec-power-opmode optional on usbc-tusb320 driver
: Prevent probe error when usb-c connector is configured
in the DT without "typec-power-opmode" property
* tag 'extcon-next-for-7.1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/chanwoo/extcon:
extcon: usbc-tusb320: Make typec-power-opmode optional
extcon: ptn5150: Support USB role switch via connector fwnode
extcon: ptn5150: Add Type-C orientation switch support
dt-bindings: extcon: ptn5150: Allow "connector" node to present
extcon: Fixed sysfs duplicate filename issue
extcon: int3496: replace use of system_wq with system_percpu_wq
extcon: ptn5150: handle pending IRQ events during system resume
| -rw-r--r-- | Documentation/devicetree/bindings/extcon/extcon-ptn5150.yaml | 3 | ||||
| -rw-r--r-- | drivers/extcon/Kconfig | 1 | ||||
| -rw-r--r-- | drivers/extcon/extcon-intel-int3496.c | 4 | ||||
| -rw-r--r-- | drivers/extcon/extcon-ptn5150.c | 56 | ||||
| -rw-r--r-- | drivers/extcon/extcon-usbc-tusb320.c | 24 | ||||
| -rw-r--r-- | drivers/extcon/extcon.c | 4 |
6 files changed, 75 insertions, 17 deletions
diff --git a/Documentation/devicetree/bindings/extcon/extcon-ptn5150.yaml b/Documentation/devicetree/bindings/extcon/extcon-ptn5150.yaml index 072b3c0c5fd0..79f88b5f4e5c 100644 --- a/Documentation/devicetree/bindings/extcon/extcon-ptn5150.yaml +++ b/Documentation/devicetree/bindings/extcon/extcon-ptn5150.yaml @@ -42,6 +42,9 @@ properties: description: A port node to link the usb controller for the dual role switch. + connector: + $ref: /schemas/connector/usb-connector.yaml# + required: - compatible - interrupts diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig index aec46bf03302..68d9df7d2dae 100644 --- a/drivers/extcon/Kconfig +++ b/drivers/extcon/Kconfig @@ -158,6 +158,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-intel-int3496.c b/drivers/extcon/extcon-intel-int3496.c index ded1a85a5549..7d16d5b7d58f 100644 --- a/drivers/extcon/extcon-intel-int3496.c +++ b/drivers/extcon/extcon-intel-int3496.c @@ -106,7 +106,7 @@ static irqreturn_t int3496_thread_isr(int irq, void *priv) struct int3496_data *data = priv; /* Let the pin settle before processing it */ - mod_delayed_work(system_wq, &data->work, DEBOUNCE_TIME); + mod_delayed_work(system_percpu_wq, &data->work, DEBOUNCE_TIME); return IRQ_HANDLED; } @@ -181,7 +181,7 @@ static int int3496_probe(struct platform_device *pdev) } /* process id-pin so that we start with the right status */ - queue_delayed_work(system_wq, &data->work, 0); + queue_delayed_work(system_percpu_wq, &data->work, 0); flush_delayed_work(&data->work); platform_set_drvdata(pdev, data); diff --git a/drivers/extcon/extcon-ptn5150.c b/drivers/extcon/extcon-ptn5150.c index 78ad86c4a3be..eca1b140aeb0 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,7 +343,17 @@ 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 (!info->role_sw && connector) + info->role_sw = fwnode_usb_role_switch_get(connector); if (IS_ERR(info->role_sw)) return dev_err_probe(info->dev, PTR_ERR(info->role_sw), "failed to get role switch\n"); @@ -331,6 +373,19 @@ static int ptn5150_i2c_probe(struct i2c_client *i2c) return 0; } +static int ptn5150_resume(struct device *dev) +{ + struct i2c_client *i2c = to_i2c_client(dev); + struct ptn5150_info *info = i2c_get_clientdata(i2c); + + /* Need to check possible pending interrupt events */ + schedule_work(&info->irq_work); + + return 0; +} + +static DEFINE_SIMPLE_DEV_PM_OPS(ptn5150_pm_ops, NULL, ptn5150_resume); + static const struct of_device_id ptn5150_dt_match[] = { { .compatible = "nxp,ptn5150" }, { }, @@ -346,6 +401,7 @@ MODULE_DEVICE_TABLE(i2c, ptn5150_i2c_id); static struct i2c_driver ptn5150_i2c_driver = { .driver = { .name = "ptn5150", + .pm = pm_sleep_ptr(&ptn5150_pm_ops), .of_match_table = ptn5150_dt_match, }, .probe = ptn5150_i2c_probe, diff --git a/drivers/extcon/extcon-usbc-tusb320.c b/drivers/extcon/extcon-usbc-tusb320.c index 2eab341de6b7..920b03421850 100644 --- a/drivers/extcon/extcon-usbc-tusb320.c +++ b/drivers/extcon/extcon-usbc-tusb320.c @@ -454,20 +454,18 @@ static int tusb320_typec_probe(struct i2c_client *client, priv->port_type = priv->cap.type; /* This goes into register 0x8 field CURRENT_MODE_ADVERTISE */ - ret = fwnode_property_read_string(connector, "typec-power-opmode", &cap_str); - if (ret) - goto err_put; - - ret = typec_find_pwr_opmode(cap_str); - if (ret < 0) - goto err_put; - - priv->pwr_opmode = ret; + if (!fwnode_property_read_string(connector, "typec-power-opmode", + &cap_str)) { + ret = typec_find_pwr_opmode(cap_str); + if (ret < 0) + goto err_put; + priv->pwr_opmode = ret; - /* Initialize the hardware with the devicetree settings. */ - ret = tusb320_set_adv_pwr_mode(priv); - if (ret) - goto err_put; + /* Initialize the hardware with the devicetree settings. */ + ret = tusb320_set_adv_pwr_mode(priv); + if (ret) + goto err_put; + } priv->cap.revision = USB_TYPEC_REV_1_1; priv->cap.accessory[0] = TYPEC_ACCESSORY_AUDIO; diff --git a/drivers/extcon/extcon.c b/drivers/extcon/extcon.c index d9e9815a5f96..98d85cc114a7 100644 --- a/drivers/extcon/extcon.c +++ b/drivers/extcon/extcon.c @@ -1366,10 +1366,10 @@ void extcon_dev_unregister(struct extcon_dev *edev) return; } - ida_free(&extcon_dev_ids, edev->id); - device_unregister(&edev->dev); + ida_free(&extcon_dev_ids, edev->id); + if (edev->mutually_exclusive && edev->max_supported) { for (index = 0; edev->mutually_exclusive[index]; index++) |
