From: Heikki Krogerus <heikki.krogerus@linux.intel.com>
To: Alexander Koskovich <akoskovich@pm.me>
Cc: Bryan O'Donoghue <bryan.odonoghue@linaro.org>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Rob Herring <robh@kernel.org>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
Conor Dooley <conor+dt@kernel.org>,
linux-arm-msm@vger.kernel.org, linux-usb@vger.kernel.org,
devicetree@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v2] usb: typec: qcom: Add support for per port VBUS detection
Date: Fri, 13 Mar 2026 10:46:23 +0200 [thread overview]
Message-ID: <abPO31SynIPY6fJD@kuha> (raw)
In-Reply-To: <20260312-qcom-typec-shared-vbus-v2-1-99ed9e500947@pm.me>
Thu, Mar 12, 2026 at 06:16:58AM +0000, Alexander Koskovich kirjoitti:
> This is required for devices (e.g. ASUS ROG Phone 3) where more than
> one USB port can act as a sink and both share a single USBIN input on
> the PMIC.
>
> Because the PM8150B uses USBIN to determine VBUS presence, a charger
> connected to one port causes the PMIC to falsely detect VBUS on the
> other port, preventing it from entering source mode.
>
> For example, plugging a charger into one port prevents using the other
> port for a flash drive.
>
> Fix this by adding support for the vbus-gpios connector binding so the
> driver can use an external GPIO for per-port VBUS presence detection
> instead of the shared USBIN register.
>
> Signed-off-by: Alexander Koskovich <akoskovich@pm.me>
Acked-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> ---
> Changes in v2:
> - Dropped RFC prefix
> - Remove redundant vbus-detect-gpios, instead use existing vbus-gpios from usb-connector (Dmitry)
> - Updated cover to better describe scenario where this change is relevant
> - Update comment for EN_TRY_SRC to make more sense
> - Skip vSafe5V poll too not just vSafe0V
> - return gpiod_get_value_cansleep (Konrad)
> - regmap_update_bits -> regmap_set_bits (Konrad)
> - Get vbus-gpios per connector (Konrad)
> - Add bracket to if (IS_ERR(pmic_typec_port->vbus_detect_gpio)) (Bryan)
> - Link to v1: https://lore.kernel.org/r/20260308-qcom-typec-shared-vbus-v1-0-7d574b91052a@pm.me
> ---
> drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.c | 53 +++++++++++++++++++++-
> 1 file changed, 52 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.c b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.c
> index 8051eaa46991..a8f6687a3522 100644
> --- a/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.c
> +++ b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.c
> @@ -5,6 +5,7 @@
>
> #include <linux/delay.h>
> #include <linux/err.h>
> +#include <linux/gpio/consumer.h>
> #include <linux/interrupt.h>
> #include <linux/kernel.h>
> #include <linux/mod_devicetable.h>
> @@ -176,6 +177,8 @@ struct pmic_typec_port {
> bool vbus_enabled;
> struct mutex vbus_lock; /* VBUS state serialization */
>
> + struct gpio_desc *vbus_detect_gpio;
> +
> int cc;
> bool debouncing_cc;
> struct delayed_work cc_debounce_dwork;
> @@ -279,6 +282,9 @@ static int qcom_pmic_typec_port_vbus_detect(struct pmic_typec_port *pmic_typec_p
> unsigned int misc;
> int ret;
>
> + if (pmic_typec_port->vbus_detect_gpio)
> + return gpiod_get_value_cansleep(pmic_typec_port->vbus_detect_gpio);
> +
> ret = regmap_read(pmic_typec_port->regmap,
> pmic_typec_port->base + TYPEC_MISC_STATUS_REG,
> &misc);
> @@ -310,6 +316,13 @@ static int qcom_pmic_typec_port_vbus_toggle(struct pmic_typec_port *pmic_typec_p
> val = TYPEC_SM_VBUS_VSAFE0V;
> }
>
> + /*
> + * On devices with multiple ports sharing USBIN, VBUS from another
> + * port makes the USBIN-based vsafe polls unreliable.
> + */
> + if (pmic_typec_port->vbus_detect_gpio)
> + return 0;
> +
> /* Poll waiting for transition to required vSafe5V or vSafe0V */
> ret = regmap_read_poll_timeout(pmic_typec_port->regmap,
> pmic_typec_port->base + TYPEC_SM_STATUS_REG,
> @@ -589,7 +602,15 @@ static int qcom_pmic_typec_port_start_toggling(struct tcpc_dev *tcpc,
> mode = EN_SNK_ONLY;
> break;
> case TYPEC_PORT_DRP:
> - mode = EN_TRY_SNK;
> + /*
> + * With VBUS present on USBIN from another port, EN_TRY_SNK
> + * keeps the port in sink mode. Use EN_TRY_SRC so the port
> + * tries to source first.
> + */
> + if (pmic_typec_port->vbus_detect_gpio)
> + mode = EN_TRY_SRC;
> + else
> + mode = EN_TRY_SNK;
> break;
> }
>
> @@ -677,6 +698,19 @@ static int qcom_pmic_typec_port_start(struct pmic_typec *tcpm,
> if (ret)
> goto done;
>
> + /*
> + * On devices with multiple USB-C ports sharing USBIN, bypass
> + * VSAFE0V so SRC attachment can complete despite VBUS being
> + * present on USBIN from another port.
> + */
> + if (pmic_typec_port->vbus_detect_gpio) {
> + ret = regmap_set_bits(pmic_typec_port->regmap,
> + pmic_typec_port->base + TYPEC_EXIT_STATE_CFG_REG,
> + BYPASS_VSAFE0V_DURING_ROLE_SWAP);
> + if (ret)
> + goto done;
> + }
> +
> pmic_typec_port->tcpm_port = tcpm_port;
>
> for (i = 0; i < pmic_typec_port->nr_irqs; i++)
> @@ -704,6 +738,7 @@ int qcom_pmic_typec_port_probe(struct platform_device *pdev,
> struct device *dev = &pdev->dev;
> struct pmic_typec_port_irq_data *irq_data;
> struct pmic_typec_port *pmic_typec_port;
> + struct fwnode_handle *connector;
> int i, ret, irq;
>
> pmic_typec_port = devm_kzalloc(dev, sizeof(*pmic_typec_port), GFP_KERNEL);
> @@ -724,6 +759,22 @@ int qcom_pmic_typec_port_probe(struct platform_device *pdev,
> if (IS_ERR(pmic_typec_port->vdd_vbus))
> return PTR_ERR(pmic_typec_port->vdd_vbus);
>
> + connector = device_get_named_child_node(dev, "connector");
> + if (connector) {
> + pmic_typec_port->vbus_detect_gpio =
> + devm_fwnode_gpiod_get(dev, connector, "vbus",
> + GPIOD_IN, NULL);
> + fwnode_handle_put(connector);
> +
> + if (IS_ERR(pmic_typec_port->vbus_detect_gpio)) {
> + ret = PTR_ERR(pmic_typec_port->vbus_detect_gpio);
> + pmic_typec_port->vbus_detect_gpio = NULL;
> + if (ret != -ENOENT)
> + return dev_err_probe(dev, ret,
> + "failed to get vbus GPIO\n");
> + }
> + }
> +
> pmic_typec_port->dev = dev;
> pmic_typec_port->base = base;
> pmic_typec_port->regmap = regmap;
>
> ---
> base-commit: 1f318b96cc84d7c2ab792fcc0bfd42a7ca890681
> change-id: 20260308-qcom-typec-shared-vbus-7d37c6b2d155
>
> Best regards,
> --
> Alexander Koskovich <akoskovich@pm.me>
>
--
heikki
next prev parent reply other threads:[~2026-03-13 8:47 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-12 6:16 [PATCH v2] usb: typec: qcom: Add support for per port VBUS detection Alexander Koskovich
2026-03-12 10:04 ` Bryan O'Donoghue
2026-03-13 8:46 ` Heikki Krogerus [this message]
2026-03-19 13:26 ` Konrad Dybcio
2026-03-19 19:57 ` Dmitry Baryshkov
2026-03-20 10:03 ` Bryan O'Donoghue
2026-03-23 9:36 ` Konrad Dybcio
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=abPO31SynIPY6fJD@kuha \
--to=heikki.krogerus@linux.intel.com \
--cc=akoskovich@pm.me \
--cc=bryan.odonoghue@linaro.org \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=gregkh@linuxfoundation.org \
--cc=krzk+dt@kernel.org \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=robh@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.