From nobody Thu Apr 2 23:57:12 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 751B732720C; Wed, 25 Mar 2026 22:22:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774477355; cv=none; b=sfyJdQlEktCBBjBz1h4UHv7nOGGRTm2sHO4oiCOJkRO1yWHfEuYzHs9JRSfOY7jkep1hMB/CD8D7xLQbLsFdb9IRrtkvlislmfAbYVlXH/HbsGyoR15KP0Hno4A47wQwke2irtiBn6CgNBmFIAKZe/Yt5u0NjxstOxXGeOaWPVA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774477355; c=relaxed/simple; bh=9UCX6c9kBue4B3sgbyp0P1Fi4/nUyuZVOM3nKzPEbWs=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=BBtjSlKDqziHM9iiIYV3OhYVP7VVZJd6SA33VJWL4POjT+LDHG3J4S0BpDUYJ9T8saWWCDg0d3vwtEE2t3oI4JzRWvx3MGXaSffoH99FoWsole9GCxKRUWd0BNbu6KmdQJ97PZ/KrXdME71SlumiDhl7OY+ePeBF0MvYCPevVNs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=LXpL4/p+; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="LXpL4/p+" Received: by smtp.kernel.org (Postfix) with ESMTPS id 30C08C116C6; Wed, 25 Mar 2026 22:22:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774477355; bh=9UCX6c9kBue4B3sgbyp0P1Fi4/nUyuZVOM3nKzPEbWs=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=LXpL4/p+3x2GYazbMumdPJ2u0s4HQn9WONBeVb9KuNqoRECEJnYzgV62TPBISI4HI Iqp790T4+F4A9fD843kXcVg1Som7DXB2K/33XuNn9DPJEn4YVnIyZzc7K9k8Wg/tYt ENIDnHJ5i863lJbZSYBcOfmFSCaTc6f9ZZwIE/A/HfSXDgrxyAwW2DqiTqGlE3be6e DiW3UTchGsxv65duWRfMxOqdFJ/g6pd5Dt1cBmqBHpDltPCmTy7iIsQbhRnJCfL1o7 s5CmltsEo8KIfquu2hNIOL7UYXxekWnsjQRfyOVPCI4+aw1KgvKaAQpnoalH/axvB1 QQoXKCthNx2ig== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1D4B6109E527; Wed, 25 Mar 2026 22:22:35 +0000 (UTC) From: Amit Sunil Dhamne via B4 Relay Date: Wed, 25 Mar 2026 22:22:22 +0000 Subject: [PATCH v9 1/6] dt-bindings: mfd: maxim,max77759: reference power-supply schema and add regulator property 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: <20260325-max77759-charger-v9-1-4486dd297adc@google.com> References: <20260325-max77759-charger-v9-0-4486dd297adc@google.com> In-Reply-To: <20260325-max77759-charger-v9-0-4486dd297adc@google.com> To: Sebastian Reichel , Rob Herring , Krzysztof Kozlowski , Conor Dooley , =?utf-8?q?Andr=C3=A9_Draszik?= , Lee Jones , Greg Kroah-Hartman , Badhri Jagan Sridharan , Heikki Krogerus , Peter Griffin , Tudor Ambarus , Alim Akhtar , Mark Brown , Matti Vaittinen , Andrew Morton Cc: linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, devicetree@vger.kernel.org, linux-usb@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-samsung-soc@vger.kernel.org, RD Babiera , Kyle Tso , Amit Sunil Dhamne , Krzysztof Kozlowski X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=ed25519-sha256; t=1774477354; l=1898; i=amitsd@google.com; s=20241031; h=from:subject:message-id; bh=vVEQb41vA+t6rlDPrzI7KwMZCc1WnDQaHQOICIfZd9s=; b=3j8YrSqS2bsLk/cq1k+cPifauF6cnA/HvyVgV3zfi6ELmpRQH1eCykwiBpndv7iy2yRq7X+Nb dlkLgbGkw+XDPWm5EOdSmAvy1c1LmTTfrfNnRNTWTGW2hotstxIGsab X-Developer-Key: i=amitsd@google.com; a=ed25519; pk=wD+XZSST4dmnNZf62/lqJpLm7fiyT8iv462zmQ3H6bI= X-Endpoint-Received: by B4 Relay for amitsd@google.com/20241031 with auth_id=262 X-Original-From: Amit Sunil Dhamne Reply-To: amitsd@google.com From: Amit Sunil Dhamne Extend the max77759 binding to reference power-supply schema, so that PMIC node can reference its supplier. Also, add regulator property to control CHGIN (OTG) voltage. Signed-off-by: Amit Sunil Dhamne Reviewed-by: Krzysztof Kozlowski Reviewed-by: Andr=C3=A9 Draszik --- .../devicetree/bindings/mfd/maxim,max77759.yaml | 16 ++++++++++++= +++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/mfd/maxim,max77759.yaml b/Do= cumentation/devicetree/bindings/mfd/maxim,max77759.yaml index 525de9ab3c2b..42e4a84d5204 100644 --- a/Documentation/devicetree/bindings/mfd/maxim,max77759.yaml +++ b/Documentation/devicetree/bindings/mfd/maxim,max77759.yaml @@ -16,6 +16,9 @@ description: | The MAX77759 includes Battery Charger, Fuel Gauge, temperature sensors, = USB Type-C Port Controller (TCPC), NVMEM, and a GPIO expander. =20 +allOf: + - $ref: /schemas/power/supply/power-supply.yaml# + properties: compatible: const: maxim,max77759 @@ -37,12 +40,18 @@ properties: nvmem-0: $ref: /schemas/nvmem/maxim,max77759-nvmem.yaml =20 + chgin-otg-regulator: + type: object + description: Provides Boost for sourcing VBUS. + $ref: /schemas/regulator/regulator.yaml# + unevaluatedProperties: false + required: - compatible - interrupts - reg =20 -additionalProperties: false +unevaluatedProperties: false =20 examples: - | @@ -59,6 +68,11 @@ examples: =20 interrupt-controller; #interrupt-cells =3D <2>; + power-supplies =3D <&maxtcpci>; + + chgin-otg-regulator { + regulator-name =3D "chgin-otg"; + }; =20 gpio { compatible =3D "maxim,max77759-gpio"; --=20 2.53.0.1018.g2bb0e51243-goog From nobody Thu Apr 2 23:57:12 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 7509D322B7B; Wed, 25 Mar 2026 22:22:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774477355; cv=none; b=qtMgbhJMX5q+6LYfunU8YS1hvupoUcpeTvf6WpMs0DRcwjsWcuN7NFz9moZq1sZPsjwYjoiQHlwYzRosSe8Z3Tx6czenkjJMVUJ72w4V9LY9Yt+fvpGP7PEmjoQTH1fItvxWWUmvPWhYGg/t8mF69EPdSKfcy1MZDg+XCAVFT5w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774477355; c=relaxed/simple; bh=2aya4qzSBOnrqFcF0qCiQffRH1oUsnDZtVMTEa3jgnE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=IBzY1qykXeZgqFkQi60g7qryJ/32A899e0A7amhiloGBM+/v9s33LGFY84Ku9aHqapBGH4sEul5nOjQp7UocvkR1fyBX/CpZZZA4DVngP0XDS6hPtxafgNICQfSfMxytztzj60PnYBDb4QC0VgH0XmQAMhHnVStHx8U0huEhf7w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ml0wSrig; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ml0wSrig" Received: by smtp.kernel.org (Postfix) with ESMTPS id 405E1C2BCB4; Wed, 25 Mar 2026 22:22:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774477355; bh=2aya4qzSBOnrqFcF0qCiQffRH1oUsnDZtVMTEa3jgnE=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=ml0wSrigpR2DeHga6KHr4v8dLcTUo6ZEco/FPiw8erY70q6kzf7ChYRCbB2s0ofgb lyASFqjbGMUfN5L6AdvdLHLN7ekJi2XNYkYSeRz73uM+dINv+ffNxuhLPoY5sqgm1G GEr3N5/5sNx+cHyIGzHr6yMKnnTbnzkPkufn4cWvHLeR9XAOpkOmZKfTLzO36OYgsP cBW53YtJBPDamav8JExn4XpIJlywsnnNtXUSkG6HWFHaIagdQaLq7AnYGwqPdyBJ8B mkqQoVWtVaal+uwX2jwTyhi+eI5Y7kLlw69SuVKN5XhyndQ8uz28iY7hhuQmKOOWS+ sTBdrObXYChgg== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 34FD4109E529; Wed, 25 Mar 2026 22:22:35 +0000 (UTC) From: Amit Sunil Dhamne via B4 Relay Date: Wed, 25 Mar 2026 22:22:23 +0000 Subject: [PATCH v9 2/6] dt-bindings: usb: maxim,max33359: Add supply property for vbus 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: <20260325-max77759-charger-v9-2-4486dd297adc@google.com> References: <20260325-max77759-charger-v9-0-4486dd297adc@google.com> In-Reply-To: <20260325-max77759-charger-v9-0-4486dd297adc@google.com> To: Sebastian Reichel , Rob Herring , Krzysztof Kozlowski , Conor Dooley , =?utf-8?q?Andr=C3=A9_Draszik?= , Lee Jones , Greg Kroah-Hartman , Badhri Jagan Sridharan , Heikki Krogerus , Peter Griffin , Tudor Ambarus , Alim Akhtar , Mark Brown , Matti Vaittinen , Andrew Morton Cc: linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, devicetree@vger.kernel.org, linux-usb@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-samsung-soc@vger.kernel.org, RD Babiera , Kyle Tso , Amit Sunil Dhamne , Krzysztof Kozlowski X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=ed25519-sha256; t=1774477354; l=1273; i=amitsd@google.com; s=20241031; h=from:subject:message-id; bh=xHGJ1Vk5ohekxV/HkgsFaQ5FhplVGnbXa8tx/HTuhSE=; b=CTTOsuHGqVUcu4uWfAFuYbSqHf/2gLAtRaF9QcKDjxZI511TxrXnXqTcN5uL2O40X58LVgvhg 2xQrghgR95LAiEQ4UxBVsFYDj/kEO+8Q7PFMWxrkTvQlb05IeA8qpkG X-Developer-Key: i=amitsd@google.com; a=ed25519; pk=wD+XZSST4dmnNZf62/lqJpLm7fiyT8iv462zmQ3H6bI= X-Endpoint-Received: by B4 Relay for amitsd@google.com/20241031 with auth_id=262 X-Original-From: Amit Sunil Dhamne Reply-To: amitsd@google.com From: Amit Sunil Dhamne Add a regulator supply property for vbus. This notifies the regulator provider to source vbus when Type-C operates in Source power mode, while turn off sourcing vbus when operating in Sink mode or disconnected. Signed-off-by: Amit Sunil Dhamne Acked-by: Krzysztof Kozlowski --- Documentation/devicetree/bindings/usb/maxim,max33359.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/usb/maxim,max33359.yaml b/Do= cumentation/devicetree/bindings/usb/maxim,max33359.yaml index 3de4dc40b791..e652a24902ea 100644 --- a/Documentation/devicetree/bindings/usb/maxim,max33359.yaml +++ b/Documentation/devicetree/bindings/usb/maxim,max33359.yaml @@ -32,6 +32,9 @@ properties: description: Properties for usb c connector. =20 + vbus-supply: + description: Regulator to control sourcing Vbus. + required: - compatible - reg @@ -53,6 +56,7 @@ examples: reg =3D <0x25>; interrupt-parent =3D <&gpa8>; interrupts =3D <2 IRQ_TYPE_LEVEL_LOW>; + vbus-supply =3D <&chgin_otg_reg>; =20 connector { compatible =3D "usb-c-connector"; --=20 2.53.0.1018.g2bb0e51243-goog From nobody Thu Apr 2 23:57:12 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 9AB3E34CFD1; Wed, 25 Mar 2026 22:22:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774477355; cv=none; b=RmTgWL3FwIDUg15Ejse/+UjcmieBLXQQ1iISvyLHN+sj3Yf/rQnGHpb2RJz3KkFl1QjkF2wcOxN3Aul/m5Qt5juyhl1JWfS+onePEserQICdPF+z9FgPEmSWepiLwG1bskPn+tPZ4c2W7GWiLQJV8T2dl3vlKRkYHu/9W6j0T9M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774477355; c=relaxed/simple; bh=3dOJBsu/mhOxw7zFeDS89B+Ji5i6+gCIrRC9/H1hK38=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=mhbPHYqNgjQuSDMl0ovV8TuidqFmkx3bQe1MQ2PZnpjPnzaajiCUhhRknFU/+0wl5Kc/7/xz4VUcXlodJBEQMATSeRlZtwyNGTQpYm0wdG9ZK1BXBI2Lt+UIvt4IlwRCV+RRZX1VXE6uRrMRu0ZsvkSuee/cKQ47isNZnS9aPN8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=omyzdFwu; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="omyzdFwu" Received: by smtp.kernel.org (Postfix) with ESMTPS id 5FC61C2BCB9; Wed, 25 Mar 2026 22:22:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774477355; bh=3dOJBsu/mhOxw7zFeDS89B+Ji5i6+gCIrRC9/H1hK38=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=omyzdFwu0eJpZEFvkOre0WchwcHX5Yaw7WPhwLodQwsKEfz7Q+lN7Ky6Y8hxLjDMo 1La1uKEZCmVi106T5bEnuKOCo1VdkuCURoW1zzIba+76GsLVrJhRRvUxX7N6glbV71 wWLh8WKRs4evcWr5KtRSGmxw7/3zDsFvnAKw+pBn8x15UIpffWwZdYW2qxJ4ziwN6n iuzzXdcWVkfKSgYKS83481Az8iK48/6FhR+QpBIeYC1bCUbCjceg1tJtMxkNjXVi8r QTYtpzX5D+Q+qsKzDYrALRS4YsWu5aibVDxMx4tlRoIhU6QIKa8SLPWCVG1/qbp8hu g4aoy6VCq7JCw== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 516AD109E523; Wed, 25 Mar 2026 22:22:35 +0000 (UTC) From: Amit Sunil Dhamne via B4 Relay Date: Wed, 25 Mar 2026 22:22:24 +0000 Subject: [PATCH v9 3/6] mfd: max77759: add register bitmasks and modify irq configs for charger 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: <20260325-max77759-charger-v9-3-4486dd297adc@google.com> References: <20260325-max77759-charger-v9-0-4486dd297adc@google.com> In-Reply-To: <20260325-max77759-charger-v9-0-4486dd297adc@google.com> To: Sebastian Reichel , Rob Herring , Krzysztof Kozlowski , Conor Dooley , =?utf-8?q?Andr=C3=A9_Draszik?= , Lee Jones , Greg Kroah-Hartman , Badhri Jagan Sridharan , Heikki Krogerus , Peter Griffin , Tudor Ambarus , Alim Akhtar , Mark Brown , Matti Vaittinen , Andrew Morton Cc: linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, devicetree@vger.kernel.org, linux-usb@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-samsung-soc@vger.kernel.org, RD Babiera , Kyle Tso , Amit Sunil Dhamne X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=ed25519-sha256; t=1774477354; l=15745; i=amitsd@google.com; s=20241031; h=from:subject:message-id; bh=RmkenkZNLl78Q5/ZYdNWEU6X8RjyetJUGBcnWXXmEPA=; b=O0nXCUcDy2DJ9WSmLpe7ex+yuYGCL89x7kW6arbZZ80HEtU/M0i64SAtlShlWUfqsLuEsZIi8 JFMs1i8yXIGDD67Pa0uXQ6VioMQo9YAIWbgOmKXjfVCqIi0Z2/tc7f/ X-Developer-Key: i=amitsd@google.com; a=ed25519; pk=wD+XZSST4dmnNZf62/lqJpLm7fiyT8iv462zmQ3H6bI= X-Endpoint-Received: by B4 Relay for amitsd@google.com/20241031 with auth_id=262 X-Original-From: Amit Sunil Dhamne Reply-To: amitsd@google.com From: Amit Sunil Dhamne Add register bitmasks for charger function. In addition split the charger IRQs further such that each bit represents an IRQ downstream of charger regmap irq chip. In addition populate the ack_base to offload irq ack to the regmap irq chip framework. Signed-off-by: Amit Sunil Dhamne Reviewed-by: Andr=C3=A9 Draszik --- drivers/mfd/max77759.c | 95 ++++++++++++++++++++++--- include/linux/mfd/max77759.h | 166 +++++++++++++++++++++++++++++++++++----= ---- 2 files changed, 222 insertions(+), 39 deletions(-) diff --git a/drivers/mfd/max77759.c b/drivers/mfd/max77759.c index a7efe233ec8c..9fa6027a92c4 100644 --- a/drivers/mfd/max77759.c +++ b/drivers/mfd/max77759.c @@ -201,8 +201,24 @@ static const struct regmap_config max77759_regmap_conf= ig_charger =3D { * - SYSUVLO_INT * - FSHIP_NOT_RD * - CHGR_INT: charger - * - CHG_INT - * - CHG_INT2 + * - INT1 + * - AICL + * - CHGIN + * - WCIN + * - CHG + * - BAT + * - INLIM + * - THM2 + * - BYP + * - INT2 + * - INSEL + * - SYS_UVLO1 + * - SYS_UVLO2 + * - BAT_OILO + * - CHG_STA_CC + * - CHG_STA_CV + * - CHG_STA_TO + * - CHG_STA_DONE */ enum { MAX77759_INT_MAXQ, @@ -228,8 +244,22 @@ enum { }; =20 enum { - MAX77759_CHARGER_INT_1, - MAX77759_CHARGER_INT_2, + MAX77759_CHGR_INT1_AICL, + MAX77759_CHGR_INT1_CHGIN, + MAX77759_CHGR_INT1_WCIN, + MAX77759_CHGR_INT1_CHG, + MAX77759_CHGR_INT1_BAT, + MAX77759_CHGR_INT1_INLIM, + MAX77759_CHGR_INT1_THM2, + MAX77759_CHGR_INT1_BYP, + MAX77759_CHGR_INT2_INSEL, + MAX77759_CHGR_INT2_SYS_UVLO1, + MAX77759_CHGR_INT2_SYS_UVLO2, + MAX77759_CHGR_INT2_BAT_OILO, + MAX77759_CHGR_INT2_CHG_STA_CC, + MAX77759_CHGR_INT2_CHG_STA_CV, + MAX77759_CHGR_INT2_CHG_STA_TO, + MAX77759_CHGR_INT2_CHG_STA_DONE, }; =20 static const struct regmap_irq max77759_pmic_irqs[] =3D { @@ -256,8 +286,38 @@ static const struct regmap_irq max77759_topsys_irqs[] = =3D { }; =20 static const struct regmap_irq max77759_chgr_irqs[] =3D { - REGMAP_IRQ_REG(MAX77759_CHARGER_INT_1, 0, GENMASK(7, 0)), - REGMAP_IRQ_REG(MAX77759_CHARGER_INT_2, 1, GENMASK(7, 0)), + REGMAP_IRQ_REG(MAX77759_CHGR_INT1_AICL, 0, + MAX77759_CHGR_REG_CHG_INT_AICL), + REGMAP_IRQ_REG(MAX77759_CHGR_INT1_CHGIN, 0, + MAX77759_CHGR_REG_CHG_INT_CHGIN), + REGMAP_IRQ_REG(MAX77759_CHGR_INT1_WCIN, 0, + MAX77759_CHGR_REG_CHG_INT_WCIN), + REGMAP_IRQ_REG(MAX77759_CHGR_INT1_CHG, 0, + MAX77759_CHGR_REG_CHG_INT_CHG), + REGMAP_IRQ_REG(MAX77759_CHGR_INT1_BAT, 0, + MAX77759_CHGR_REG_CHG_INT_BAT), + REGMAP_IRQ_REG(MAX77759_CHGR_INT1_INLIM, 0, + MAX77759_CHGR_REG_CHG_INT_INLIM), + REGMAP_IRQ_REG(MAX77759_CHGR_INT1_THM2, 0, + MAX77759_CHGR_REG_CHG_INT_THM2), + REGMAP_IRQ_REG(MAX77759_CHGR_INT1_BYP, 0, + MAX77759_CHGR_REG_CHG_INT_BYP), + REGMAP_IRQ_REG(MAX77759_CHGR_INT2_INSEL, 1, + MAX77759_CHGR_REG_CHG_INT2_INSEL), + REGMAP_IRQ_REG(MAX77759_CHGR_INT2_SYS_UVLO1, 1, + MAX77759_CHGR_REG_CHG_INT2_SYS_UVLO1), + REGMAP_IRQ_REG(MAX77759_CHGR_INT2_SYS_UVLO2, 1, + MAX77759_CHGR_REG_CHG_INT2_SYS_UVLO2), + REGMAP_IRQ_REG(MAX77759_CHGR_INT2_BAT_OILO, 1, + MAX77759_CHGR_REG_CHG_INT2_BAT_OILO), + REGMAP_IRQ_REG(MAX77759_CHGR_INT2_CHG_STA_CC, 1, + MAX77759_CHGR_REG_CHG_INT2_CHG_STA_CC), + REGMAP_IRQ_REG(MAX77759_CHGR_INT2_CHG_STA_CV, 1, + MAX77759_CHGR_REG_CHG_INT2_CHG_STA_CV), + REGMAP_IRQ_REG(MAX77759_CHGR_INT2_CHG_STA_TO, 1, + MAX77759_CHGR_REG_CHG_INT2_CHG_STA_TO), + REGMAP_IRQ_REG(MAX77759_CHGR_INT2_CHG_STA_DONE, 1, + MAX77759_CHGR_REG_CHG_INT2_CHG_STA_DONE), }; =20 static const struct regmap_irq_chip max77759_pmic_irq_chip =3D { @@ -297,11 +357,12 @@ static const struct regmap_irq_chip max77759_topsys_i= rq_chip =3D { .num_irqs =3D ARRAY_SIZE(max77759_topsys_irqs), }; =20 -static const struct regmap_irq_chip max77759_chrg_irq_chip =3D { +static const struct regmap_irq_chip max77759_chgr_irq_chip =3D { .name =3D "max77759-chgr", .domain_suffix =3D "CHGR", .status_base =3D MAX77759_CHGR_REG_CHG_INT, .mask_base =3D MAX77759_CHGR_REG_CHG_INT_MASK, + .ack_base =3D MAX77759_CHGR_REG_CHG_INT, .num_regs =3D 2, .irqs =3D max77759_chgr_irqs, .num_irqs =3D ARRAY_SIZE(max77759_chgr_irqs), @@ -325,8 +386,22 @@ static const struct resource max77759_gpio_resources[]= =3D { }; =20 static const struct resource max77759_charger_resources[] =3D { - DEFINE_RES_IRQ_NAMED(MAX77759_CHARGER_INT_1, "INT1"), - DEFINE_RES_IRQ_NAMED(MAX77759_CHARGER_INT_2, "INT2"), + DEFINE_RES_IRQ_NAMED(MAX77759_CHGR_INT1_AICL, "AICL"), + DEFINE_RES_IRQ_NAMED(MAX77759_CHGR_INT1_CHGIN, "CHGIN"), + DEFINE_RES_IRQ_NAMED(MAX77759_CHGR_INT1_WCIN, "WCIN"), + DEFINE_RES_IRQ_NAMED(MAX77759_CHGR_INT1_CHG, "CHG"), + DEFINE_RES_IRQ_NAMED(MAX77759_CHGR_INT1_BAT, "BAT"), + DEFINE_RES_IRQ_NAMED(MAX77759_CHGR_INT1_INLIM, "INLIM"), + DEFINE_RES_IRQ_NAMED(MAX77759_CHGR_INT1_THM2, "THM2"), + DEFINE_RES_IRQ_NAMED(MAX77759_CHGR_INT1_BYP, "BYP"), + DEFINE_RES_IRQ_NAMED(MAX77759_CHGR_INT2_INSEL, "INSEL"), + DEFINE_RES_IRQ_NAMED(MAX77759_CHGR_INT2_SYS_UVLO1, "SYS_UVLO1"), + DEFINE_RES_IRQ_NAMED(MAX77759_CHGR_INT2_SYS_UVLO2, "SYS_UVLO2"), + DEFINE_RES_IRQ_NAMED(MAX77759_CHGR_INT2_BAT_OILO, "BAT_OILO"), + DEFINE_RES_IRQ_NAMED(MAX77759_CHGR_INT2_CHG_STA_CC, "CHG_STA_CC"), + DEFINE_RES_IRQ_NAMED(MAX77759_CHGR_INT2_CHG_STA_CV, "CHG_STA_CV"), + DEFINE_RES_IRQ_NAMED(MAX77759_CHGR_INT2_CHG_STA_TO, "CHG_STA_TO"), + DEFINE_RES_IRQ_NAMED(MAX77759_CHGR_INT2_CHG_STA_DONE, "CHG_STA_DONE"), }; =20 static const struct mfd_cell max77759_cells[] =3D { @@ -567,7 +642,7 @@ static int max77759_add_chained_charger(struct i2c_clie= nt *client, max77759->regmap_charger, MAX77759_INT_CHGR, parent, - &max77759_chrg_irq_chip, + &max77759_chgr_irq_chip, &irq_chip_data); if (ret) return ret; diff --git a/include/linux/mfd/max77759.h b/include/linux/mfd/max77759.h index c6face34e385..ad1aa4c2b779 100644 --- a/include/linux/mfd/max77759.h +++ b/include/linux/mfd/max77759.h @@ -59,35 +59,65 @@ #define MAX77759_MAXQ_REG_AP_DATAIN0 0xb1 #define MAX77759_MAXQ_REG_UIC_SWRST 0xe0 =20 -#define MAX77759_CHGR_REG_CHG_INT 0xb0 -#define MAX77759_CHGR_REG_CHG_INT2 0xb1 -#define MAX77759_CHGR_REG_CHG_INT_MASK 0xb2 -#define MAX77759_CHGR_REG_CHG_INT2_MASK 0xb3 -#define MAX77759_CHGR_REG_CHG_INT_OK 0xb4 -#define MAX77759_CHGR_REG_CHG_DETAILS_00 0xb5 -#define MAX77759_CHGR_REG_CHG_DETAILS_01 0xb6 -#define MAX77759_CHGR_REG_CHG_DETAILS_02 0xb7 -#define MAX77759_CHGR_REG_CHG_DETAILS_03 0xb8 -#define MAX77759_CHGR_REG_CHG_CNFG_00 0xb9 -#define MAX77759_CHGR_REG_CHG_CNFG_01 0xba -#define MAX77759_CHGR_REG_CHG_CNFG_02 0xbb -#define MAX77759_CHGR_REG_CHG_CNFG_03 0xbc -#define MAX77759_CHGR_REG_CHG_CNFG_04 0xbd -#define MAX77759_CHGR_REG_CHG_CNFG_05 0xbe -#define MAX77759_CHGR_REG_CHG_CNFG_06 0xbf -#define MAX77759_CHGR_REG_CHG_CNFG_07 0xc0 -#define MAX77759_CHGR_REG_CHG_CNFG_08 0xc1 -#define MAX77759_CHGR_REG_CHG_CNFG_09 0xc2 -#define MAX77759_CHGR_REG_CHG_CNFG_10 0xc3 -#define MAX77759_CHGR_REG_CHG_CNFG_11 0xc4 -#define MAX77759_CHGR_REG_CHG_CNFG_12 0xc5 -#define MAX77759_CHGR_REG_CHG_CNFG_13 0xc6 -#define MAX77759_CHGR_REG_CHG_CNFG_14 0xc7 -#define MAX77759_CHGR_REG_CHG_CNFG_15 0xc8 -#define MAX77759_CHGR_REG_CHG_CNFG_16 0xc9 -#define MAX77759_CHGR_REG_CHG_CNFG_17 0xca -#define MAX77759_CHGR_REG_CHG_CNFG_18 0xcb -#define MAX77759_CHGR_REG_CHG_CNFG_19 0xcc +#define MAX77759_CHGR_REG_CHG_INT 0xb0 +#define MAX77759_CHGR_REG_CHG_INT_AICL BIT(7) +#define MAX77759_CHGR_REG_CHG_INT_CHGIN BIT(6) +#define MAX77759_CHGR_REG_CHG_INT_WCIN BIT(5) +#define MAX77759_CHGR_REG_CHG_INT_CHG BIT(4) +#define MAX77759_CHGR_REG_CHG_INT_BAT BIT(3) +#define MAX77759_CHGR_REG_CHG_INT_INLIM BIT(2) +#define MAX77759_CHGR_REG_CHG_INT_THM2 BIT(1) +#define MAX77759_CHGR_REG_CHG_INT_BYP BIT(0) +#define MAX77759_CHGR_REG_CHG_INT2 0xb1 +#define MAX77759_CHGR_REG_CHG_INT2_INSEL BIT(7) +#define MAX77759_CHGR_REG_CHG_INT2_SYS_UVLO1 BIT(6) +#define MAX77759_CHGR_REG_CHG_INT2_SYS_UVLO2 BIT(5) +#define MAX77759_CHGR_REG_CHG_INT2_BAT_OILO BIT(4) +#define MAX77759_CHGR_REG_CHG_INT2_CHG_STA_CC BIT(3) +#define MAX77759_CHGR_REG_CHG_INT2_CHG_STA_CV BIT(2) +#define MAX77759_CHGR_REG_CHG_INT2_CHG_STA_TO BIT(1) +#define MAX77759_CHGR_REG_CHG_INT2_CHG_STA_DONE BIT(0) +#define MAX77759_CHGR_REG_CHG_INT_MASK 0xb2 +#define MAX77759_CHGR_REG_CHG_INT2_MASK 0xb3 +#define MAX77759_CHGR_REG_CHG_INT_OK 0xb4 +#define MAX77759_CHGR_REG_CHG_DETAILS_00 0xb5 +#define MAX77759_CHGR_REG_CHG_DETAILS_00_CHGIN_DTLS GENMASK(6, 5) +#define MAX77759_CHGR_REG_CHG_DETAILS_01 0xb6 +#define MAX77759_CHGR_REG_CHG_DETAILS_01_BAT_DTLS GENMASK(6, 4) +#define MAX77759_CHGR_REG_CHG_DETAILS_01_CHG_DTLS GENMASK(3, 0) +#define MAX77759_CHGR_REG_CHG_DETAILS_02 0xb7 +#define MAX77759_CHGR_REG_CHG_DETAILS_02_CHGIN_STS BIT(5) +#define MAX77759_CHGR_REG_CHG_DETAILS_03 0xb8 +#define MAX77759_CHGR_REG_CHG_CNFG_00 0xb9 +#define MAX77759_CHGR_REG_CHG_CNFG_00_MODE GENMASK(3, 0) +#define MAX77759_CHGR_REG_CHG_CNFG_01 0xba +#define MAX77759_CHGR_REG_CHG_CNFG_02 0xbb +#define MAX77759_CHGR_REG_CHG_CNFG_02_CHGCC GENMASK(5, 0) +#define MAX77759_CHGR_REG_CHG_CNFG_03 0xbc +#define MAX77759_CHGR_REG_CHG_CNFG_04 0xbd +#define MAX77759_CHGR_REG_CHG_CNFG_04_CHG_CV_PRM GENMASK(5, 0) +#define MAX77759_CHGR_REG_CHG_CNFG_05 0xbe +#define MAX77759_CHGR_REG_CHG_CNFG_06 0xbf +#define MAX77759_CHGR_REG_CHG_CNFG_06_CHGPROT GENMASK(3, 2) +#define MAX77759_CHGR_REG_CHG_CNFG_07 0xc0 +#define MAX77759_CHGR_REG_CHG_CNFG_08 0xc1 +#define MAX77759_CHGR_REG_CHG_CNFG_09 0xc2 +#define MAX77759_CHGR_REG_CHG_CNFG_09_CHGIN_ILIM GENMASK(6, 0) +#define MAX77759_CHGR_REG_CHG_CNFG_10 0xc3 +#define MAX77759_CHGR_REG_CHG_CNFG_11 0xc4 +#define MAX77759_CHGR_REG_CHG_CNFG_12 0xc5 +/* Wireless Charging input channel select */ +#define MAX77759_CHGR_REG_CHG_CNFG_12_WCINSEL BIT(6) +/* CHGIN/USB input channel select */ +#define MAX77759_CHGR_REG_CHG_CNFG_12_CHGINSEL BIT(5) +#define MAX77759_CHGR_REG_CHG_CNFG_13 0xc6 +#define MAX77759_CHGR_REG_CHG_CNFG_14 0xc7 +#define MAX77759_CHGR_REG_CHG_CNFG_15 0xc8 +#define MAX77759_CHGR_REG_CHG_CNFG_16 0xc9 +#define MAX77759_CHGR_REG_CHG_CNFG_17 0xca +#define MAX77759_CHGR_REG_CHG_CNFG_18 0xcb +#define MAX77759_CHGR_REG_CHG_CNFG_18_WDTEN BIT(0) +#define MAX77759_CHGR_REG_CHG_CNFG_19 0xcc =20 /* MaxQ opcodes for max77759_maxq_command() */ #define MAX77759_MAXQ_OPCODE_MAXLENGTH (MAX77759_MAXQ_REG_AP_DATAOUT32 - \ @@ -101,6 +131,84 @@ #define MAX77759_MAXQ_OPCODE_USER_SPACE_READ 0x81 #define MAX77759_MAXQ_OPCODE_USER_SPACE_WRITE 0x82 =20 +/* + * enum max77759_chgr_chgin_dtls_status - Charger Input Status + * @MAX77759_CHGR_CHGIN_DTLS_VBUS_UNDERVOLTAGE: + * Charger input voltage (Vchgin) < Under Voltage Threshold (Vuvlo) + * @MAX77759_CHGR_CHGIN_DTLS_VBUS_MARGINAL_VOLTAGE: Vchgin > Vuvlo and + * Vchgin < (Battery Voltage (Vbatt) + system voltage (Vsys)) + * @MAX77759_CHGR_CHGIN_DTLS_VBUS_OVERVOLTAGE: + * Vchgin > Over Voltage threshold (Vovlo) + * @MAX77759_CHGR_CHGIN_DTLS_VBUS_VALID: + * Vchgin > Vuvlo, Vchgin < Vovlo and Vchgin > (Vsys + Vbatt) + */ +enum max77759_chgr_chgin_dtls_status { + MAX77759_CHGR_CHGIN_DTLS_VBUS_UNDERVOLTAGE, + MAX77759_CHGR_CHGIN_DTLS_VBUS_MARGINAL_VOLTAGE, + MAX77759_CHGR_CHGIN_DTLS_VBUS_OVERVOLTAGE, + MAX77759_CHGR_CHGIN_DTLS_VBUS_VALID, +}; + +/* + * enum max77759_chgr_bat_dtls_states - Battery Details + * @MAX77759_CHGR_BAT_DTLS_NO_BATT_CHG_SUSP: No battery and the charger su= spended + * @MAX77759_CHGR_BAT_DTLS_DEAD_BATTERY: Vbatt < Vtrickle + * @MAX77759_CHGR_BAT_DTLS_BAT_CHG_TIMER_FAULT: Charging suspended due to = timer fault + * @MAX77759_CHGR_BAT_DTLS_BAT_OKAY: Battery okay and Vbatt > Min Sys Vol= tage (Vsysmin) + * @MAX77759_CHGR_BAT_DTLS_BAT_UNDERVOLTAGE: Battery is okay. Vtrickle < V= batt < Vsysmin + * @MAX77759_CHGR_BAT_DTLS_BAT_OVERVOLTAGE: Battery voltage > Overvoltage = threshold + * @MAX77759_CHGR_BAT_DTLS_BAT_OVERCURRENT: Battery current exceeds overcu= rrent threshold + * @MAX77759_CHGR_BAT_DTLS_BAT_ONLY_MODE: Battery only mode and battery le= vel not available + */ +enum max77759_chgr_bat_dtls_states { + MAX77759_CHGR_BAT_DTLS_NO_BATT_CHG_SUSP, + MAX77759_CHGR_BAT_DTLS_DEAD_BATTERY, + MAX77759_CHGR_BAT_DTLS_BAT_CHG_TIMER_FAULT, + MAX77759_CHGR_BAT_DTLS_BAT_OKAY, + MAX77759_CHGR_BAT_DTLS_BAT_UNDERVOLTAGE, + MAX77759_CHGR_BAT_DTLS_BAT_OVERVOLTAGE, + MAX77759_CHGR_BAT_DTLS_BAT_OVERCURRENT, + MAX77759_CHGR_BAT_DTLS_BAT_ONLY_MODE, +}; + +/* + * enum max77759_chgr_chg_dtls_states - Charger Details + * @MAX77759_CHGR_CHG_DTLS_PREQUAL: Charger in prequalification mode + * @MAX77759_CHGR_CHG_DTLS_CC: Charger in fast charge const curr mode + * @MAX77759_CHGR_CHG_DTLS_CV: Charger in fast charge const voltage mode + * @MAX77759_CHGR_CHG_DTLS_TO: Charger is in top off mode + * @MAX77759_CHGR_CHG_DTLS_DONE: Charger is done + * @MAX77759_CHGR_CHG_DTLS_RSVD_1: Reserved + * @MAX77759_CHGR_CHG_DTLS_TIMER_FAULT: Charger is in timer fault mode + * @MAX77759_CHGR_CHG_DTLS_SUSP_BATT_THM: Charger is suspended as battery = removal detected + * @MAX77759_CHGR_CHG_DTLS_OFF: Charger is off. Input invalid or charger= disabled + * @MAX77759_CHGR_CHG_DTLS_RSVD_2: Reserved + * @MAX77759_CHGR_CHG_DTLS_RSVD_3: Reserved + * @MAX77759_CHGR_CHG_DTLS_OFF_WDOG_TIMER: Charger is off as watchdog time= r expired + * @MAX77759_CHGR_CHG_DTLS_SUSP_JEITA: Charger is in JEITA control mode + */ +enum max77759_chgr_chg_dtls_states { + MAX77759_CHGR_CHG_DTLS_PREQUAL, + MAX77759_CHGR_CHG_DTLS_CC, + MAX77759_CHGR_CHG_DTLS_CV, + MAX77759_CHGR_CHG_DTLS_TO, + MAX77759_CHGR_CHG_DTLS_DONE, + MAX77759_CHGR_CHG_DTLS_RSVD_1, + MAX77759_CHGR_CHG_DTLS_TIMER_FAULT, + MAX77759_CHGR_CHG_DTLS_SUSP_BATT_THM, + MAX77759_CHGR_CHG_DTLS_OFF, + MAX77759_CHGR_CHG_DTLS_RSVD_2, + MAX77759_CHGR_CHG_DTLS_RSVD_3, + MAX77759_CHGR_CHG_DTLS_OFF_WDOG_TIMER, + MAX77759_CHGR_CHG_DTLS_SUSP_JEITA, +}; + +enum max77759_chgr_mode { + MAX77759_CHGR_MODE_OFF, + MAX77759_CHGR_MODE_CHG_BUCK_ON =3D 0x5, + MAX77759_CHGR_MODE_OTG_BOOST_ON =3D 0xA, +}; + /** * struct max77759 - core max77759 internal data structure * --=20 2.53.0.1018.g2bb0e51243-goog From nobody Thu Apr 2 23:57:12 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 9DD0234EF12; Wed, 25 Mar 2026 22:22:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774477355; cv=none; b=VY7yKPv2jtosp3b3hVrQw6UW2WzkunvNFHchRr0dFiMSu1lY7pczpd+luoeLyc6v0aRTFCdoPdGgJp9hz3jdvCVEI5kl4b2Oc0vO+A3wqkVye9uHqFoMonglV3BQ+gXYFn/2fb/fNlS/mR7Fh14X1zBcBYHINlAc+oMj2Yxwhvg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774477355; c=relaxed/simple; bh=XlbkRM4Y81V56cTV6+/QXoC0VtBMPVLklzsTe2WL+4A=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=IJXQu8Yb2B5gYGmcbN9jtPEEf/Q31klcoedRKF8fmQW3+M8Jo1t9/mRNAXJDfJvb8QyREDrlQvlwTKUxNk9i0uUpmIidV7K7pI5fUz7LDnitIFEuiNz+rDN412EcRdfCe0xLagXKOibBCAxVALc2vXJktmlobe8f3bMc9+2vidk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=lQ69Jv8B; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="lQ69Jv8B" Received: by smtp.kernel.org (Postfix) with ESMTPS id 76E5DC2BCB2; Wed, 25 Mar 2026 22:22:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774477355; bh=XlbkRM4Y81V56cTV6+/QXoC0VtBMPVLklzsTe2WL+4A=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=lQ69Jv8B/3wQDhxqPuov8bHPKS0hHNxLndUK5wwPb9y5NyueAhiwDRgOlIBA8mCOZ Re2Vm8HOgJjjNMVa+hAOCTSFS4H/cZqLyFOupnoR8CgDT1H05ojyNAvPp7TBk31WSl 6f4/S8r9356ZmbgYuIlknWYE3Pil6XGUOWSZ+PPRC3/PGnJuesjn8MXmxv8OdCzZ73 TkxqM+teioQnumDahMEH+4hVFYgB0UXNTjOdixwWYjoXlau2fH+E7Dkc/yoS+HUWt+ 2TgDC6scEg3l2uPQLbxlFmH24xOMUkk28OG52sQtGqpLCDS7PmmLX9Hq82Ujogyuyk ANpB645nkO0FA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6BBDC109E529; Wed, 25 Mar 2026 22:22:35 +0000 (UTC) From: Amit Sunil Dhamne via B4 Relay Date: Wed, 25 Mar 2026 22:22:25 +0000 Subject: [PATCH v9 4/6] lib/linear_ranges: Add linear_range_get_selector_high_array 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: <20260325-max77759-charger-v9-4-4486dd297adc@google.com> References: <20260325-max77759-charger-v9-0-4486dd297adc@google.com> In-Reply-To: <20260325-max77759-charger-v9-0-4486dd297adc@google.com> To: Sebastian Reichel , Rob Herring , Krzysztof Kozlowski , Conor Dooley , =?utf-8?q?Andr=C3=A9_Draszik?= , Lee Jones , Greg Kroah-Hartman , Badhri Jagan Sridharan , Heikki Krogerus , Peter Griffin , Tudor Ambarus , Alim Akhtar , Mark Brown , Matti Vaittinen , Andrew Morton Cc: linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, devicetree@vger.kernel.org, linux-usb@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-samsung-soc@vger.kernel.org, RD Babiera , Kyle Tso , Amit Sunil Dhamne X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=ed25519-sha256; t=1774477354; l=3004; i=amitsd@google.com; s=20241031; h=from:subject:message-id; bh=Nqh5k2fIldoRheNZDSxzkfLUdV4de+6ygmmg823YqUE=; b=zFfRG5xDa1iRyZnqxrL4HRmDlQGIPEekP5OMzzTGSReG9mypAumDchcaavNYgfUVcps5AgubH rlsgj/H7UQLCHLyUh8/XTfNgfB1Casz8OIAv6Oq0clzrCFxNsB/ZduV X-Developer-Key: i=amitsd@google.com; a=ed25519; pk=wD+XZSST4dmnNZf62/lqJpLm7fiyT8iv462zmQ3H6bI= X-Endpoint-Received: by B4 Relay for amitsd@google.com/20241031 with auth_id=262 X-Original-From: Amit Sunil Dhamne Reply-To: amitsd@google.com From: Amit Sunil Dhamne Add a helper function to find the selector for a given value in a linear range array. The selector should be such that the value it represents should be higher or equal to the given value. Signed-off-by: Amit Sunil Dhamne Reviewed-by: Matti Vaittinen Acked-by: Mark Brown --- include/linux/linear_range.h | 3 +++ lib/linear_ranges.c | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/include/linux/linear_range.h b/include/linux/linear_range.h index 2e4f4c3539c0..0f3037f1a94f 100644 --- a/include/linux/linear_range.h +++ b/include/linux/linear_range.h @@ -57,5 +57,8 @@ void linear_range_get_selector_within(const struct linear= _range *r, int linear_range_get_selector_low_array(const struct linear_range *r, int ranges, unsigned int val, unsigned int *selector, bool *found); +int linear_range_get_selector_high_array(const struct linear_range *r, + int ranges, unsigned int val, + unsigned int *selector, bool *found); =20 #endif diff --git a/lib/linear_ranges.c b/lib/linear_ranges.c index a1a7dfa881de..c85583678f6b 100644 --- a/lib/linear_ranges.c +++ b/lib/linear_ranges.c @@ -241,6 +241,42 @@ int linear_range_get_selector_high(const struct linear= _range *r, } EXPORT_SYMBOL_GPL(linear_range_get_selector_high); =20 +/** + * linear_range_get_selector_high_array - return linear range selector for= value + * @r: pointer to array of linear ranges where selector is looked from + * @ranges: amount of ranges to scan from array + * @val: value for which the selector is searched + * @selector: address where found selector value is updated + * @found: flag to indicate that given value was in the range + * + * Scan array of ranges for selector for which range value matches given + * input value. Value is matching if it is equal or higher than given value + * If given value is found to be in a range scanning is stopped and @found= is + * set true. If a range with values greater than given value is found + * but the range min is being greater than given value, then the range's + * lowest selector is updated to @selector and scanning is stopped. + * + * Return: 0 on success, -EINVAL if range array is invalid or does not con= tain + * range with a value greater or equal to given value + */ +int linear_range_get_selector_high_array(const struct linear_range *r, + int ranges, unsigned int val, + unsigned int *selector, bool *found) +{ + int i; + int ret; + + for (i =3D 0; i < ranges; i++) { + ret =3D linear_range_get_selector_high(&r[i], val, selector, + found); + if (!ret) + return 0; + } + + return -EINVAL; +} +EXPORT_SYMBOL_GPL(linear_range_get_selector_high_array); + /** * linear_range_get_selector_within - return linear range selector for val= ue * @r: pointer to linear range where selector is looked from --=20 2.53.0.1018.g2bb0e51243-goog From nobody Thu Apr 2 23:57:12 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 B9F66359A89; Wed, 25 Mar 2026 22:22:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774477355; cv=none; b=qa3mJ89CrmTBqxSUnz1Nvab1ycaOuNAEvtfExRaOqPg2XfWICa/yJiLD+pR+Sd6FW/bZNAxFFfrpToX8l/xMEC95otJ7dzjvIEsXz6GOvPXlron9WLCiPT9UtfyJUtyTc1NWg3V6cxfNn3Lb+55yLPYjGVkx+6nRXEyD9zSuAac= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774477355; c=relaxed/simple; bh=3SO+n5qTK7w/Oq6SqASoseGkXsFMYkMW6T+K7R30Wg8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=SGjUlG8X/W3H6HuKqRbXp6k51MvW0c6J4+WkXD2oRGnoMgssv+Tc2Dy1rVO62Ue/hrbRNl0ljDZH6b5mMdKMU+erfbq+9ZN+rJcXXvonfBKP847bwEcMZos3rTkQGwmEJyRx5/+kRZEVZ3iHW46xAqfdKhTK3vq7y1OadKSMb0I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=FXaOcGXP; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="FXaOcGXP" Received: by smtp.kernel.org (Postfix) with ESMTPS id 972A7C4CEF7; Wed, 25 Mar 2026 22:22:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774477355; bh=3SO+n5qTK7w/Oq6SqASoseGkXsFMYkMW6T+K7R30Wg8=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=FXaOcGXP1iigIlbxBl0zmsU8y/VofUHIQnLjTcfU4c+8Lx8YQ3k/1CJmnFcHYy6B5 /0gNJ2NToT+u8/DFZDX+gmGmChBZiFOAi2W9ZQsiq1TGdIMHwHll/glu5rzUp6N2Ix 8rZwCGWJpI8FtVS5EQ/dr5t7un6phgMTFj205ej+QOAYy2iPKFSYXG6MR5UquHqsk5 ZJMTd46PKTYAAiRaHrGHKCc/WNEmNV/cWHmJb3cOR4utSp80Q4e9e5887c7dBkxtxq n7NJNzuOjsN/cIzg1QhO3LGNlbekSE34DWRbolkmYwrzmVvoKO/47P8FBu2XZOj6Xv Pa/uOCZa+jiIA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 81A2A109E527; Wed, 25 Mar 2026 22:22:35 +0000 (UTC) From: Amit Sunil Dhamne via B4 Relay Date: Wed, 25 Mar 2026 22:22:26 +0000 Subject: [PATCH v9 5/6] power: supply: max77759: add charger driver 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: <20260325-max77759-charger-v9-5-4486dd297adc@google.com> References: <20260325-max77759-charger-v9-0-4486dd297adc@google.com> In-Reply-To: <20260325-max77759-charger-v9-0-4486dd297adc@google.com> To: Sebastian Reichel , Rob Herring , Krzysztof Kozlowski , Conor Dooley , =?utf-8?q?Andr=C3=A9_Draszik?= , Lee Jones , Greg Kroah-Hartman , Badhri Jagan Sridharan , Heikki Krogerus , Peter Griffin , Tudor Ambarus , Alim Akhtar , Mark Brown , Matti Vaittinen , Andrew Morton Cc: linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, devicetree@vger.kernel.org, linux-usb@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-samsung-soc@vger.kernel.org, RD Babiera , Kyle Tso , Amit Sunil Dhamne X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=ed25519-sha256; t=1774477354; l=24145; i=amitsd@google.com; s=20241031; h=from:subject:message-id; bh=oC60pCC9Zcrbx6qJmDffH7xMY5pWSNjdusuYQFmIFeA=; b=9jDVjhtaDZb16V5VvvmIEnnnSXVCJvfuNr3PHvNWQiansbB1pqHk7NHsSk7azfH7lsOnn3dYJ R5Ex+Nqx/UNA821t8jiYq26Lt/0mhHWQCH2KvXnWuQIbSl4Ltdm8rxv X-Developer-Key: i=amitsd@google.com; a=ed25519; pk=wD+XZSST4dmnNZf62/lqJpLm7fiyT8iv462zmQ3H6bI= X-Endpoint-Received: by B4 Relay for amitsd@google.com/20241031 with auth_id=262 X-Original-From: Amit Sunil Dhamne Reply-To: amitsd@google.com From: Amit Sunil Dhamne Add support for MAX77759 battery charger driver. This is a 4A 1-Cell Li+/LiPoly dual input switch mode charger. While the device can support USB & wireless charger inputs, this implementation only supports USB input. This implementation supports both buck and boost modes. Signed-off-by: Amit Sunil Dhamne Reviewed-by: Andr=C3=A9 Draszik --- MAINTAINERS | 6 + drivers/power/supply/Kconfig | 11 + drivers/power/supply/Makefile | 1 + drivers/power/supply/max77759_charger.c | 774 ++++++++++++++++++++++++++++= ++++ 4 files changed, 792 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 61bf550fd37c..eefd78c72d82 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -15716,6 +15716,12 @@ F: drivers/mfd/max77759.c F: drivers/nvmem/max77759-nvmem.c F: include/linux/mfd/max77759.h =20 +MAXIM MAX77759 BATTERY CHARGER DRIVER +M: Amit Sunil Dhamne +L: linux-kernel@vger.kernel.org +S: Maintained +F: drivers/power/supply/max77759_charger.c + MAXIM MAX77802 PMIC REGULATOR DEVICE DRIVER M: Javier Martinez Canillas L: linux-kernel@vger.kernel.org diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig index 92f9f7aae92f..3a2cdb95c98e 100644 --- a/drivers/power/supply/Kconfig +++ b/drivers/power/supply/Kconfig @@ -631,6 +631,17 @@ config CHARGER_MAX77705 help Say Y to enable support for the Maxim MAX77705 battery charger. =20 +config CHARGER_MAX77759 + tristate "Maxim MAX77759 battery charger driver" + depends on MFD_MAX77759 && REGULATOR + default MFD_MAX77759 + help + Say M or Y here to enable the MAX77759 battery charger. MAX77759 + charger is a function of the MAX77759 PMIC. This is a dual input + switch-mode charger. This driver supports buck and OTG boost modes. + + If built as a module, it will be called max77759_charger. + config CHARGER_MAX77976 tristate "Maxim MAX77976 battery charger driver" depends on I2C diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile index 4b79d5abc49a..6af905875ad5 100644 --- a/drivers/power/supply/Makefile +++ b/drivers/power/supply/Makefile @@ -128,3 +128,4 @@ obj-$(CONFIG_CHARGER_SURFACE) +=3D surface_charger.o obj-$(CONFIG_BATTERY_UG3105) +=3D ug3105_battery.o obj-$(CONFIG_CHARGER_QCOM_SMB2) +=3D qcom_smbx.o obj-$(CONFIG_FUEL_GAUGE_MM8013) +=3D mm8013.o +obj-$(CONFIG_CHARGER_MAX77759) +=3D max77759_charger.o diff --git a/drivers/power/supply/max77759_charger.c b/drivers/power/supply= /max77759_charger.c new file mode 100644 index 000000000000..9bb414599f16 --- /dev/null +++ b/drivers/power/supply/max77759_charger.c @@ -0,0 +1,774 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * max77759_charger.c - Battery charger driver for MAX77759 charger device. + * + * Copyright 2025 Google LLC. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Default values for Fast Charge Current & Float Voltage */ +#define CHG_CC_DEFAULT_UA 2266770 +#define CHG_FV_DEFAULT_MV 4300 + +#define MAX_NUM_RETRIES 3 +#define PSY_WORK_RETRY_DELAY_MS 10 + +#define FOREACH_IRQ(S) \ + S(AICL), \ + S(CHGIN), \ + S(CHG), \ + S(INLIM), \ + S(BAT_OILO), \ + S(CHG_STA_CC), \ + S(CHG_STA_CV), \ + S(CHG_STA_TO), \ + S(CHG_STA_DONE) + +#define GENERATE_ENUM(e) e +#define GENERATE_STRING(s) #s + +enum { + FOREACH_IRQ(GENERATE_ENUM) +}; + +static const char *const chgr_irqs_str[] =3D { + FOREACH_IRQ(GENERATE_STRING) +}; + +#define NUM_IRQS ARRAY_SIZE(chgr_irqs_str) + +/* Fast charge current limits (in uA) */ +static const struct linear_range chgcc_limit_ranges[] =3D { + LINEAR_RANGE(133330, 0x0, 0x2, 0), + LINEAR_RANGE(200000, 0x3, 0x3C, 66670), +}; + +/* Charge Termination Voltage Limits (in mV) */ +static const struct linear_range chg_cv_prm_ranges[] =3D { + LINEAR_RANGE(3800, 0x38, 0x39, 100), + LINEAR_RANGE(4000, 0x0, 0x32, 10), +}; + +/* USB input current limits (in uA) */ +static const struct linear_range chgin_ilim_ranges[] =3D { + LINEAR_RANGE(100000, 0x3, 0x7F, 25000), +}; + +struct max77759_charger { + struct device *dev; + struct regmap *regmap; + struct power_supply *psy; + struct regulator_dev *chgin_otg_rdev; + struct notifier_block nb; + struct power_supply *tcpm_psy; + struct delayed_work psy_work; + struct mutex retry_lock; /* Protects psy_work_retry_cnt */ + u32 psy_work_retry_cnt; + int irqs[NUM_IRQS]; + struct mutex lock; /* protects the state below */ + enum max77759_chgr_mode mode; +}; + +static inline int unlock_prot_regs(struct max77759_charger *chg, bool unlo= ck) +{ + return regmap_update_bits(chg->regmap, MAX77759_CHGR_REG_CHG_CNFG_06, + MAX77759_CHGR_REG_CHG_CNFG_06_CHGPROT, unlock + ? MAX77759_CHGR_REG_CHG_CNFG_06_CHGPROT : 0); +} + +static int charger_input_valid(struct max77759_charger *chg) +{ + u32 val; + int ret; + + ret =3D regmap_read(chg->regmap, MAX77759_CHGR_REG_CHG_INT_OK, &val); + if (ret) + return ret; + + return (val & MAX77759_CHGR_REG_CHG_INT_CHG) && + (val & MAX77759_CHGR_REG_CHG_INT_CHGIN); +} + +static int get_online(struct max77759_charger *chg) +{ + u32 val; + int ret; + + ret =3D charger_input_valid(chg); + if (ret <=3D 0) + return ret; + + ret =3D regmap_read(chg->regmap, MAX77759_CHGR_REG_CHG_DETAILS_02, &val); + if (ret) + return ret; + + guard(mutex)(&chg->lock); + + return (val & MAX77759_CHGR_REG_CHG_DETAILS_02_CHGIN_STS) && + (chg->mode =3D=3D MAX77759_CHGR_MODE_CHG_BUCK_ON); +} + +static int get_status(struct max77759_charger *chg) +{ + u32 val; + int ret; + + ret =3D regmap_read(chg->regmap, MAX77759_CHGR_REG_CHG_DETAILS_01, &val); + if (ret) + return ret; + + switch (FIELD_GET(MAX77759_CHGR_REG_CHG_DETAILS_01_CHG_DTLS, val)) { + case MAX77759_CHGR_CHG_DTLS_PREQUAL: + case MAX77759_CHGR_CHG_DTLS_CC: + case MAX77759_CHGR_CHG_DTLS_CV: + case MAX77759_CHGR_CHG_DTLS_TO: + return POWER_SUPPLY_STATUS_CHARGING; + case MAX77759_CHGR_CHG_DTLS_DONE: + return POWER_SUPPLY_STATUS_FULL; + case MAX77759_CHGR_CHG_DTLS_TIMER_FAULT: + case MAX77759_CHGR_CHG_DTLS_SUSP_BATT_THM: + case MAX77759_CHGR_CHG_DTLS_OFF_WDOG_TIMER: + case MAX77759_CHGR_CHG_DTLS_SUSP_JEITA: + return POWER_SUPPLY_STATUS_NOT_CHARGING; + case MAX77759_CHGR_CHG_DTLS_OFF: + return POWER_SUPPLY_STATUS_DISCHARGING; + default: + break; + } + + return POWER_SUPPLY_STATUS_UNKNOWN; +} + +static int get_charge_type(struct max77759_charger *chg) +{ + u32 val; + int ret; + + ret =3D regmap_read(chg->regmap, MAX77759_CHGR_REG_CHG_DETAILS_01, &val); + if (ret) + return ret; + + switch (FIELD_GET(MAX77759_CHGR_REG_CHG_DETAILS_01_CHG_DTLS, val)) { + case MAX77759_CHGR_CHG_DTLS_PREQUAL: + return POWER_SUPPLY_CHARGE_TYPE_TRICKLE; + case MAX77759_CHGR_CHG_DTLS_CC: + case MAX77759_CHGR_CHG_DTLS_CV: + return POWER_SUPPLY_CHARGE_TYPE_FAST; + case MAX77759_CHGR_CHG_DTLS_TO: + return POWER_SUPPLY_CHARGE_TYPE_STANDARD; + case MAX77759_CHGR_CHG_DTLS_DONE: + case MAX77759_CHGR_CHG_DTLS_TIMER_FAULT: + case MAX77759_CHGR_CHG_DTLS_SUSP_BATT_THM: + case MAX77759_CHGR_CHG_DTLS_OFF_WDOG_TIMER: + case MAX77759_CHGR_CHG_DTLS_SUSP_JEITA: + case MAX77759_CHGR_CHG_DTLS_OFF: + return POWER_SUPPLY_CHARGE_TYPE_NONE; + default: + break; + } + + return POWER_SUPPLY_CHARGE_TYPE_UNKNOWN; +} + +static int get_chg_health(struct max77759_charger *chg) +{ + u32 val; + int ret; + + ret =3D regmap_read(chg->regmap, MAX77759_CHGR_REG_CHG_DETAILS_00, &val); + if (ret) + return ret; + + switch (FIELD_GET(MAX77759_CHGR_REG_CHG_DETAILS_00_CHGIN_DTLS, val)) { + case MAX77759_CHGR_CHGIN_DTLS_VBUS_UNDERVOLTAGE: + case MAX77759_CHGR_CHGIN_DTLS_VBUS_MARGINAL_VOLTAGE: + return POWER_SUPPLY_HEALTH_UNDERVOLTAGE; + case MAX77759_CHGR_CHGIN_DTLS_VBUS_OVERVOLTAGE: + return POWER_SUPPLY_HEALTH_OVERVOLTAGE; + case MAX77759_CHGR_CHGIN_DTLS_VBUS_VALID: + return POWER_SUPPLY_HEALTH_GOOD; + default: + break; + } + + return POWER_SUPPLY_HEALTH_UNKNOWN; +} + +static int get_batt_health(struct max77759_charger *chg) +{ + u32 val; + int ret; + + ret =3D regmap_read(chg->regmap, MAX77759_CHGR_REG_CHG_DETAILS_01, &val); + if (ret) + return ret; + + switch (FIELD_GET(MAX77759_CHGR_REG_CHG_DETAILS_01_BAT_DTLS, val)) { + case MAX77759_CHGR_BAT_DTLS_NO_BATT_CHG_SUSP: + return POWER_SUPPLY_HEALTH_NO_BATTERY; + case MAX77759_CHGR_BAT_DTLS_DEAD_BATTERY: + return POWER_SUPPLY_HEALTH_DEAD; + case MAX77759_CHGR_BAT_DTLS_BAT_CHG_TIMER_FAULT: + return POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE; + case MAX77759_CHGR_BAT_DTLS_BAT_OKAY: + case MAX77759_CHGR_BAT_DTLS_BAT_ONLY_MODE: + return POWER_SUPPLY_HEALTH_GOOD; + case MAX77759_CHGR_BAT_DTLS_BAT_UNDERVOLTAGE: + return POWER_SUPPLY_HEALTH_UNDERVOLTAGE; + case MAX77759_CHGR_BAT_DTLS_BAT_OVERVOLTAGE: + return POWER_SUPPLY_HEALTH_OVERVOLTAGE; + case MAX77759_CHGR_BAT_DTLS_BAT_OVERCURRENT: + return POWER_SUPPLY_HEALTH_OVERCURRENT; + default: + break; + } + + return POWER_SUPPLY_HEALTH_UNKNOWN; +} + +static int get_health(struct max77759_charger *chg) +{ + int ret; + + ret =3D get_online(chg); + if (ret < 0) + return ret; + + if (ret) { + ret =3D get_chg_health(chg); + if (ret < 0 || ret !=3D POWER_SUPPLY_HEALTH_GOOD) + return ret; + } + + return get_batt_health(chg); +} + +static int get_fast_charge_current(struct max77759_charger *chg) +{ + u32 regval, val; + int ret; + + ret =3D regmap_read(chg->regmap, MAX77759_CHGR_REG_CHG_CNFG_02, ®val); + if (ret) + return ret; + + regval =3D FIELD_GET(MAX77759_CHGR_REG_CHG_CNFG_02_CHGCC, regval); + ret =3D linear_range_get_value_array(chgcc_limit_ranges, + ARRAY_SIZE(chgcc_limit_ranges), + regval, &val); + return ret ? ret : val; +} + +static int set_fast_charge_current_limit(struct max77759_charger *chg, + u32 cc_max_ua) +{ + bool found; + u32 regval; + + linear_range_get_selector_high_array(chgcc_limit_ranges, + ARRAY_SIZE(chgcc_limit_ranges), + cc_max_ua, ®val, &found); + if (!found) + return -EINVAL; + + return regmap_update_bits(chg->regmap, MAX77759_CHGR_REG_CHG_CNFG_02, + MAX77759_CHGR_REG_CHG_CNFG_02_CHGCC, regval); +} + +static int get_float_voltage(struct max77759_charger *chg) +{ + u32 regval, val; + int ret; + + ret =3D regmap_read(chg->regmap, MAX77759_CHGR_REG_CHG_CNFG_04, ®val); + if (ret) + return ret; + + regval =3D FIELD_GET(MAX77759_CHGR_REG_CHG_CNFG_04_CHG_CV_PRM, regval); + ret =3D linear_range_get_value_array(chg_cv_prm_ranges, + ARRAY_SIZE(chg_cv_prm_ranges), + regval, &val); + + return ret ? ret : val; +} + +static int set_float_voltage_limit(struct max77759_charger *chg, u32 fv_mv) +{ + u32 regval; + bool found; + + linear_range_get_selector_high_array(chg_cv_prm_ranges, + ARRAY_SIZE(chg_cv_prm_ranges), + fv_mv, ®val, &found); + if (!found) + return -EINVAL; + + return regmap_update_bits(chg->regmap, MAX77759_CHGR_REG_CHG_CNFG_04, + MAX77759_CHGR_REG_CHG_CNFG_04_CHG_CV_PRM, + regval); +} + +static int get_input_current_limit(struct max77759_charger *chg) +{ + u32 regval, val; + int ret; + + ret =3D regmap_read(chg->regmap, MAX77759_CHGR_REG_CHG_CNFG_09, ®val); + if (ret) + return ret; + + regval =3D FIELD_GET(MAX77759_CHGR_REG_CHG_CNFG_09_CHGIN_ILIM, regval); + regval =3D umax(regval, chgin_ilim_ranges[0].min_sel); + + ret =3D linear_range_get_value_array(chgin_ilim_ranges, + ARRAY_SIZE(chgin_ilim_ranges), + regval, &val); + + return ret ? ret : val; +} + +static int set_input_current_limit(struct max77759_charger *chg, int ilim_= ua) +{ + u32 regval; + + if (ilim_ua < 0) + return -EINVAL; + + linear_range_get_selector_within(chgin_ilim_ranges, ilim_ua, ®val); + + return regmap_update_bits(chg->regmap, MAX77759_CHGR_REG_CHG_CNFG_09, + MAX77759_CHGR_REG_CHG_CNFG_09_CHGIN_ILIM, + regval); +} + +static const enum power_supply_property max77759_charger_props[] =3D { + POWER_SUPPLY_PROP_ONLINE, + POWER_SUPPLY_PROP_PRESENT, + POWER_SUPPLY_PROP_STATUS, + POWER_SUPPLY_PROP_CHARGE_TYPE, + POWER_SUPPLY_PROP_HEALTH, + POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, + POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX, + POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, +}; + +static int max77759_charger_get_property(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *pval) +{ + struct max77759_charger *chg =3D power_supply_get_drvdata(psy); + int ret; + + switch (psp) { + case POWER_SUPPLY_PROP_ONLINE: + ret =3D get_online(chg); + break; + case POWER_SUPPLY_PROP_PRESENT: + ret =3D charger_input_valid(chg); + break; + case POWER_SUPPLY_PROP_STATUS: + ret =3D get_status(chg); + break; + case POWER_SUPPLY_PROP_CHARGE_TYPE: + ret =3D get_charge_type(chg); + break; + case POWER_SUPPLY_PROP_HEALTH: + ret =3D get_health(chg); + break; + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: + ret =3D get_fast_charge_current(chg); + break; + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX: + ret =3D get_float_voltage(chg); + break; + case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: + ret =3D get_input_current_limit(chg); + break; + default: + ret =3D -EINVAL; + } + + pval->intval =3D ret; + return ret < 0 ? ret : 0; +} + +static const struct power_supply_desc max77759_charger_desc =3D { + .name =3D "max77759-charger", + .type =3D POWER_SUPPLY_TYPE_USB, + .properties =3D max77759_charger_props, + .num_properties =3D ARRAY_SIZE(max77759_charger_props), + .get_property =3D max77759_charger_get_property, +}; + +static int charger_set_mode(struct max77759_charger *chg, + enum max77759_chgr_mode mode) +{ + int ret; + + guard(mutex)(&chg->lock); + + if (chg->mode =3D=3D mode) + return 0; + + if ((mode =3D=3D MAX77759_CHGR_MODE_CHG_BUCK_ON || + mode =3D=3D MAX77759_CHGR_MODE_OTG_BOOST_ON) && + chg->mode !=3D MAX77759_CHGR_MODE_OFF) { + dev_err(chg->dev, "Invalid mode transition from %d to %d\n", + chg->mode, mode); + return -EINVAL; + } + + ret =3D regmap_update_bits(chg->regmap, MAX77759_CHGR_REG_CHG_CNFG_00, + MAX77759_CHGR_REG_CHG_CNFG_00_MODE, mode); + if (ret) + return ret; + + chg->mode =3D mode; + return 0; +} + +static int enable_chgin_otg(struct regulator_dev *rdev) +{ + struct max77759_charger *chg =3D rdev_get_drvdata(rdev); + + return charger_set_mode(chg, MAX77759_CHGR_MODE_OTG_BOOST_ON); +} + +static int disable_chgin_otg(struct regulator_dev *rdev) +{ + struct max77759_charger *chg =3D rdev_get_drvdata(rdev); + + return charger_set_mode(chg, MAX77759_CHGR_MODE_OFF); +} + +static int chgin_otg_status(struct regulator_dev *rdev) +{ + struct max77759_charger *chg =3D rdev_get_drvdata(rdev); + + guard(mutex)(&chg->lock); + + return chg->mode =3D=3D MAX77759_CHGR_MODE_OTG_BOOST_ON; +} + +static const struct regulator_ops chgin_otg_reg_ops =3D { + .enable =3D enable_chgin_otg, + .disable =3D disable_chgin_otg, + .is_enabled =3D chgin_otg_status, +}; + +static const struct regulator_desc chgin_otg_reg_desc =3D { + .name =3D "chgin-otg", + .of_match =3D of_match_ptr("chgin-otg-regulator"), + .owner =3D THIS_MODULE, + .ops =3D &chgin_otg_reg_ops, + .fixed_uV =3D 5000000, + .n_voltages =3D 1, +}; + +static irqreturn_t irq_handler(int irq, void *data) +{ + struct max77759_charger *chg =3D data; + + power_supply_changed(chg->psy); + + return IRQ_HANDLED; +} + +static irqreturn_t bat_oilo_irq_handler(int irq, void *data) +{ + struct max77759_charger *chg =3D data; + + dev_warn_ratelimited(chg->dev, + "Battery over-current threshold crossed\n"); + + return irq_handler(irq, data); +} + +static int max77759_init_irqhandler(struct max77759_charger *chg) +{ + struct device *dev =3D chg->dev; + irq_handler_t thread_fn; + char *name; + int i, ret; + + for (i =3D 0; i < ARRAY_SIZE(chgr_irqs_str); i++) { + ret =3D platform_get_irq_byname(to_platform_device(dev), + chgr_irqs_str[i]); + if (ret < 0) + return dev_err_probe(dev, ret, + "Failed to get irq resource for %s\n", + chgr_irqs_str[i]); + + chg->irqs[i] =3D ret; + name =3D devm_kasprintf(dev, GFP_KERNEL, "%s:%s", dev_name(dev), + chgr_irqs_str[i]); + if (!name) + return dev_err_probe(dev, -ENOMEM, + "Failed to allocate space for irqname: %s\n", + chgr_irqs_str[i]); + + if (i =3D=3D BAT_OILO) + thread_fn =3D bat_oilo_irq_handler; + else + thread_fn =3D irq_handler; + + ret =3D devm_request_threaded_irq(dev, chg->irqs[i], NULL, + thread_fn, 0, name, chg); + if (ret) + return dev_err_probe(dev, ret, + "Unable to register irq handler for %s\n", + chgr_irqs_str[i]); + } + + return 0; +} + +static int max77759_charger_init(struct max77759_charger *chg) +{ + struct power_supply_battery_info *info; + u32 regval, fast_chg_curr, fv; + int ret; + + ret =3D regmap_read(chg->regmap, MAX77759_CHGR_REG_CHG_CNFG_00, ®val); + if (ret) + return ret; + + chg->mode =3D FIELD_GET(MAX77759_CHGR_REG_CHG_CNFG_00_MODE, regval); + ret =3D charger_set_mode(chg, MAX77759_CHGR_MODE_OFF); + if (ret) + return ret; + + if (power_supply_get_battery_info(chg->psy, &info)) { + fv =3D CHG_FV_DEFAULT_MV; + fast_chg_curr =3D CHG_CC_DEFAULT_UA; + } else { + fv =3D info->constant_charge_voltage_max_uv / 1000; + fast_chg_curr =3D info->constant_charge_current_max_ua; + } + + ret =3D set_fast_charge_current_limit(chg, fast_chg_curr); + if (ret) + return ret; + + ret =3D set_float_voltage_limit(chg, fv); + if (ret) + return ret; + + ret =3D unlock_prot_regs(chg, true); + if (ret) + return ret; + + /* Disable wireless charging input */ + ret =3D regmap_update_bits(chg->regmap, MAX77759_CHGR_REG_CHG_CNFG_12, + MAX77759_CHGR_REG_CHG_CNFG_12_WCINSEL, 0); + if (ret) + goto relock; + + ret =3D regmap_update_bits(chg->regmap, MAX77759_CHGR_REG_CHG_CNFG_18, + MAX77759_CHGR_REG_CHG_CNFG_18_WDTEN, 0); + if (ret) + goto relock; + + return unlock_prot_regs(chg, false); + +relock: + (void)unlock_prot_regs(chg, false); + return ret; +} + +static void psy_work_item(struct work_struct *work) +{ + struct max77759_charger *chg =3D + container_of(work, struct max77759_charger, psy_work.work); + union power_supply_propval current_limit, online; + int ret; + + ret =3D power_supply_get_property(chg->tcpm_psy, + POWER_SUPPLY_PROP_CURRENT_MAX, + ¤t_limit); + if (ret) { + dev_err(chg->dev, + "Failed to get CURRENT_MAX psy property, ret=3D%d\n", + ret); + goto err; + } + + ret =3D power_supply_get_property(chg->tcpm_psy, POWER_SUPPLY_PROP_ONLINE, + &online); + if (ret) { + dev_err(chg->dev, + "Failed to get ONLINE psy property, ret=3D%d\n", + ret); + goto err; + } + + if (online.intval && current_limit.intval) { + ret =3D set_input_current_limit(chg, current_limit.intval); + if (ret) { + dev_err(chg->dev, + "Unable to set current limit, ret=3D%d\n", ret); + goto err; + } + + charger_set_mode(chg, MAX77759_CHGR_MODE_CHG_BUCK_ON); + } else { + charger_set_mode(chg, MAX77759_CHGR_MODE_OFF); + } + + scoped_guard(mutex, &chg->retry_lock) { + if (chg->psy_work_retry_cnt) + dev_dbg(chg->dev, + "chg psy_work succeeded after %u tries\n", + chg->psy_work_retry_cnt); + chg->psy_work_retry_cnt =3D 0; + } + + return; + +err: + charger_set_mode(chg, MAX77759_CHGR_MODE_OFF); + scoped_guard(mutex, &chg->retry_lock) { + if (chg->psy_work_retry_cnt >=3D MAX_NUM_RETRIES) { + dev_err(chg->dev, "chg psy work failed, giving up\n"); + return; + } + + ++chg->psy_work_retry_cnt; + dev_dbg(chg->dev, "Retrying %u/%u chg psy_work\n", + chg->psy_work_retry_cnt, MAX_NUM_RETRIES); + schedule_delayed_work(&chg->psy_work, + msecs_to_jiffies(PSY_WORK_RETRY_DELAY_MS)); + } +} + +static int psy_changed(struct notifier_block *nb, unsigned long evt, void = *data) +{ + struct max77759_charger *chg =3D container_of(nb, struct max77759_charger, + nb); + static const char *psy_name =3D "tcpm-source"; + struct power_supply *psy =3D data; + + if (!strnstr(psy->desc->name, psy_name, strlen(psy_name)) || + evt !=3D PSY_EVENT_PROP_CHANGED) + return NOTIFY_OK; + + chg->tcpm_psy =3D psy; + scoped_guard(mutex, &chg->retry_lock) + chg->psy_work_retry_cnt =3D 0; + + schedule_delayed_work(&chg->psy_work, 0); + + return NOTIFY_OK; +} + +static void max_tcpci_unregister_psy_notifier(void *nb) +{ + power_supply_unreg_notifier(nb); +} + +static int max77759_charger_probe(struct platform_device *pdev) +{ + struct regulator_config chgin_otg_reg_cfg; + struct power_supply_config psy_cfg; + struct device *dev =3D &pdev->dev; + struct max77759_charger *chg; + int ret; + + device_set_of_node_from_dev(dev, dev->parent); + chg =3D devm_kzalloc(dev, sizeof(*chg), GFP_KERNEL); + if (!chg) + return -ENOMEM; + + platform_set_drvdata(pdev, chg); + chg->dev =3D dev; + chg->regmap =3D dev_get_regmap(dev->parent, "charger"); + if (!chg->regmap) + return dev_err_probe(dev, -ENODEV, "Missing regmap\n"); + + ret =3D devm_mutex_init(dev, &chg->lock); + if (ret) + return dev_err_probe(dev, ret, "Failed to initialize lock\n"); + + ret =3D devm_mutex_init(dev, &chg->retry_lock); + if (ret) + return dev_err_probe(dev, ret, + "Failed to initialize retry_lock\n"); + + psy_cfg.fwnode =3D dev_fwnode(dev); + psy_cfg.drv_data =3D chg; + chg->psy =3D devm_power_supply_register(dev, &max77759_charger_desc, + &psy_cfg); + if (IS_ERR(chg->psy)) + return dev_err_probe(dev, PTR_ERR(chg->psy), + "Failed to register psy\n"); + + ret =3D max77759_charger_init(chg); + if (ret) + return dev_err_probe(dev, ret, + "Failed to initialize max77759 charger\n"); + + chgin_otg_reg_cfg.dev =3D dev; + chgin_otg_reg_cfg.driver_data =3D chg; + chgin_otg_reg_cfg.of_node =3D dev_of_node(dev); + chg->chgin_otg_rdev =3D devm_regulator_register(dev, &chgin_otg_reg_desc, + &chgin_otg_reg_cfg); + if (IS_ERR(chg->chgin_otg_rdev)) + return dev_err_probe(dev, PTR_ERR(chg->chgin_otg_rdev), + "Failed to register chgin otg regulator\n"); + + ret =3D devm_delayed_work_autocancel(dev, &chg->psy_work, psy_work_item); + if (ret) + return dev_err_probe(dev, ret, "Failed to initialize psy work\n"); + + chg->nb.notifier_call =3D psy_changed; + ret =3D power_supply_reg_notifier(&chg->nb); + if (ret) + return dev_err_probe(dev, ret, + "Unable to register psy notifier\n"); + + ret =3D devm_add_action_or_reset(dev, max_tcpci_unregister_psy_notifier, + &chg->nb); + if (ret) + return dev_err_probe(dev, ret, + "Failed to add devm action to unregister psy notifier\n"); + + return max77759_init_irqhandler(chg); +} + +static const struct platform_device_id max77759_charger_id[] =3D { + { .name =3D "max77759-charger", }, + { } +}; +MODULE_DEVICE_TABLE(platform, max77759_charger_id); + +static struct platform_driver max77759_charger_driver =3D { + .driver =3D { + .name =3D "max77759-charger", + .probe_type =3D PROBE_PREFER_ASYNCHRONOUS, + }, + .probe =3D max77759_charger_probe, + .id_table =3D max77759_charger_id, +}; +module_platform_driver(max77759_charger_driver); + +MODULE_AUTHOR("Amit Sunil Dhamne "); +MODULE_DESCRIPTION("Maxim MAX77759 charger driver"); +MODULE_LICENSE("GPL"); --=20 2.53.0.1018.g2bb0e51243-goog From nobody Thu Apr 2 23:57:12 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 F3F2A3783B2; Wed, 25 Mar 2026 22:22:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774477356; cv=none; b=nNlyofnYZaDu7osZxN4kkUCU93FERmcvMb1n63jOP9m5gQgKX8/K8DKFp6Yj9CUVKIS2mc1sPOdsjk2pVf3jZpf7K6X2eSRAJmY6xfNQ89ke3+FO01YzCGnnIV0InFRDRYhe99H62wtpl7dy6Ckivocb4Iszw2gwHca6UmO+IAc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774477356; c=relaxed/simple; bh=Ko5eJ00+iD2PkDlRZb5TmiRuUZmptMbNVLOisdGaDYg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=kNoneP0ECIkeSuL/OwPug2Gkojhceha2GCF1gyGh/nZDlnREe+6KR6DjSRbGhaQ1MqiLdU/IERgOclCVYSMx8AWJYttanTqaVjhhGraIam30oR4y6NGdVwLtCSo6lHZY2pMwzYBYGKriWNNIeAV1e0rwBhXtJqQ54XrOjSQztEo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=QHwqgfv/; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="QHwqgfv/" Received: by smtp.kernel.org (Postfix) with ESMTPS id C429BC2BCB0; Wed, 25 Mar 2026 22:22:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774477355; bh=Ko5eJ00+iD2PkDlRZb5TmiRuUZmptMbNVLOisdGaDYg=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=QHwqgfv/Bf/pgAcUvzt+2XvDOn75vl+tJzhvdr2A8yJODeYFg2OAWynuNr5uddf68 jrjNLoexwKb1Zzu+8/hf34TJZLKOuSHJ+FE7dK1N1RMxfWPLQroDHOzBbqgy01So0G 192cKChyhP0T6NAyJqSLFXcOpYQJUfX5dvwypXEJS+Z1rsQ1vHutF3zzKLkHcxBtjy ifj3mEgHJV9ro9QGX5fc/jY/eRpUgFD9eaxQRAZLp3xUfKskhSxdziqV3CqQCFHGbt AcDmPuUmu9o0seBr1kz5jvvgTA5xTR/gXjAWbtwskgX8frpluSmkoupBkdfvKNYd24 MQHdSn+OdIDkw== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id BAA0C109E527; Wed, 25 Mar 2026 22:22:35 +0000 (UTC) From: Amit Sunil Dhamne via B4 Relay Date: Wed, 25 Mar 2026 22:22:27 +0000 Subject: [PATCH v9 6/6] usb: typec: tcpm/tcpci_maxim: deprecate WAR for setting charger mode 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: <20260325-max77759-charger-v9-6-4486dd297adc@google.com> References: <20260325-max77759-charger-v9-0-4486dd297adc@google.com> In-Reply-To: <20260325-max77759-charger-v9-0-4486dd297adc@google.com> To: Sebastian Reichel , Rob Herring , Krzysztof Kozlowski , Conor Dooley , =?utf-8?q?Andr=C3=A9_Draszik?= , Lee Jones , Greg Kroah-Hartman , Badhri Jagan Sridharan , Heikki Krogerus , Peter Griffin , Tudor Ambarus , Alim Akhtar , Mark Brown , Matti Vaittinen , Andrew Morton Cc: linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, devicetree@vger.kernel.org, linux-usb@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-samsung-soc@vger.kernel.org, RD Babiera , Kyle Tso , Amit Sunil Dhamne X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=ed25519-sha256; t=1774477354; l=3934; i=amitsd@google.com; s=20241031; h=from:subject:message-id; bh=bruH2PMOUkO97UYu2THTFVcDzHT49eOgRVKEaZdvmY4=; b=UnZJCmEPXSOTZU8eIu3pKBaNNSm5b6cf2wd4OSDRS+1pTSFSHnDBncyhynszpzLtMvhpzQk3x J/bDqEhAQE6CQFg6v9Z+rB2tJywptY3TNS6k2xoTCp5XjV5idjdW+Li X-Developer-Key: i=amitsd@google.com; a=ed25519; pk=wD+XZSST4dmnNZf62/lqJpLm7fiyT8iv462zmQ3H6bI= X-Endpoint-Received: by B4 Relay for amitsd@google.com/20241031 with auth_id=262 X-Original-From: Amit Sunil Dhamne Reply-To: amitsd@google.com From: Amit Sunil Dhamne TCPCI maxim driver directly writes to the charger's register space to set charger mode depending on the power role. As MAX77759 chg driver exists, this WAR is not required. Instead, use a regulator interface to source vbus when typec is in source power mode. In other power modes, this regulator will be turned off if active. Signed-off-by: Amit Sunil Dhamne Reviewed-by: Heikki Krogerus Reviewed-by: Andr=C3=A9 Draszik --- drivers/usb/typec/tcpm/tcpci_maxim.h | 1 + drivers/usb/typec/tcpm/tcpci_maxim_core.c | 54 +++++++++++++++++++--------= ---- 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/drivers/usb/typec/tcpm/tcpci_maxim.h b/drivers/usb/typec/tcpm/= tcpci_maxim.h index b33540a42a95..b314606eb0f6 100644 --- a/drivers/usb/typec/tcpm/tcpci_maxim.h +++ b/drivers/usb/typec/tcpm/tcpci_maxim.h @@ -60,6 +60,7 @@ struct max_tcpci_chip { struct tcpm_port *port; enum contamiant_state contaminant_state; bool veto_vconn_swap; + struct regulator *vbus_reg; }; =20 static inline int max_tcpci_read16(struct max_tcpci_chip *chip, unsigned i= nt reg, u16 *val) diff --git a/drivers/usb/typec/tcpm/tcpci_maxim_core.c b/drivers/usb/typec/= tcpm/tcpci_maxim_core.c index 19f638650796..c0ee7e6959ed 100644 --- a/drivers/usb/typec/tcpm/tcpci_maxim_core.c +++ b/drivers/usb/typec/tcpm/tcpci_maxim_core.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -35,12 +36,6 @@ */ #define TCPC_RECEIVE_BUFFER_LEN 32 =20 -#define MAX_BUCK_BOOST_SID 0x69 -#define MAX_BUCK_BOOST_OP 0xb9 -#define MAX_BUCK_BOOST_OFF 0 -#define MAX_BUCK_BOOST_SOURCE 0xa -#define MAX_BUCK_BOOST_SINK 0x5 - static const struct regmap_range max_tcpci_tcpci_range[] =3D { regmap_reg_range(0x00, 0x95) }; @@ -202,32 +197,49 @@ static void process_rx(struct max_tcpci_chip *chip, u= 16 status) tcpm_pd_receive(chip->port, &msg, rx_type); } =20 +static int get_vbus_regulator_handle(struct max_tcpci_chip *chip) +{ + if (IS_ERR_OR_NULL(chip->vbus_reg)) { + chip->vbus_reg =3D devm_regulator_get_exclusive(chip->dev, + "vbus"); + if (IS_ERR_OR_NULL(chip->vbus_reg)) { + dev_err(chip->dev, + "Failed to get vbus regulator handle\n"); + return -ENODEV; + } + } + + return 0; +} + static int max_tcpci_set_vbus(struct tcpci *tcpci, struct tcpci_data *tdat= a, bool source, bool sink) { struct max_tcpci_chip *chip =3D tdata_to_max_tcpci(tdata); - u8 buffer_source[2] =3D {MAX_BUCK_BOOST_OP, MAX_BUCK_BOOST_SOURCE}; - u8 buffer_sink[2] =3D {MAX_BUCK_BOOST_OP, MAX_BUCK_BOOST_SINK}; - u8 buffer_none[2] =3D {MAX_BUCK_BOOST_OP, MAX_BUCK_BOOST_OFF}; - struct i2c_client *i2c =3D chip->client; int ret; =20 - struct i2c_msg msgs[] =3D { - { - .addr =3D MAX_BUCK_BOOST_SID, - .flags =3D i2c->flags & I2C_M_TEN, - .len =3D 2, - .buf =3D source ? buffer_source : sink ? buffer_sink : buffer_none, - }, - }; - if (source && sink) { dev_err(chip->dev, "Both source and sink set\n"); return -EINVAL; } =20 - ret =3D i2c_transfer(i2c->adapter, msgs, 1); + ret =3D get_vbus_regulator_handle(chip); + if (ret) { + /* + * Regulator is not necessary for sink only applications. Return + * success in cases where sink mode is being modified. + */ + return source ? ret : 1; + } + + if (source) { + if (!regulator_is_enabled(chip->vbus_reg)) + ret =3D regulator_enable(chip->vbus_reg); + } else { + if (regulator_is_enabled(chip->vbus_reg)) + ret =3D regulator_disable(chip->vbus_reg); + } =20 - return ret < 0 ? ret : 1; + return ret < 0 ? ret : 1; } =20 static void process_power_status(struct max_tcpci_chip *chip) --=20 2.53.0.1018.g2bb0e51243-goog