From nobody Fri Oct 2 12:25:27 2026 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) (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 E945C3B14C7 for ; Sat, 1 Aug 2026 07:49:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.168.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785570550; cv=none; b=fsYpNE2U8smUDGlXnfCnKmw0AImZQ1/2GPYaTuspvt44c4blMA9mSF/AVhZYFKA8MVIqEtXCa7284MT5ntSgSUk3OlvjCJqkcZopBtLQdn3zw8JivSAAAc4HPiljilN3IWtxH8fR9okyIleDvv15NvTALSxRhEOHJNz/JD8UPAw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785570550; c=relaxed/simple; bh=wckzg7u3tcRfa6jZax71MInhaQ/FdjfR66RHknyTaWY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:To:Cc; b=QHRm3rGWPc92l/+zHGe5idDpN04XINmiSdzpzdzbCPJbuJ45J3rrA4m3aBIQQchlAOPjjpuxMxDOzCpdwEpI4QlfRwed1chLYmdQiugtQFW8LeQ1BCj3EBQ9az9e1r/W3EwahjQh62OvyMxKTrcl9fp2FsfLAaxfwF0KNA39sok= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com; spf=pass smtp.mailfrom=oss.qualcomm.com; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b=HB9bGlik; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b=X5+iNvth; arc=none smtp.client-ip=205.220.168.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b="HB9bGlik"; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b="X5+iNvth" Received: from pps.filterd (m0279864.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 6714djoD1417130 for ; Sat, 1 Aug 2026 07:49:08 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:content-type:date:from:message-id :mime-version:subject:to; s=qcppdkim1; bh=AR4d/t3FeZghBRdNEvysF+ dmiVXYZTZuk9ukn2d2jJw=; b=HB9bGlikE+hKDtQkZY5255y2GDa7C57OI23AF4 lWcQOMdaHc7rNnnZl+xq+oKdpZCnQP6yfGv+CeZuK0A+IKUugvQ1jd5G8bv5vSoA vDyDCsr5e5QI+dPalRdJcJfCvzSQI0Ww1/HZ++9KFzU/jeJdQRv6Pig5HX2ayM4S oLgn7YvVqnetcRw4bAZ1gJ07mMgH7bc97WBK+sm+uPICCjuf3TlizREGK9jvtzqh WKPRq5xhaRnLkjXPNdgQEpqA7ZUuHCJilv4wUiQBxaVRp0oCPgZQQc6kbi6LvuQQ AawQHhrNdSukOtFuC8XJk302stXqAPgQ1Mp4BpLN6YKiaGhw== Received: from mail-pf1-f197.google.com (mail-pf1-f197.google.com [209.85.210.197]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4fs9yggab4-1 (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT) for ; Sat, 01 Aug 2026 07:49:07 +0000 (GMT) Received: by mail-pf1-f197.google.com with SMTP id d2e1a72fcca58-84a67b16217so3292010b3a.3 for ; Sat, 01 Aug 2026 00:49:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oss.qualcomm.com; s=google; t=1785570547; x=1786175347; darn=vger.kernel.org; h=cc:to:message-id:content-transfer-encoding:content-type :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=AR4d/t3FeZghBRdNEvysF+dmiVXYZTZuk9ukn2d2jJw=; b=X5+iNvthr3btkhia5PRUogo/+KmzCs/TZoQI4uQA8mpUCzTm0ym2WdFMXVfU2DqWEb 0BCDTdEYMhjjvEaI4lzN31Wd0RoRKJ4azwHST3y+XuuzDdOxzvdm4U1txjPtfehFO+Z8 8vAXolyNS/LsaR3EQpkzUxiC5MFcwpc8wsBlMKlwJXr7r6/0arMex3LZrTlermmIDxnS q6nPTiw3fLFoQJS94Gt428iNffvVgozkJzTWLjPQPayV/56JJzGxrhCpQwXvTaRiLv8p zHpH3+vpZpovbA5oE25x7GoOWRhlod0RI9Y6arVlE68/8+FDdqenP5r5PEPwrAIR0RMV bD5g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785570547; x=1786175347; h=cc:to:message-id:content-transfer-encoding:content-type :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=AR4d/t3FeZghBRdNEvysF+dmiVXYZTZuk9ukn2d2jJw=; b=n4cxKz+Y4PHkN809dIACwpeQchQF8Ng56XPEbXse1Rc++wBV14DqKskdySlowHqX8x nnsqOo2rnfXM09PtABnzHRSRSvnrwvy6palFL2GFPcC1JgYQz2ER6Yp9q8DdmHBEBlZk t+42pwr4k+9ozLFVXLbll7XawTPCzjPM2pn5UIzxDjOCmprvPCWUrqHcl1O8AXho35bn 5Sclwisvu0IwBzMFNOBX/bohG5KaSt+Ct6n+9o479+BzQjlYWonYNShN2nAy7pKQbTid uMG7uYk34nEw9T+Q9DcSOLAu4OFDk3MBgBLdb+90u2CzI6INlbwPm/upQQMvhpvLv0nl p1GQ== X-Forwarded-Encrypted: i=1; AHgh+Roj1ZrFIVlnEqloFYXE5J78smqxqkBmptNmFwcrjOkkhcPYKrXUmBVGqHSJkGHqUUqKoj2tfzHAW2Gk6C4=@vger.kernel.org X-Gm-Message-State: AOJu0YwCjdZNdTQekIVSOtWtpixQyMt6b62KkH/kMlV+jetRYzZs8wiw HfEAOPkW8OX1jthg/FITa8jFsMSOQ60lYRfpQIV4QC9AV9Ww00RzVabY7coJnQKcThicncqtaFQ WlkhMSVbGUNlmo2fjHPHWgHH1Yu12tjmy8NdYBacyLUGN1LQV1L8+vvK7eM2d8ShjCljv2kf32u M= X-Gm-Gg: AR+sD106KdTJbS69pYgdglGSddXBlDSRdDPy6WSk1H1teOdsx9HMWZSpLWBKrsuFs6a 0f2gSCEckCyEpz7e9X7IxzVTed4XhGeV8xM7Gi62nw/9DZcV6P8loFK1zMUBNDTP5KatG2+y52y tacziG971P+/37BO8VqH6azF7RRKop6DulVP04U97RKIXht5gwjL9kXLEsd9zM9ZCsXUb4ZgcLp 92sUUkLmRMzS2wug5PtVxina3FgL+fcMUkLC8/5Sj9HYuqiHr+Wx44yR89hPxPR3ckfaEMyoZXe Ww+Hnmqe4JZmSfs44MhEWhXMYG26AA3v4fw9Zvsj3f0a9WqFGn5/z9zSretj2FhuG8matWj8jh7 zdzh7ICQXcy/JNZR5nsLpDliqX0ZofQ== X-Received: by 2002:a05:6a21:7d01:b0:3c6:3c5b:fe66 with SMTP id adf61e73a8af0-3c92a89c78amr2513277637.41.1785570547103; Sat, 01 Aug 2026 00:49:07 -0700 (PDT) X-Received: by 2002:a05:6a21:7d01:b0:3c6:3c5b:fe66 with SMTP id adf61e73a8af0-3c92a89c78amr2513247637.41.1785570546546; Sat, 01 Aug 2026 00:49:06 -0700 (PDT) Received: from hu-kamalw-hyd.qualcomm.com ([202.46.22.19]) by smtp.gmail.com with ESMTPSA id a92af1059eb24-13fab4fdb80sm9645923c88.15.2026.08.01.00.49.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 01 Aug 2026 00:49:06 -0700 (PDT) From: Kamal Wadhwa Date: Sat, 01 Aug 2026 13:18:45 +0530 Subject: [PATCH] power: supply: qcom_battmgr: Add multi-port USB-C power supply support Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260801-b4-battmgr-multiport-usb-v1-1-89d90bf5de1f@oss.qualcomm.com> X-B4-Tracking: v=1; b=H4sIANykbWoC/yXMTQrCQAxA4auUrA1MSxlHryIumprWiP0hyYhQe ndHXX6L9zYwVmGDc7WB8ktMlrmgPlTQ37t5ZJRbMTShiSGFGqlF6tynUXHKT5d1UcdshG1kCsd TijENUPJVeZD3b325/m2ZHtz79wf7/gFTLsCpfAAAAA== X-Change-ID: 20260801-b4-battmgr-multiport-usb-46eb0798668f To: Sebastian Reichel Cc: linux-arm-msm@vger.kernel.org, linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org, Kamal Wadhwa X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1785570543; l=16255; i=kamal.wadhwa@oss.qualcomm.com; s=20260406; h=from:subject:message-id; bh=wckzg7u3tcRfa6jZax71MInhaQ/FdjfR66RHknyTaWY=; b=LpBXz4x4Qa8BCLCHZnjP+HyhPBnPNoUfHEC98tKrz9Zx0pS9HQXIGYAvfmd4EbNJ8bG7Ax8KR D8z7+vhS+yhDhP8fWCBRS2NNX4yOjUK+5J9M5qQzE3dRmYDSgfggi05 X-Developer-Key: i=kamal.wadhwa@oss.qualcomm.com; a=ed25519; pk=ylH1NxUZkBpYsmww89g6zVxpS0q8qthtzcORkYxn/Ag= X-Proofpoint-Spam-Info: AW1haW4tMjYwODAxMDA1NSBTYWx0ZWRfXy5GlfWT2j+8s ZGM9Px4wDxeetnfaYe1Wp6CKZVp0M1V/fxwmeXIfctxmKK4i+aedekAESHokDdiFj/L+lDgrWeU AeAsDHPl5m/2LqvRQ2HU1IxqDv8njkk= X-Proofpoint-GUID: fECiej3oYJDETzMq3ZQBjz9jtaaWvmP8 X-Authority-Analysis: v=2.4 cv=Gu5yPE1C c=1 sm=1 tr=0 ts=6a6da4f4 cx=c_pps a=rEQLjTOiSrHUhVqRoksmgQ==:117 a=fChuTYTh2wq5r3m49p7fHw==:17 a=IkcTkHD0fZMA:10 a=Sv0fKeRqtYgA:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=DJpcGTmdVt4CTyJn9g5Z:22 a=EUspDBNiAAAA:8 a=zFCAPC_QsuEp93vFkkwA:9 a=QEXdDO2ut3YA:10 a=2VI0MkxyNR6bbpdq8BZq:22 X-Proofpoint-ORIG-GUID: fECiej3oYJDETzMq3ZQBjz9jtaaWvmP8 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwODAxMDA1NSBTYWx0ZWRfX+ZQLuquL1ku4 t0e0mOe1paNJwGcyiTt3dp3vG2FwI+GLfwV71yD0wuGAXvRLTeOkwezCQLWhk3AfMbnqXFDpTR7 ODUmnue1Thqr8cNh1DlDPq6ud1/iC83M2UIGt33uIG6X/5p93PmitkY1rycrFduP55bcNqgMctm zfdg8rJYqcaPXiqzz1hEB6smrbuki/Orb0rcGzZpkeRyGDsqEEnJaw/U177ewp9jlxXZm6i3KFE MosOKUYHV3S0E5ahvlWH+oa9Cke6kr+QnIDkMq1rqzkPOr/g1QLht6YX7RtdWcEczcq8GvtyNYX Jb6Q2lZdz8SVffz+4p1qSlfcMNVtOOcdj8jZGPYiVb91zbN1wUP0kbtCbnv2baeJFiZ7ZMIGrxt RxKd/v9eclfkTu8VfzQvAa1JFq7mFfUG0ZlSVVqTsWXFjweVnQ6rU+Lb96+H+rnEL5xmQBHhpp5 Tm/NkHX9E4E6UBhwAcg== X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-07-31_07,2026-07-30_01,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 impostorscore=0 bulkscore=0 clxscore=1015 phishscore=0 priorityscore=1501 lowpriorityscore=0 spamscore=0 malwarescore=0 adultscore=0 suspectscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608010055 Extend the qcom_battmgr driver to report up to MAX_USB_PORTS (3) USB-C power supply ports on the X1E80100 & Glymur platform, which exposes more than one charger port to firmware. At firmware-enable time, query USB_NUM_PORTS over the existing BATTMGR_USB_PROPERTY_GET opcode to discover how many ports the firmware actually reports, and register the additional "qcom-battmgr-usb2"/"qcom-battmgr-usb3" power supplies only when the firmware confirms a second/third port. Each additional port is polled independently via new BATTMGR_USB2_PROPERTY_GET/SET (0xC0/0xC1) and BATTMGR_USB3_PROPERTY_GET/SET (0xC2/0xC3) opcodes so its properties are not aliased to the primary port's state. Also add the POWER_SUPPLY_PROP_CAPACITY entry to x1e80100_bat_props[]. Assisted-by: Claude:claude-sonnet-5 Signed-off-by: Kamal Wadhwa --- drivers/power/supply/qcom_battmgr.c | 353 ++++++++++++++++++++++++++++++++= +++- 1 file changed, 351 insertions(+), 2 deletions(-) diff --git a/drivers/power/supply/qcom_battmgr.c b/drivers/power/supply/qco= m_battmgr.c index 490137a23d00..17675a9975d6 100644 --- a/drivers/power/supply/qcom_battmgr.c +++ b/drivers/power/supply/qcom_battmgr.c @@ -26,6 +26,8 @@ enum qcom_battmgr_variant { QCOM_BATTMGR_X1E80100, }; =20 +#define MAX_USB_PORTS 3 + #define BATTMGR_BAT_STATUS 0x1 =20 #define BATTMGR_REQUEST_NOTIFICATION 0x4 @@ -76,6 +78,10 @@ enum qcom_battmgr_variant { =20 #define BATTMGR_USB_PROPERTY_GET 0x32 #define BATTMGR_USB_PROPERTY_SET 0x33 +#define BATTMGR_USB2_PROPERTY_GET 0xC0 +#define BATTMGR_USB2_PROPERTY_SET 0xC1 +#define BATTMGR_USB3_PROPERTY_GET 0xC2 +#define BATTMGR_USB3_PROPERTY_SET 0xC3 #define USB_ONLINE 0 #define USB_VOLT_NOW 1 #define USB_VOLT_MAX 2 @@ -86,6 +92,13 @@ enum qcom_battmgr_variant { #define USB_ADAP_TYPE 7 #define USB_MOISTURE_DET_EN 8 #define USB_MOISTURE_DET_STS 9 +#define USB_CONNECTOR_TEMP 10 +#define USB_REAL_TYPE 11 +#define USB_TYPEC_COMPLIANT 12 +#define USB_SCOPE 13 +#define USB_CONNECTOR_TYPE 14 +#define USB_F_ACTIVE 15 +#define USB_NUM_PORTS 16 =20 #define BATTMGR_WLS_PROPERTY_GET 0x34 #define BATTMGR_WLS_PROPERTY_SET 0x35 @@ -297,6 +310,7 @@ struct qcom_battmgr_usb { unsigned int current_max; unsigned int current_limit; unsigned int usb_type; + unsigned int num_ports; }; =20 struct qcom_battmgr_wireless { @@ -316,6 +330,8 @@ struct qcom_battmgr { struct power_supply *ac_psy; struct power_supply *bat_psy; struct power_supply *usb_psy; + struct power_supply *usb2_psy; + struct power_supply *usb3_psy; struct power_supply *wls_psy; =20 enum qcom_battmgr_unit unit; @@ -329,8 +345,12 @@ struct qcom_battmgr { struct qcom_battmgr_status status; struct qcom_battmgr_ac ac; struct qcom_battmgr_usb usb; + struct qcom_battmgr_usb usb2; + struct qcom_battmgr_usb usb3; struct qcom_battmgr_wireless wireless; =20 + struct power_supply_config usb_psy_cfg; + struct work_struct enable_work; =20 /* @@ -829,6 +849,7 @@ static const enum power_supply_property x1e80100_bat_pr= ops[] =3D { POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_PROP_PRESENT, POWER_SUPPLY_PROP_TECHNOLOGY, + POWER_SUPPLY_PROP_CAPACITY, POWER_SUPPLY_PROP_CYCLE_COUNT, POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, POWER_SUPPLY_PROP_VOLTAGE_NOW, @@ -1042,8 +1063,136 @@ static int qcom_battmgr_usb_get_property(struct pow= er_supply *psy, return 0; } =20 +static int qcom_battmgr_usb2_x1e80100_update(struct qcom_battmgr *battmgr, + enum power_supply_property psp) +{ + unsigned int prop; + int ret; + + if (psp >=3D ARRAY_SIZE(sm8350_usb_prop_map)) + return -EINVAL; + + prop =3D sm8350_usb_prop_map[psp]; + + mutex_lock(&battmgr->lock); + ret =3D qcom_battmgr_request_property(battmgr, BATTMGR_USB2_PROPERTY_GET,= prop, 0); + mutex_unlock(&battmgr->lock); + + return ret; +} + +static int qcom_battmgr_usb3_x1e80100_update(struct qcom_battmgr *battmgr, + enum power_supply_property psp) +{ + unsigned int prop; + int ret; + + if (psp >=3D ARRAY_SIZE(sm8350_usb_prop_map)) + return -EINVAL; + + prop =3D sm8350_usb_prop_map[psp]; + + mutex_lock(&battmgr->lock); + ret =3D qcom_battmgr_request_property(battmgr, BATTMGR_USB3_PROPERTY_GET,= prop, 0); + mutex_unlock(&battmgr->lock); + + return ret; +} + +static int qcom_battmgr_usb2_get_property(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct qcom_battmgr *battmgr =3D power_supply_get_drvdata(psy); + int ret; + + if (!battmgr->service_up) + return -EAGAIN; + + ret =3D qcom_battmgr_usb2_x1e80100_update(battmgr, psp); + if (ret) + return ret; + + switch (psp) { + case POWER_SUPPLY_PROP_ONLINE: + val->intval =3D battmgr->usb2.online; + break; + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + val->intval =3D battmgr->usb2.voltage_now; + break; + case POWER_SUPPLY_PROP_VOLTAGE_MAX: + val->intval =3D battmgr->usb2.voltage_max; + break; + case POWER_SUPPLY_PROP_CURRENT_NOW: + val->intval =3D battmgr->usb2.current_now; + break; + case POWER_SUPPLY_PROP_CURRENT_MAX: + val->intval =3D battmgr->usb2.current_max; + break; + case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: + val->intval =3D battmgr->usb2.current_limit; + break; + case POWER_SUPPLY_PROP_USB_TYPE: + val->intval =3D battmgr->usb2.usb_type; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int qcom_battmgr_usb3_get_property(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct qcom_battmgr *battmgr =3D power_supply_get_drvdata(psy); + int ret; + + if (!battmgr->service_up) + return -EAGAIN; + + ret =3D qcom_battmgr_usb3_x1e80100_update(battmgr, psp); + if (ret) + return ret; + + switch (psp) { + case POWER_SUPPLY_PROP_ONLINE: + val->intval =3D battmgr->usb3.online; + break; + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + val->intval =3D battmgr->usb3.voltage_now; + break; + case POWER_SUPPLY_PROP_VOLTAGE_MAX: + val->intval =3D battmgr->usb3.voltage_max; + break; + case POWER_SUPPLY_PROP_CURRENT_NOW: + val->intval =3D battmgr->usb3.current_now; + break; + case POWER_SUPPLY_PROP_CURRENT_MAX: + val->intval =3D battmgr->usb3.current_max; + break; + case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: + val->intval =3D battmgr->usb3.current_limit; + break; + case POWER_SUPPLY_PROP_USB_TYPE: + val->intval =3D battmgr->usb3.usb_type; + break; + default: + return -EINVAL; + } + + return 0; +} + static const enum power_supply_property sc8280xp_usb_props[] =3D { POWER_SUPPLY_PROP_ONLINE, + POWER_SUPPLY_PROP_VOLTAGE_NOW, + POWER_SUPPLY_PROP_VOLTAGE_MAX, + POWER_SUPPLY_PROP_CURRENT_NOW, + POWER_SUPPLY_PROP_CURRENT_MAX, + POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, + POWER_SUPPLY_PROP_USB_TYPE, }; =20 static const struct power_supply_desc sc8280xp_usb_psy_desc =3D { @@ -1064,6 +1213,42 @@ static const struct power_supply_desc sc8280xp_usb_p= sy_desc =3D { BIT(POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID), }; =20 +static const struct power_supply_desc x1e80100_usb2_psy_desc =3D { + .name =3D "qcom-battmgr-usb2", + .type =3D POWER_SUPPLY_TYPE_USB, + .properties =3D sc8280xp_usb_props, + .num_properties =3D ARRAY_SIZE(sc8280xp_usb_props), + .get_property =3D qcom_battmgr_usb2_get_property, + .usb_types =3D BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN) | + BIT(POWER_SUPPLY_USB_TYPE_SDP) | + BIT(POWER_SUPPLY_USB_TYPE_DCP) | + BIT(POWER_SUPPLY_USB_TYPE_CDP) | + BIT(POWER_SUPPLY_USB_TYPE_ACA) | + BIT(POWER_SUPPLY_USB_TYPE_C) | + BIT(POWER_SUPPLY_USB_TYPE_PD) | + BIT(POWER_SUPPLY_USB_TYPE_PD_DRP) | + BIT(POWER_SUPPLY_USB_TYPE_PD_PPS) | + BIT(POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID), +}; + +static const struct power_supply_desc x1e80100_usb3_psy_desc =3D { + .name =3D "qcom-battmgr-usb3", + .type =3D POWER_SUPPLY_TYPE_USB, + .properties =3D sc8280xp_usb_props, + .num_properties =3D ARRAY_SIZE(sc8280xp_usb_props), + .get_property =3D qcom_battmgr_usb3_get_property, + .usb_types =3D BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN) | + BIT(POWER_SUPPLY_USB_TYPE_SDP) | + BIT(POWER_SUPPLY_USB_TYPE_DCP) | + BIT(POWER_SUPPLY_USB_TYPE_CDP) | + BIT(POWER_SUPPLY_USB_TYPE_ACA) | + BIT(POWER_SUPPLY_USB_TYPE_C) | + BIT(POWER_SUPPLY_USB_TYPE_PD) | + BIT(POWER_SUPPLY_USB_TYPE_PD_DRP) | + BIT(POWER_SUPPLY_USB_TYPE_PD_PPS) | + BIT(POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID), +}; + static const enum power_supply_property sm8350_usb_props[] =3D { POWER_SUPPLY_PROP_ONLINE, POWER_SUPPLY_PROP_VOLTAGE_NOW, @@ -1212,6 +1397,10 @@ static void qcom_battmgr_notification(struct qcom_ba= ttmgr *battmgr, break; case NOTIF_USB_PROPERTY: power_supply_changed(battmgr->usb_psy); + if (battmgr->usb2_psy) + power_supply_changed(battmgr->usb2_psy); + if (battmgr->usb3_psy) + power_supply_changed(battmgr->usb3_psy); break; case NOTIF_WLS_PROPERTY: power_supply_changed(battmgr->wls_psy); @@ -1260,6 +1449,7 @@ static void qcom_battmgr_sc8280xp_callback(struct qco= m_battmgr *battmgr, unsigned int opcode =3D le32_to_cpu(resp->hdr.opcode); unsigned int source; unsigned int state; + unsigned int property; size_t payload_len =3D len - sizeof(struct pmic_glink_hdr); =20 if (payload_len < sizeof(__le32)) { @@ -1355,6 +1545,121 @@ static void qcom_battmgr_sc8280xp_callback(struct q= com_battmgr *battmgr, case BATTMGR_CHG_CTRL_LIMIT_EN: battmgr->error =3D 0; break; + case BATTMGR_USB_PROPERTY_GET: + property =3D le32_to_cpu(resp->intval.property); + if (payload_len !=3D sizeof(resp->intval)) { + dev_warn(battmgr->dev, + "invalid payload length for %#x request: %zd\n", + property, payload_len); + battmgr->error =3D -ENODATA; + return; + } + + switch (property) { + case USB_ONLINE: + battmgr->usb.online =3D le32_to_cpu(resp->intval.value); + break; + case USB_VOLT_NOW: + battmgr->usb.voltage_now =3D le32_to_cpu(resp->intval.value); + break; + case USB_VOLT_MAX: + battmgr->usb.voltage_max =3D le32_to_cpu(resp->intval.value); + break; + case USB_CURR_NOW: + battmgr->usb.current_now =3D le32_to_cpu(resp->intval.value); + break; + case USB_CURR_MAX: + battmgr->usb.current_max =3D le32_to_cpu(resp->intval.value); + break; + case USB_INPUT_CURR_LIMIT: + battmgr->usb.current_limit =3D le32_to_cpu(resp->intval.value); + break; + case USB_TYPE: + battmgr->usb.usb_type =3D le32_to_cpu(resp->intval.value); + break; + case USB_NUM_PORTS: + battmgr->usb.num_ports =3D le32_to_cpu(resp->intval.value); + break; + default: + dev_warn(battmgr->dev, "unknown property %#x\n", property); + break; + } + break; + + case BATTMGR_USB2_PROPERTY_GET: + property =3D le32_to_cpu(resp->intval.property); + if (payload_len !=3D sizeof(resp->intval)) { + dev_warn(battmgr->dev, + "invalid payload length for %#x request: %zd\n", + property, payload_len); + battmgr->error =3D -ENODATA; + return; + } + + switch (property) { + case USB_ONLINE: + battmgr->usb2.online =3D le32_to_cpu(resp->intval.value); + break; + case USB_VOLT_NOW: + battmgr->usb2.voltage_now =3D le32_to_cpu(resp->intval.value); + break; + case USB_VOLT_MAX: + battmgr->usb2.voltage_max =3D le32_to_cpu(resp->intval.value); + break; + case USB_CURR_NOW: + battmgr->usb2.current_now =3D le32_to_cpu(resp->intval.value); + break; + case USB_CURR_MAX: + battmgr->usb2.current_max =3D le32_to_cpu(resp->intval.value); + break; + case USB_INPUT_CURR_LIMIT: + battmgr->usb2.current_limit =3D le32_to_cpu(resp->intval.value); + break; + case USB_TYPE: + battmgr->usb2.usb_type =3D le32_to_cpu(resp->intval.value); + break; + default: + dev_warn(battmgr->dev, "unknown property %#x\n", property); + break; + } + break; + case BATTMGR_USB3_PROPERTY_GET: + property =3D le32_to_cpu(resp->intval.property); + if (payload_len !=3D sizeof(resp->intval)) { + dev_warn(battmgr->dev, + "invalid payload length for %#x request: %zd\n", + property, payload_len); + battmgr->error =3D -ENODATA; + return; + } + + switch (property) { + case USB_ONLINE: + battmgr->usb3.online =3D le32_to_cpu(resp->intval.value); + break; + case USB_VOLT_NOW: + battmgr->usb3.voltage_now =3D le32_to_cpu(resp->intval.value); + break; + case USB_VOLT_MAX: + battmgr->usb3.voltage_max =3D le32_to_cpu(resp->intval.value); + break; + case USB_CURR_NOW: + battmgr->usb3.current_now =3D le32_to_cpu(resp->intval.value); + break; + case USB_CURR_MAX: + battmgr->usb3.current_max =3D le32_to_cpu(resp->intval.value); + break; + case USB_INPUT_CURR_LIMIT: + battmgr->usb3.current_limit =3D le32_to_cpu(resp->intval.value); + break; + case USB_TYPE: + battmgr->usb3.usb_type =3D le32_to_cpu(resp->intval.value); + break; + default: + dev_warn(battmgr->dev, "unknown property %#x\n", property); + break; + } + break; default: dev_warn(battmgr->dev, "unknown message %#x\n", opcode); break; @@ -1583,6 +1888,8 @@ static void qcom_battmgr_callback(const void *data, s= ize_t len, void *priv) qcom_battmgr_sm8350_callback(battmgr, data, len); } =20 +static char *qcom_battmgr_battery[] =3D { "battery" }; + static void qcom_battmgr_enable_worker(struct work_struct *work) { struct qcom_battmgr *battmgr =3D container_of(work, struct qcom_battmgr, = enable_work); @@ -1591,11 +1898,53 @@ static void qcom_battmgr_enable_worker(struct work_= struct *work) .hdr.type =3D cpu_to_le32(PMIC_GLINK_NOTIFY), .hdr.opcode =3D cpu_to_le32(BATTMGR_REQUEST_NOTIFICATION), }; + struct power_supply *psy; int ret; + int num_ports_fw =3D 0; =20 ret =3D qcom_battmgr_request(battmgr, &req, sizeof(req)); if (ret) dev_err(battmgr->dev, "failed to request power notifications\n"); + + if (battmgr->variant =3D=3D QCOM_BATTMGR_X1E80100) { + mutex_lock(&battmgr->lock); + ret =3D qcom_battmgr_request_property(battmgr, BATTMGR_USB_PROPERTY_GET, + USB_NUM_PORTS, 0); + mutex_unlock(&battmgr->lock); + if (ret < 0) { + dev_dbg(battmgr->dev, "Failed to read USB_NUM_PORTS from SoCCP, rc=3D%d= \n", + ret); + } else { + num_ports_fw =3D battmgr->usb.num_ports; + if (num_ports_fw > MAX_USB_PORTS) { + dev_err(battmgr->dev, "USB ports reported by SoCCP: %d exceeds max %d\= n", + num_ports_fw, MAX_USB_PORTS); + num_ports_fw =3D MAX_USB_PORTS; + } + } + + if (num_ports_fw >=3D 2 && !battmgr->usb2_psy) { + psy =3D devm_power_supply_register(battmgr->dev, &x1e80100_usb2_psy_des= c, + &battmgr->usb_psy_cfg); + if (IS_ERR(psy)) { + dev_err(battmgr->dev, "failed to register USB port-1 power supply: %ld= \n", + PTR_ERR(psy)); + } else { + battmgr->usb2_psy =3D psy; + } + } + + if (num_ports_fw >=3D 3 && !battmgr->usb3_psy) { + psy =3D devm_power_supply_register(battmgr->dev, &x1e80100_usb3_psy_des= c, + &battmgr->usb_psy_cfg); + if (IS_ERR(psy)) { + dev_err(battmgr->dev, "failed to register USB port-2 power supply: %ld= \n", + PTR_ERR(psy)); + } else { + battmgr->usb3_psy =3D psy; + } + } + } } =20 static void qcom_battmgr_pdr_notify(void *priv, int state) @@ -1621,8 +1970,6 @@ static const struct of_device_id qcom_battmgr_of_vari= ants[] =3D { {} }; =20 -static char *qcom_battmgr_battery[] =3D { "battery" }; - static int qcom_battmgr_probe(struct auxiliary_device *adev, const struct auxiliary_device_id *id) { @@ -1648,6 +1995,8 @@ static int qcom_battmgr_probe(struct auxiliary_device= *adev, psy_cfg_supply.supplied_to =3D qcom_battmgr_battery; psy_cfg_supply.num_supplicants =3D 1; =20 + battmgr->usb_psy_cfg =3D psy_cfg_supply; + INIT_WORK(&battmgr->enable_work, qcom_battmgr_enable_worker); mutex_init(&battmgr->lock); init_completion(&battmgr->ack); --- base-commit: 5c73cd9f0819c1c44e373e3dabb68318b1de1a12 change-id: 20260801-b4-battmgr-multiport-usb-46eb0798668f Best regards, -- =20 Kamal Wadhwa