From nobody Thu Apr 9 14:59:35 2026 Received: from mail-10628.protonmail.ch (mail-10628.protonmail.ch [79.135.106.28]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 928F535A38B; Sun, 8 Mar 2026 23:20:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=79.135.106.28 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773012044; cv=none; b=LelPM8v/8AaV7mo2wyFzf0dKROq3KtCutDXecbDLyyaOYtvMsduzD2qBjVYgFkSf045Y1UG1R7EKWIBqNAudr8c+E6gKhDYpQvlATG5ab/L6stRoj1rfwR5W+/025D5D5PUZpJM8CsC49ruPSBnFNxW6YKFbu2hRDpnZApNWhcg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773012044; c=relaxed/simple; bh=RgJOa6yfBGNiuGxmhUx322FszEHIkBe5nei3mIBdkcU=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=qoA3hmnOY5grIqLOUhFwQqC05MDFuFSdcqC/oTOsyb/6KBh6NajfInH/yVHbhwgrVB6Zra36DHOoJbArei5oUywuGkoqqQ4QVX27xo/M+wOV3DQmChZMmgzQZ01cmBz9s6Eg9/t2QojKvwKi/DkTTZHJr2lXOGDmgzGByiwotWs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=pm.me; spf=pass smtp.mailfrom=pm.me; dkim=pass (2048-bit key) header.d=pm.me header.i=@pm.me header.b=oeFBkwoh; arc=none smtp.client-ip=79.135.106.28 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=pm.me Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=pm.me Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=pm.me header.i=@pm.me header.b="oeFBkwoh" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pm.me; s=protonmail3; t=1773012040; x=1773271240; bh=E7aiP89oHRHkEkAMRjtP39QQVm2BmjvpXh/hYVnCB7M=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID: Message-ID:BIMI-Selector; b=oeFBkwohkQAheIMz+n0M+NKgnLQ2+0yKiamkEtI8nllzYCwNY/TXxqo+aUlFmES+g tkgxxFAjWm4Njol8VaLe9/PREt1KhJO+KmSKYM2vTTPEUyjVivJZHv1vMASJHBZBWF quyi6Uo1+DXClQtzVqM0JefXSv53qgQgAl+GcnyraXAizt4zoo1F9cTb00vQGg2kTP YmeH1/cKOuLaAGKjfH6ihA8Nf2ktBU1joo+i8kVSeVhyfM5ap6+8pWvgzsLo8AUN6d VvGT8Nu/tnrXKSdsGmyHp2cveuN2HOrH6BoG1Gm4Wed8qlwtT8z8ziiNXA1+nhpB6C 0Dxl8V+YFLWng== Date: Sun, 08 Mar 2026 23:20:35 +0000 To: Bryan O'Donoghue , Greg Kroah-Hartman , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Heikki Krogerus From: Alexander Koskovich Cc: linux-arm-msm@vger.kernel.org, linux-usb@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Alexander Koskovich Subject: [PATCH RFC 2/2] usb: typec: qcom: Add support for shared USBIN VBUS detection Message-ID: <20260308-qcom-typec-shared-vbus-v1-2-7d574b91052a@pm.me> In-Reply-To: <20260308-qcom-typec-shared-vbus-v1-0-7d574b91052a@pm.me> References: <20260308-qcom-typec-shared-vbus-v1-0-7d574b91052a@pm.me> Feedback-ID: 37836894:user:proton X-Pm-Message-ID: c1613f5bba6ccfb0859cd0880c9eeda82a1dd53e Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" On devices with multiple USB-C ports whose VBUS lines are wired to a single shared USBIN input on the PM8150B PMIC (e.g. ASUS ROG Phone 3), the Type-C port controller cannot distinguish which port is providing VBUS. In practice this shows up as being unable to use the affected Type-C port while the other port is connected to a device providing VBUS such as a PC or charger. Add support for an optional vbus-detect-gpios property that allows the Type-C port controller to read VBUS state from a per-port GPIO instead of the shared USBIN input. When present, the driver also bypasses VSAFE0V checks and switches DRP toggling to TRY_SRC to avoid false source detection caused by VBUS present on USBIN from another port. Signed-off-by: Alexander Koskovich Reviewed-by: Bryan O'Donoghue --- drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.c | 46 ++++++++++++++++++= +++- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.c b/drivers/u= sb/typec/tcpm/qcom/qcom_pmic_typec_port.c index 8051eaa46991..c338e26651b0 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 @@ =20 #include #include +#include #include #include #include @@ -176,6 +177,8 @@ struct pmic_typec_port { bool vbus_enabled; struct mutex vbus_lock; /* VBUS state serialization */ =20 + struct gpio_desc *vbus_detect_gpio; + int cc; bool debouncing_cc; struct delayed_work cc_debounce_dwork; @@ -277,7 +280,12 @@ static int qcom_pmic_typec_port_vbus_detect(struct pmi= c_typec_port *pmic_typec_p { struct device *dev =3D pmic_typec_port->dev; unsigned int misc; - int ret; + int ret, vbus; + + if (pmic_typec_port->vbus_detect_gpio) { + vbus =3D gpiod_get_value_cansleep(pmic_typec_port->vbus_detect_gpio); + return vbus; + } =20 ret =3D regmap_read(pmic_typec_port->regmap, pmic_typec_port->base + TYPEC_MISC_STATUS_REG, @@ -307,6 +315,13 @@ static int qcom_pmic_typec_port_vbus_toggle(struct pmi= c_typec_port *pmic_typec_p if (ret) return ret; =20 + /* + * On devices with multiple ports sharing USBIN, VBUS from another + * port prevents VSAFE0V from being reached. + */ + if (pmic_typec_port->vbus_detect_gpio) + return 0; + val =3D TYPEC_SM_VBUS_VSAFE0V; } =20 @@ -589,7 +604,14 @@ static int qcom_pmic_typec_port_start_toggling(struct = tcpc_dev *tcpc, mode =3D EN_SNK_ONLY; break; case TYPEC_PORT_DRP: - mode =3D EN_TRY_SNK; + /* + * VBUS from another port makes EN_TRY_SNK falsely detect + * a source. Start as Rp to reliably find sinks. + */ + if (pmic_typec_port->vbus_detect_gpio) + mode =3D EN_TRY_SRC; + else + mode =3D EN_TRY_SNK; break; } =20 @@ -677,6 +699,20 @@ static int qcom_pmic_typec_port_start(struct pmic_type= c *tcpm, if (ret) goto done; =20 + /* + * 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 =3D regmap_update_bits(pmic_typec_port->regmap, + pmic_typec_port->base + TYPEC_EXIT_STATE_CFG_REG, + BYPASS_VSAFE0V_DURING_ROLE_SWAP, + BYPASS_VSAFE0V_DURING_ROLE_SWAP); + if (ret) + goto done; + } + pmic_typec_port->tcpm_port =3D tcpm_port; =20 for (i =3D 0; i < pmic_typec_port->nr_irqs; i++) @@ -724,6 +760,12 @@ 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); =20 + pmic_typec_port->vbus_detect_gpio =3D devm_gpiod_get_optional(dev, "vbus-= detect", + GPIOD_IN); + if (IS_ERR(pmic_typec_port->vbus_detect_gpio)) + return dev_err_probe(dev, PTR_ERR(pmic_typec_port->vbus_detect_gpio), + "failed to get vbus-detect GPIO\n"); + pmic_typec_port->dev =3D dev; pmic_typec_port->base =3D base; pmic_typec_port->regmap =3D regmap; --=20 2.53.0