From nobody Tue Dec 2 01:05:42 2025 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 C207827FD74; Sun, 23 Nov 2025 08:36:24 +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=1763886984; cv=none; b=dK75xy4ctKjAAaWoxr3/uM68VyqGQX2u731Yjd/TishXAvAqbLXvdu+5sFkswTigoQ+mhzvR+SvpOsgDPa9wh+oaoGDhL6aWRiVTFNL7qOX0VDOKMdwM4zlTwfOb/1px1Qh9pH3tgf5FZy+M9SuVX26jbNfRmysD2jLYZ1OwUe4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763886984; c=relaxed/simple; bh=xwynRUzExlilQidqzDcuAEaxh+WE2LV+Vnfe/saj5Lc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=O7O26OEq+o6iyCiglaRdbwoM0QtyN/QWruyfG7Bv4NRTTYw4itFbBTVnIdr9nrZiLZsQGPrSYXJISB5cTHyoOpeQCIO84eWXZbsDPEJI0YD2y5gxCoGwHvkAa2du6O0fq1KEOCmUGU8l1WeH6uOVtBz61V78TVQz/R6r/yQcWCc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=k4iKB3oN; 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="k4iKB3oN" Received: by smtp.kernel.org (Postfix) with ESMTPS id 60A5CC16AAE; Sun, 23 Nov 2025 08:36:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1763886984; bh=xwynRUzExlilQidqzDcuAEaxh+WE2LV+Vnfe/saj5Lc=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=k4iKB3oN5fOEL369rVx86C3CoZmNft0LMRQRM7SrCy8TKUl9y13i/I/BZZXaXPDk5 ijAYq3x4admrQ5+oJCs+7BDo3hsE0Yomq3e2TiByycVOJWtGISTMobWgypI2+EFQzA R3ZfXMrCkMhMVjP0Tv0hJP/8BkFiE8CT+UJsH6HKPPmAiExKGe49dRe8Y4pJu9Y5iW lr3+j3RYo7iT7H0jjSfmMs6UnvDeUKAqs3/C559CDOqcPIMaMFEOktqo1X37Cz+iqV GhRaCmBv9tbZwRfayjk3gwntC8y7hZq5X0tZ6qjBv/VrjAwZt/o81NzAwKCFv8/53t GVB77+X7+8feA== 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 4D82CCFD313; Sun, 23 Nov 2025 08:36:24 +0000 (UTC) From: Amit Sunil Dhamne via B4 Relay Date: Sun, 23 Nov 2025 08:35:48 +0000 Subject: [PATCH 1/6] dt-bindings: power: supply: Add Maxim MAX77759 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: <20251123-max77759-charger-v1-1-6b2e4b8f7f54@google.com> References: <20251123-max77759-charger-v1-0-6b2e4b8f7f54@google.com> In-Reply-To: <20251123-max77759-charger-v1-0-6b2e4b8f7f54@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 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=1763886983; l=1642; i=amitsd@google.com; s=20241031; h=from:subject:message-id; bh=7bFNW9hXhJq5LkheOx7QT7tuIMKAsDDQ1dSnkeZc7ig=; b=1aO4U9DUYtJHenszVku1+O2T8S0nKCzm7caOTnUbbR7qLLHyk8/pXvsmaDh9xS/wwoHBFtI1i 5FyzzbHT56JAG1hlMR9W/gfQN/Zrra9GnRBfHBL0jK6C45CtkvlFvmg 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 bindings for Maxim max77759 charger device. Signed-off-by: Amit Sunil Dhamne --- .../power/supply/maxim,max77759-charger.yaml | 36 ++++++++++++++++++= ++++ 1 file changed, 36 insertions(+) diff --git a/Documentation/devicetree/bindings/power/supply/maxim,max77759-= charger.yaml b/Documentation/devicetree/bindings/power/supply/maxim,max7775= 9-charger.yaml new file mode 100644 index 000000000000..71f866419774 --- /dev/null +++ b/Documentation/devicetree/bindings/power/supply/maxim,max77759-charger= .yaml @@ -0,0 +1,36 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/power/supply/maxim,max77759-charger.yam= l# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Maxim Integrated MAX77759 Battery charger + +maintainers: + - Amit Sunil Dhamne + +description: | + This module is part of the MAX77759 PMIC. For additional information, see + Documentation/devicetree/bindings/mfd/maxim,max77759.yaml. + + The Maxim MAX77759 is a dual input switch mode battery charger for porta= ble + applications. It supports wired and wireless charging and can operate in= buck + and boost mode. + +allOf: + - $ref: power-supply.yaml# + +properties: + compatible: + const: maxim,max77759-charger + + usb-otg-vbus-regulator: + type: object + description: Provides Boost for sourcing VBUS. + $ref: /schemas/regulator/regulator.yaml# + unevaluatedProperties: false + +required: + - compatible + +unevaluatedProperties: false --=20 2.52.0.rc2.455.g230fcf2819-goog From nobody Tue Dec 2 01:05:42 2025 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 C1FB1273D66; Sun, 23 Nov 2025 08:36:24 +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=1763886984; cv=none; b=V9MITAQM/aPLArrcj7BRasPvvXUiDdZ2tQRZIdCafGabXIY+hEFQ5A9QvulX3rWhMKQS2ZV3ZYihVm6+ub69Cw5OkZrAFjJRqvFmiN6I5wVkScJrquzdHYL23Utquop9JyMh5zWgLQCka3biafBu5OQgP2pQpngz8s54M39mMzA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763886984; c=relaxed/simple; bh=r5AXU9CyKQzJCp1wGf8E69DJrr7/2kmGZppRmQDXWQc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=KdTdKA7RvhhTKpHlEHohQBliZjHR4XxpViwuAjz59puyaYxfBOR/8zxXf4LcnJ4X/EWXCBpIo9OaoEByn5EGhLtIGktV3EmFqpOjXk/8ulfjf7syC2sx6JN1Vfj2boVehMpc8Ny1G0UjpyMXQp4isQ2dmODBs5U1J/eHHJG8vxw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=hK8wbjiu; 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="hK8wbjiu" Received: by smtp.kernel.org (Postfix) with ESMTPS id 708B0C19423; Sun, 23 Nov 2025 08:36:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1763886984; bh=r5AXU9CyKQzJCp1wGf8E69DJrr7/2kmGZppRmQDXWQc=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=hK8wbjiucVE5Lyw7Nw47ddXi0ltGzV2NlA1rr54UKhwSlVHvjQsd2FIOGFxAGOY3Y Yjw2xOLyoo6lJUcXdbsD3++A6PRUJuxAzXHAtFktr3FN+UiCsGiG6o2VVgEuP4imX9 WAod9g3mNKML9t5ZgYvIQ0b8rjB4dBzYcSDtO003RzV0VaupNChph0fDJZjdZt7+nj G/wLc1RUC9QfPdv2yqLMHHVNhf+m+LlDxZV1LYddwPdheZYRWnn4Q9mYtzQMyCu7WH OEcgzVm9YVRKjWgN/rzFvreeHSzCADtn7WCZldc7Z3m38u15u+GF46pJCYo5vLlgdg XfCxiYviKRyug== 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 5F91BCFC518; Sun, 23 Nov 2025 08:36:24 +0000 (UTC) From: Amit Sunil Dhamne via B4 Relay Date: Sun, 23 Nov 2025 08:35:49 +0000 Subject: [PATCH 2/6] dt-bindings: mfd: maxim,max77759: add charger child node 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: <20251123-max77759-charger-v1-2-6b2e4b8f7f54@google.com> References: <20251123-max77759-charger-v1-0-6b2e4b8f7f54@google.com> In-Reply-To: <20251123-max77759-charger-v1-0-6b2e4b8f7f54@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 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=1763886983; l=1264; i=amitsd@google.com; s=20241031; h=from:subject:message-id; bh=qOK5jNVcnx5bjegC1dKWr0w0HMDBjskPRuyCz3Ci8qg=; b=qM5W227Kwrbrd0isfNpZBNhXmIQ8NbswaD5IYEMdymoheJrpiELbZYNT2HWxJ2SRpSo+eXcXG MwinsnfaCqxCyl++OgYXy2PKQWkgwjfJjmK1q419ZJ3qDZP8wc8PQ0m 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 The Maxim MAX77759 MFD includes a charger function, hence add its binding as a property. Also, update the example to include charger. Signed-off-by: Amit Sunil Dhamne --- Documentation/devicetree/bindings/mfd/maxim,max77759.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Documentation/devicetree/bindings/mfd/maxim,max77759.yaml b/Do= cumentation/devicetree/bindings/mfd/maxim,max77759.yaml index 525de9ab3c2b..29132f73f2c8 100644 --- a/Documentation/devicetree/bindings/mfd/maxim,max77759.yaml +++ b/Documentation/devicetree/bindings/mfd/maxim,max77759.yaml @@ -37,6 +37,9 @@ properties: nvmem-0: $ref: /schemas/nvmem/maxim,max77759-nvmem.yaml =20 + charger: + $ref: /schemas/power/supply/maxim,max77759-charger.yaml + required: - compatible - interrupts @@ -95,5 +98,14 @@ examples: }; }; }; + + charger { + compatible =3D "maxim,max77759-charger"; + power-supplies =3D <&maxtcpc>; + + usb-otg-vbus-regulator { + regulator-name =3D "usb-otg-vbus"; + }; + }; }; }; --=20 2.52.0.rc2.455.g230fcf2819-goog From nobody Tue Dec 2 01:05:42 2025 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 DB9F8285071; Sun, 23 Nov 2025 08:36:24 +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=1763886985; cv=none; b=TGVjdxsRDFK1XaTBPxJsDq/grnGDIQ6wn+cfHXWgt1MDmO/W+h8HfZQzU7ggF5M4Nv65b4GaOJ7FHR3gJlNQaOMh4MV2N2A+UStrWbwU5NpIdUv+TkyfVoROfOSnjiOKm7MqlyBIYmX8PN3HKm/YDBE3eiePG5/oKXqfBqKkF0c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763886985; c=relaxed/simple; bh=4VcxCMgYhmMmtFoirHuT2VY7mXYknw3cZfIwfQ93BDg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=A40sPX1QsLbUo5PXJEIB3fp5MPZApg6IS5wBzq+VwJTCCZLeVJELuQd94JwCdeKKTSsoTH7kj8toXyyjpcIfjguQMoj0AoshechqNliBPkcXlcXyXNzK19/pEUxS58RzkJ/O6OmHAxKoRmnZol27q87Yb0i+/wlDu3N2Bt+NWB4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ADdLpRe8; 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="ADdLpRe8" Received: by smtp.kernel.org (Postfix) with ESMTPS id 7C621C116B1; Sun, 23 Nov 2025 08:36:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1763886984; bh=4VcxCMgYhmMmtFoirHuT2VY7mXYknw3cZfIwfQ93BDg=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=ADdLpRe8tjByzXw83VIaT5hoSXH7vb1EdbIkOztecE5k7keW7iypTqd+doDcoT/F/ y23qn+6Vz26wH0BEVOl1n/wjVL/elMdNjB7U5UwS3/os/5ATZAVwPfAd7roHlDfVlM NyZ7upDErTe9OAx6dgO8EWL1xK/LsQwCjLjgTy9w2ZVsBJdxl8MFAKdp6jyI8TKthB UH+F+aspDg0WXrXyQijcSZ+onyjNlBGo9qgz4mb0QFNHaGmWflZPMhnklPLW64uB+X nUU+1L8me725OoN17cUemaJX0XmmTSX/9SjIVuUOKPirs5lyMJK5BLNBcPV4RsNSt+ ggzduqEyewamA== 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 71784CFD318; Sun, 23 Nov 2025 08:36:24 +0000 (UTC) From: Amit Sunil Dhamne via B4 Relay Date: Sun, 23 Nov 2025 08:35:50 +0000 Subject: [PATCH 3/6] dt-bindings: usb: maxim,max33359: Add supply property for VBUS in OTG 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: <20251123-max77759-charger-v1-3-6b2e4b8f7f54@google.com> References: <20251123-max77759-charger-v1-0-6b2e4b8f7f54@google.com> In-Reply-To: <20251123-max77759-charger-v1-0-6b2e4b8f7f54@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 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=1763886983; l=1124; i=amitsd@google.com; s=20241031; h=from:subject:message-id; bh=ak0DhAM6ewGMiDuF0MxJPbPRxRy5VTuNwAK+zQj0j2o=; b=mnGqbVl/z06LDtgfnWHySKhlpzdB1tI4sr08M43fZvaKI1QcLj53kcG8lfxv77MkytMWWtr3k noSNgWtq7qIDsQ+UoA9apDtsiFUsGzHKu5mAgTiqkWWxOP57RsbPlrE 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 when usb is in OTG mode. Signed-off-by: Amit Sunil Dhamne Reviewed-by: Badhri Jagan Sridharan --- 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..a529f18c4918 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 + otg-vbus-supply: + description: Regulator to control OTG VBUS supply. + required: - compatible - reg @@ -53,6 +56,7 @@ examples: reg =3D <0x25>; interrupt-parent =3D <&gpa8>; interrupts =3D <2 IRQ_TYPE_LEVEL_LOW>; + otg-vbus-supply =3D <&otg_vbus_reg>; =20 connector { compatible =3D "usb-c-connector"; --=20 2.52.0.rc2.455.g230fcf2819-goog From nobody Tue Dec 2 01:05:42 2025 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 F03352C0262; Sun, 23 Nov 2025 08:36:24 +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=1763886985; cv=none; b=TGiJg+G5nHSacrQTaXpHJppiA2YpqXmLu7l9azuoBjY+aIhkbw2XoScaRQER8NHLROXK7vKa0s5d44dds+MFr6Pf/hdl5LYakBtrvBxJksH/xhN+Qxv6H5qjlMbvQ4s7qTY8U8KhhWzyCWVQbFVoR4re5cGxrNyZ/tbluKggYWk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763886985; c=relaxed/simple; bh=XywpMBorThuIKgeGhgmqKn4VVOL6JzS6r+Dw3Lm+3d4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=D42z/BJzcy4L6H0NVC3X011r/Jsy+/zQLNNd3IcYjVVG2iRhdDhsUQlqo+/MntR94eXZHXiBuUR/rYf5ZItSxi0yEYt9xADwmRQWsqhyDhEl6RLmfsaU3Abx3m5BhQZ1uHfEzJvFqUWkI/uPHRAjGM8gI89VXyezWXZPWFQoqA8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=V/QC1nEc; 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="V/QC1nEc" Received: by smtp.kernel.org (Postfix) with ESMTPS id 9161EC2BC9E; Sun, 23 Nov 2025 08:36:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1763886984; bh=XywpMBorThuIKgeGhgmqKn4VVOL6JzS6r+Dw3Lm+3d4=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=V/QC1nEcPQTwG9JdsiEwRV0U1JqdLDptZqAMBYHB41kEtyX3L2fYB6kUwlPgaKzuv hGm05S2fVwgOU/FJNUz6usHvdAEp99DiRqTGm4QciJftBSkuH5we9RhCdOylSXokkj RJ/7/hTKxxwJHNMwys0y+vuAat6uguT+jc94V5YZAGgxVve2VOUGfNc726P8OlcDMC MqujKW1zAKq1bAL04pECILC8ebsP8LS1/5DMNKDkbt/rULH5QcwmppN45kHUYTs680 Jyi9YRy786cco16qnjR7HCWbwy/pVoUKrf21bINyH2qS6YFEmp3+3Kvfvg4Ak2YDzo GKwR7bq83sLFg== 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 86336CFD313; Sun, 23 Nov 2025 08:36:24 +0000 (UTC) From: Amit Sunil Dhamne via B4 Relay Date: Sun, 23 Nov 2025 08:35:51 +0000 Subject: [PATCH 4/6] mfd: max77759: modify irq configs 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: <20251123-max77759-charger-v1-4-6b2e4b8f7f54@google.com> References: <20251123-max77759-charger-v1-0-6b2e4b8f7f54@google.com> In-Reply-To: <20251123-max77759-charger-v1-0-6b2e4b8f7f54@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 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=1763886983; l=4037; i=amitsd@google.com; s=20241031; h=from:subject:message-id; bh=ydOm266hojKPbD6WEKQRUV3ZGSm1ejU3wNAfglGRhno=; b=V5F8mWlubDiqVeB/Qx2PXvLfFRy1bZXHPRhI1RFtIE+oJ0pFc2cLyPkBnE4Kufu8NvwJsgyWT q5sdtKQKd+JDkFRFS2KdOYsKLKdNAoQm0EpFjoOIr8sEAt7k5C0bEGV 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 Define specific bit-level masks for charger's registers and modify the irq mask for charger irq_chip. Also, configure the max77759 interrupt lines as active low to all interrupt registrations to ensure the interrupt controllers are configured with the correct trigger type. Signed-off-by: Amit Sunil Dhamne --- drivers/mfd/max77759.c | 24 +++++++++++++++++------- include/linux/mfd/max77759.h | 9 +++++++++ 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/drivers/mfd/max77759.c b/drivers/mfd/max77759.c index 6cf6306c4a3b..5fe22884f362 100644 --- a/drivers/mfd/max77759.c +++ b/drivers/mfd/max77759.c @@ -256,8 +256,17 @@ 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_CHARGER_INT_1, 0, + MAX77759_CHGR_REG_CHG_INT_AICL | + MAX77759_CHGR_REG_CHG_INT_CHGIN | + MAX77759_CHGR_REG_CHG_INT_CHG | + MAX77759_CHGR_REG_CHG_INT_INLIM), + REGMAP_IRQ_REG(MAX77759_CHARGER_INT_2, 1, + MAX77759_CHGR_REG_CHG_INT2_BAT_OILO | + MAX77759_CHGR_REG_CHG_INT2_CHG_STA_CC | + MAX77759_CHGR_REG_CHG_INT2_CHG_STA_CV | + MAX77759_CHGR_REG_CHG_INT2_CHG_STA_TO | + MAX77759_CHGR_REG_CHG_INT2_CHG_STA_DONE), }; =20 static const struct regmap_irq_chip max77759_pmic_irq_chip =3D { @@ -486,8 +495,8 @@ static int max77759_add_chained_irq_chip(struct device = *dev, "failed to get parent vIRQ(%d) for chip %s\n", pirq, chip->name); =20 - ret =3D devm_regmap_add_irq_chip(dev, regmap, irq, - IRQF_ONESHOT | IRQF_SHARED, 0, chip, + ret =3D devm_regmap_add_irq_chip(dev, regmap, irq, IRQF_ONESHOT | + IRQF_SHARED | IRQF_TRIGGER_LOW, 0, chip, data); if (ret) return dev_err_probe(dev, ret, "failed to add %s IRQ chip\n", @@ -519,8 +528,9 @@ static int max77759_add_chained_maxq(struct i2c_client = *client, =20 ret =3D devm_request_threaded_irq(&client->dev, apcmdres_irq, NULL, apcmdres_irq_handler, - IRQF_ONESHOT | IRQF_SHARED, - dev_name(&client->dev), max77759); + IRQF_ONESHOT | IRQF_SHARED | + IRQF_TRIGGER_LOW, dev_name(&client->dev), + max77759); if (ret) return dev_err_probe(&client->dev, ret, "MAX77759_MAXQ_INT_APCMDRESI failed\n"); @@ -633,7 +643,7 @@ static int max77759_probe(struct i2c_client *client) return dev_err_probe(&client->dev, -EINVAL, "invalid IRQ: %d\n", client->irq); =20 - irq_flags =3D IRQF_ONESHOT | IRQF_SHARED; + irq_flags =3D IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_LOW; irq_flags |=3D irqd_get_trigger_type(irq_data); =20 ret =3D devm_regmap_add_irq_chip(&client->dev, max77759->regmap_top, diff --git a/include/linux/mfd/max77759.h b/include/linux/mfd/max77759.h index c6face34e385..0ef29a48deec 100644 --- a/include/linux/mfd/max77759.h +++ b/include/linux/mfd/max77759.h @@ -62,7 +62,16 @@ #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_INT_AICL BIT(7) +#define MAX77759_CHGR_REG_CHG_INT_CHGIN BIT(6) +#define MAX77759_CHGR_REG_CHG_INT_CHG BIT(4) +#define MAX77759_CHGR_REG_CHG_INT_INLIM BIT(2) #define MAX77759_CHGR_REG_CHG_INT2_MASK 0xb3 +#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_OK 0xb4 #define MAX77759_CHGR_REG_CHG_DETAILS_00 0xb5 #define MAX77759_CHGR_REG_CHG_DETAILS_01 0xb6 --=20 2.52.0.rc2.455.g230fcf2819-goog From nobody Tue Dec 2 01:05:42 2025 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 2CC9C2C21EF; Sun, 23 Nov 2025 08:36:24 +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=1763886985; cv=none; b=MEvN3fVTrqUqyEHcQENNfl8VOBVHm+Rz7OeDSm82X74MQnZECVnSzp3DHLwjzwD0yUiyYE6ymHuAlNK+IzWDmyg7f6PaGMI76U7uNvt0I3qVfL6GSTOnBql1IVLgIG8wgxEr3i2etCLOgKDV5rnqbjfF/P5E4zhEqSi948WPYC0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763886985; c=relaxed/simple; bh=nbI3jzIZ2uEKktt3QCn8jq0Xe2XjfYUGU4VdU9jUR1s=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=SgBAw5wlt3vqa2RrwP2190Yz+2u185wE0iid96VpLP+3Ohx6i7zQLIoGrO4uW47T1vOO+N69wKORmiqDqw72DwG86JmOyBT0+x1or+3NWVIqTOo/YDgNjATy34LjUB2kgOkfOKv/iaKkm1dV8Vl2pEAfPUZ8YzRuhFwR9UC0Xbw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=M13cjboI; 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="M13cjboI" Received: by smtp.kernel.org (Postfix) with ESMTPS id A6A34C19422; Sun, 23 Nov 2025 08:36:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1763886984; bh=nbI3jzIZ2uEKktt3QCn8jq0Xe2XjfYUGU4VdU9jUR1s=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=M13cjboIN0xNTjW7/K9zdVOIuYrq69Jw6HOA2HX6zpzgsaV7XxbyR06nFGZzmFLnm CRxSQaeC52fmkZ+Izpygvm6Ip92YkIbeGWIRr+Q8QVWSPh3Ae8+e90OZxDLtFI7kdw 5IWb19M1Q3a9IMizcFj9PPR+VakMXadm3ezyhBdGwIWSkx+x2TqqH5fqN1GT7xodCh WTSDip7qZ/+1/fbq/ew6h9g67MZ8aWxZlC3iqrQebvDCZ1E07ynNz3+X1MHc0pIwhU 4/a537BsMw90rx4nhDs4MOy2jZpXaD7NHFqtRLXtqbPjXOI6FibQ1tijWkgREOUNix wB0382t1ZqUvw== 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 9A564CFC518; Sun, 23 Nov 2025 08:36:24 +0000 (UTC) From: Amit Sunil Dhamne via B4 Relay Date: Sun, 23 Nov 2025 08:35:52 +0000 Subject: [PATCH 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: <20251123-max77759-charger-v1-5-6b2e4b8f7f54@google.com> References: <20251123-max77759-charger-v1-0-6b2e4b8f7f54@google.com> In-Reply-To: <20251123-max77759-charger-v1-0-6b2e4b8f7f54@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 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=1763886983; l=27952; i=amitsd@google.com; s=20241031; h=from:subject:message-id; bh=olSsVAIqZAs6q4ySfHs7E4OAjYF++M56AzHStv3HjTo=; b=QA6K8gT1GIXhGCkzvrie8tzzZaP8ypqHWHEj7Tvguoy1ohgzbGPIVglDVOYWMjiX5eBMN2GjI sqOxTxCVFn5BkzAZ26sIo3f6BLLS4l18GkFOa/xfcGA8uVUCvHvpYA+ 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 --- MAINTAINERS | 7 + drivers/mfd/max77759.c | 3 +- drivers/power/supply/Kconfig | 11 + drivers/power/supply/Makefile | 1 + drivers/power/supply/max77759_charger.c | 866 ++++++++++++++++++++++++++++= ++++ 5 files changed, 887 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index fed6cd812d79..f1b1015c08b5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -15053,6 +15053,13 @@ 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: Documentation/devicetree/bindings/power/supply/maxim,max77759-charger.y= aml +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/mfd/max77759.c b/drivers/mfd/max77759.c index 5fe22884f362..8a22838be1b0 100644 --- a/drivers/mfd/max77759.c +++ b/drivers/mfd/max77759.c @@ -349,7 +349,8 @@ static const struct mfd_cell max77759_maxq_cells[] =3D { }; =20 static const struct mfd_cell max77759_charger_cells[] =3D { - MFD_CELL_RES("max77759-charger", max77759_charger_resources), + MFD_CELL_OF("max77759-charger", max77759_charger_resources, NULL, 0, 0, + "maxim,max77759-charger"), }; =20 int max77759_maxq_command(struct max77759 *max77759, diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig index 79ddb006e2da..b97990cc0b92 100644 --- a/drivers/power/supply/Kconfig +++ b/drivers/power/supply/Kconfig @@ -1074,4 +1074,15 @@ config FUEL_GAUGE_MM8013 the state of charge, temperature, cycle count, actual and design capacity, etc. =20 +config CHARGER_MAX77759 + tristate "MAX77759 Charger Driver" + depends on MFD_MAX77759 + default MFD_MAX77759 + help + Say M or Y here to enable the MAX77759 Charger Driver. 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. + endif # POWER_SUPPLY diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile index f943c9150b32..12669734cfe3 100644 --- a/drivers/power/supply/Makefile +++ b/drivers/power/supply/Makefile @@ -122,3 +122,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..51637e87182b --- /dev/null +++ b/drivers/power/supply/max77759_charger.c @@ -0,0 +1,866 @@ +// 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 + +/* CHG_INT_OK */ +#define CHG_INT_OK_AICL_OK BIT(7) +#define CHG_INT_OK_CHGIN_OK BIT(6) +#define CHG_INT_OK_CHG_OK BIT(4) +#define CHG_INT_OK_INLIM_OK BIT(2) + +/* CHG_DETAILS_00 */ +#define CHG_DETAILS_OO_CHGIN_DTLS GENMASK(6, 5) + +/* + * Charger Input Status + * @CHGIN_DTLS_VBUS_UNDERVOLTAGE: Charger input voltage (Vchgin) < Under V= oltage + * Threshold (Vuvlo) + * @CHGIN_DTLS_VBUS_MARGINAL_VOLTAGE: Vchgin > Vuvlo and + * Vchgin < (Battery Voltage (Vbatt) + system voltage (Vsys)) + * @CHGIN_DTLS_VBUS_OVERVOLTAGE: Vchgin > Over Voltage threshold (Vovlo) + * @CHGIN_DTLS_VBUS_VALID: Vchgin > Vuvlo, Vchgin < Vovlo and + * Vchgin > (Vsys + Vbatt) + */ +enum chgin_dtls_status { + CHGIN_DTLS_VBUS_UNDERVOLTAGE, + CHGIN_DTLS_VBUS_MARGINAL_VOLTAGE, + CHGIN_DTLS_VBUS_OVERVOLTAGE, + CHGIN_DTLS_VBUS_VALID, +}; + +/* CHG_DETAILS_01 */ +#define CHG_DETAILS_01_BAT_DTLS GENMASK(6, 4) + +/* + * Battery Details + * @BAT_DTLS_NO_BATT_CHG_SUSP: No battery and the charger suspended + * @BAT_DTLS_DEAD_BATTERY: Vbatt < Vtrickle + * @BAT_DTLS_BAT_CHG_TIMER_FAULT: Charging suspended due to timer fault + * @BAT_DTLS_BAT_OKAY: Battery okay and Vbatt > Min Sys Voltage (Vsysmin) + * @BAT_DTLS_BAT_UNDERVOLTAGE: Battery is okay. Vtrickle < Vbatt < Vsys= min + * @BAT_DTLS_BAT_OVERVOLTAGE: Battery voltage > Overvoltage threshold + * @BAT_DTLS_BAT_OVERCURRENT: Battery current exceeds overcurrent threshold + * @BAT_DTLS_BAT_ONLY_MODE: Battery only mode and battery level not avai= lable + */ +enum bat_dtls_states { + BAT_DTLS_NO_BATT_CHG_SUSP, + BAT_DTLS_DEAD_BATTERY, + BAT_DTLS_BAT_CHG_TIMER_FAULT, + BAT_DTLS_BAT_OKAY, + BAT_DTLS_BAT_UNDERVOLTAGE, + BAT_DTLS_BAT_OVERVOLTAGE, + BAT_DTLS_BAT_OVERCURRENT, + BAT_DTLS_BAT_ONLY_MODE, +}; + +#define CHG_DETAILS_01_CHG_DTLS GENMASK(3, 0) + +/* + * Charger Details + * @CHG_DTLS_PREQUAL: Charger in prequalification mode + * @CHG_DTLS_CC: Charger in fast charge const curr mode + * @CHG_DTLS_CV: Charger in fast charge const voltage mode + * @CHG_DTLS_TO: Charger is in top off mode + * @CHG_DTLS_DONE: Charger is done + * @CHG_DTLS_RSVD_1: Reserved + * @CHG_DTLS_TIMER_FAULT: Charger is in timer fault mode + * @CHG_DTLS_SUSP_BATT_THM: Charger is suspended as bettery removal detect= ed + * @CHG_DTLS_OFF: Charger is off. Input invalid or charger disabled + * @CHG_DTLS_RSVD_2: Reserved + * @CHG_DTLS_RSVD_3: Reserved + * @CHG_DTLS_OFF_WDOG_TIMER: Charger is off as watchdog timer expired + * @CHG_DTLS_SUSP_JEITA: Charger is in JEITA control mode + */ +enum chg_dtls_states { + CHG_DTLS_PREQUAL, + CHG_DTLS_CC, + CHG_DTLS_CV, + CHG_DTLS_TO, + CHG_DTLS_DONE, + CHG_DTLS_RSVD_1, + CHG_DTLS_TIMER_FAULT, + CHG_DTLS_SUSP_BATT_THM, + CHG_DTLS_OFF, + CHG_DTLS_RSVD_2, + CHG_DTLS_RSVD_3, + CHG_DTLS_OFF_WDOG_TIMER, + CHG_DTLS_SUSP_JEITA, +}; + +/* CHG_DETAILS_02 */ +#define CHG_DETAILS_02_CHGIN_STS BIT(5) + +/* CHG_CNFG_00 */ +#define CHG_CNFG_00_MODE GENMASK(3, 0) + +enum chg_mode { + CHG_MODE_OFF, + CHG_MODE_CHG_BUCK_ON =3D 0x5, + CHG_MODE_OTG_BOOST_ON =3D 0xA, +}; + +/* CHG_CNFG_02 */ +/* Fast Charge Current Selection (in uA) */ +#define CHG_CNFG_02_CHGCC GENMASK(5, 0) +#define CHGCC_LIMIT_MIN_UA 133330 +#define CHGCC_LIMIT_MAX_UA 4000000 +#define CHGCC_LIMIT_STEP_UA 66670 +#define CHGCC_LIMIT_REG_OFFSET 0x2 + +/* CHG_CNFG_04 */ +/* Charge Termination Voltage Setting (in mV) */ +#define CHG_CNFG_04_CHG_CV_PRM GENMASK(5, 0) +/* [3.8, 3.9] V range */ +#define CHG_CV_PRM_LIMIT_LO_MIN_MV 3800 +#define CHG_CV_PRM_LIMIT_LO_MAX_MV 3900 +#define CHG_CV_PRM_LIMIT_LO_STEP_MV 100 +#define CHG_CV_PRM_LIMIT_LO_MIN_REG 0x38 +#define CHG_CV_PRM_LIMIT_LO_MAX_REG 0x39 +/* [4, 4.5] V range */ +#define CHG_CV_PRM_LIMIT_HI_MIN_MV 4000 +#define CHG_CV_PRM_LIMIT_HI_MAX_MV 4500 +#define CHG_CV_PRM_LIMIT_HI_STEP_MV 10 +#define CHG_CV_PRM_LIMIT_HI_MIN_REG 0x0 +#define CHG_CV_PRM_LIMIT_HI_MAX_REG 0x32 + +/* CHG_CNFG_06 */ +#define CHG_CNFG_06_CHGPROT GENMASK(3, 2) + +/* CHG_CNFG_09 */ +/* CHGIN Input Current Limit (in uA) */ +#define CHG_CNFG_09_CHGIN_ILIM GENMASK(6, 0) +#define CHGIN_ILIM_MIN_UA 100000 +#define CHGIN_ILIM_MAX_UA 3200000 +#define CHGIN_ILIM_STEP_UA 25000 +#define CHGIN_ILIM_REG_OFFSET 0x3 + +/* CHG_CNFG_12 (Protected) */ +/* Wireless Charging input channel select */ +#define CHG_CNFG_12_WCINSEL BIT(6) +/* CHGIN/USB input channel select */ +#define CHG_CNFG_12_CHGINSEL BIT(5) + +/* CHG_CNFG_18 (Protected) */ +/* Watchdog Timer Enable Bit */ +#define CHG_CNFG_18_WDTEN BIT(0) + +/* Default values for Fast Charge Current & Float Voltage */ +#define CHG_CC_DEFAULT_UA 2266770 +#define CHG_FV_DEFAULT_MV 4300 + +struct max77759_charger { + struct device *dev; + struct regmap *regmap; + struct power_supply *psy; + int irq[2]; + struct regulator_dev *usb_otg_rdev; + struct notifier_block nb; + struct power_supply *tcpm_psy; + struct work_struct psy_work; + struct mutex lock; /* protects the state below */ + enum chg_mode mode; +}; + +static inline int regval_to_val(int reg, int reg_offset, int step, int min= val) +{ + return ((reg - reg_offset) * step) + minval; +} + +static inline int val_to_regval(int val, int minval, int step, int reg_off= set) +{ + s64 dividend; + + if (unlikely(step =3D=3D 0)) + return reg_offset; + + dividend =3D (s64)val - minval; + return DIV_S64_ROUND_CLOSEST(dividend, step) + reg_offset; +} + +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, + CHG_CNFG_06_CHGPROT, + unlock ? 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 & CHG_INT_OK_CHG_OK) && (val & CHG_INT_OK_CHGIN_OK); +} + +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 & CHG_DETAILS_02_CHGIN_STS) && + (chg->mode =3D=3D CHG_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(CHG_DETAILS_01_CHG_DTLS, val)) { + case CHG_DTLS_PREQUAL: + case CHG_DTLS_CC: + case CHG_DTLS_CV: + case CHG_DTLS_TO: + return POWER_SUPPLY_STATUS_CHARGING; + case CHG_DTLS_DONE: + return POWER_SUPPLY_STATUS_FULL; + case CHG_DTLS_TIMER_FAULT: + case CHG_DTLS_SUSP_BATT_THM: + case CHG_DTLS_OFF_WDOG_TIMER: + case CHG_DTLS_SUSP_JEITA: + return POWER_SUPPLY_STATUS_NOT_CHARGING; + case 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(CHG_DETAILS_01_CHG_DTLS, val)) { + case CHG_DTLS_PREQUAL: + return POWER_SUPPLY_CHARGE_TYPE_TRICKLE; + case CHG_DTLS_CC: + return POWER_SUPPLY_CHARGE_TYPE_FAST; + case CHG_DTLS_CV: + case CHG_DTLS_TO: + return POWER_SUPPLY_CHARGE_TYPE_STANDARD; + case CHG_DTLS_DONE: + case CHG_DTLS_TIMER_FAULT: + case CHG_DTLS_SUSP_BATT_THM: + case CHG_DTLS_OFF_WDOG_TIMER: + case CHG_DTLS_SUSP_JEITA: + case 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(CHG_DETAILS_OO_CHGIN_DTLS, val)) { + case CHGIN_DTLS_VBUS_UNDERVOLTAGE: + case CHGIN_DTLS_VBUS_MARGINAL_VOLTAGE: + return POWER_SUPPLY_HEALTH_UNDERVOLTAGE; + case CHGIN_DTLS_VBUS_OVERVOLTAGE: + return POWER_SUPPLY_HEALTH_OVERVOLTAGE; + case 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(CHG_DETAILS_01_BAT_DTLS, val)) { + case BAT_DTLS_NO_BATT_CHG_SUSP: + return POWER_SUPPLY_HEALTH_NO_BATTERY; + case BAT_DTLS_DEAD_BATTERY: + return POWER_SUPPLY_HEALTH_DEAD; + case BAT_DTLS_BAT_CHG_TIMER_FAULT: + return POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE; + case BAT_DTLS_BAT_OKAY: + case BAT_DTLS_BAT_ONLY_MODE: + return POWER_SUPPLY_HEALTH_GOOD; + case BAT_DTLS_BAT_UNDERVOLTAGE: + return POWER_SUPPLY_HEALTH_UNDERVOLTAGE; + case BAT_DTLS_BAT_OVERVOLTAGE: + return POWER_SUPPLY_HEALTH_OVERVOLTAGE; + case 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; + int ret; + + ret =3D regmap_read(chg->regmap, MAX77759_CHGR_REG_CHG_CNFG_02, ®val); + if (ret) + return ret; + + ret =3D FIELD_GET(CHG_CNFG_02_CHGCC, regval); + if (ret <=3D CHGCC_LIMIT_REG_OFFSET) + return CHGCC_LIMIT_MIN_UA; + + return regval_to_val(ret, CHGCC_LIMIT_REG_OFFSET, CHGCC_LIMIT_STEP_UA, + CHGCC_LIMIT_MIN_UA); +} + +static int set_fast_charge_current_limit(struct max77759_charger *chg, u32= cc_max_ua) +{ + u32 val; + + if (cc_max_ua < CHGCC_LIMIT_MIN_UA || cc_max_ua > CHGCC_LIMIT_MAX_UA) + return -EINVAL; + + val =3D val_to_regval(cc_max_ua, CHGCC_LIMIT_MIN_UA, CHGCC_LIMIT_STEP_UA, + CHGCC_LIMIT_REG_OFFSET); + return regmap_update_bits(chg->regmap, MAX77759_CHGR_REG_CHG_CNFG_02, + CHG_CNFG_02_CHGCC, val); +} + +static int get_float_voltage(struct max77759_charger *chg) +{ + u32 regval; + int ret; + + ret =3D regmap_read(chg->regmap, MAX77759_CHGR_REG_CHG_CNFG_04, ®val); + if (ret) + return ret; + + ret =3D FIELD_GET(CHG_CNFG_04_CHG_CV_PRM, regval); + switch (ret) { + case CHG_CV_PRM_LIMIT_HI_MIN_REG ... CHG_CV_PRM_LIMIT_HI_MAX_REG: + return regval_to_val(ret, CHG_CV_PRM_LIMIT_HI_MIN_REG, + CHG_CV_PRM_LIMIT_HI_STEP_MV, + CHG_CV_PRM_LIMIT_HI_MIN_MV); + case CHG_CV_PRM_LIMIT_LO_MIN_REG ... CHG_CV_PRM_LIMIT_LO_MAX_REG: + return regval_to_val(ret, CHG_CV_PRM_LIMIT_LO_MIN_REG, + CHG_CV_PRM_LIMIT_LO_STEP_MV, + CHG_CV_PRM_LIMIT_LO_MIN_MV); + default: + return -EINVAL; + } + + return 0; +} + +static int set_float_voltage_limit(struct max77759_charger *chg, u32 fv_mv) +{ + u32 regval; + + if (fv_mv >=3D CHG_CV_PRM_LIMIT_LO_MIN_MV && + fv_mv <=3D CHG_CV_PRM_LIMIT_LO_MAX_MV) { + regval =3D val_to_regval(fv_mv, CHG_CV_PRM_LIMIT_LO_MIN_MV, + CHG_CV_PRM_LIMIT_LO_STEP_MV, + CHG_CV_PRM_LIMIT_LO_MIN_REG); + } else if (fv_mv >=3D CHG_CV_PRM_LIMIT_HI_MIN_MV && + fv_mv <=3D CHG_CV_PRM_LIMIT_HI_MAX_MV) { + regval =3D val_to_regval(fv_mv, CHG_CV_PRM_LIMIT_HI_MIN_MV, + CHG_CV_PRM_LIMIT_HI_STEP_MV, + CHG_CV_PRM_LIMIT_HI_MIN_REG); + } else { + return -EINVAL; + } + + return regmap_update_bits(chg->regmap, MAX77759_CHGR_REG_CHG_CNFG_04, + CHG_CNFG_04_CHG_CV_PRM, regval); +} + +static int get_input_current_limit(struct max77759_charger *chg) +{ + u32 regval; + int ret; + + ret =3D regmap_read(chg->regmap, MAX77759_CHGR_REG_CHG_CNFG_09, ®val); + if (ret) + return ret; + + ret =3D FIELD_GET(CHG_CNFG_09_CHGIN_ILIM, regval); + if (ret <=3D CHGIN_ILIM_REG_OFFSET) + return CHGIN_ILIM_MIN_UA; + + return regval_to_val(ret, CHGIN_ILIM_REG_OFFSET, CHGIN_ILIM_STEP_UA, + CHGIN_ILIM_MIN_UA); +} + +static int set_input_current_limit(struct max77759_charger *chg, int ilim_= ua) +{ + u32 regval; + + if (ilim_ua < 0) + return -EINVAL; + + if (ilim_ua =3D=3D 0) + ilim_ua =3D CHGIN_ILIM_MIN_UA; + else if (ilim_ua > CHGIN_ILIM_MAX_UA) + ilim_ua =3D CHGIN_ILIM_MAX_UA; + + regval =3D val_to_regval(ilim_ua, CHGIN_ILIM_MIN_UA, + CHGIN_ILIM_STEP_UA, CHGIN_ILIM_REG_OFFSET); + return regmap_update_bits(chg->regmap, MAX77759_CHGR_REG_CHG_CNFG_09, + 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 chg_mode mo= de) +{ + int ret; + + guard(mutex)(&chg->lock); + + if (chg->mode =3D=3D mode) + return 0; + + if ((mode =3D=3D CHG_MODE_CHG_BUCK_ON || mode =3D=3D CHG_MODE_OTG_BOOST_O= N) && + chg->mode !=3D CHG_MODE_OFF) { + dev_err(chg->dev, "Invalid mode transition from %d to %d", + chg->mode, mode); + return -EINVAL; + } + + ret =3D regmap_update_bits(chg->regmap, MAX77759_CHGR_REG_CHG_CNFG_00, + CHG_CNFG_00_MODE, mode); + if (ret) + return ret; + + chg->mode =3D mode; + return 0; +} + +static int enable_usb_otg(struct regulator_dev *rdev) +{ + struct max77759_charger *chg =3D rdev_get_drvdata(rdev); + + return charger_set_mode(chg, CHG_MODE_OTG_BOOST_ON); +} + +static int disable_usb_otg(struct regulator_dev *rdev) +{ + struct max77759_charger *chg =3D rdev_get_drvdata(rdev); + + return charger_set_mode(chg, CHG_MODE_OFF); +} + +static int usb_otg_status(struct regulator_dev *rdev) +{ + struct max77759_charger *chg =3D rdev_get_drvdata(rdev); + + guard(mutex)(&chg->lock); + return chg->mode =3D=3D CHG_MODE_OTG_BOOST_ON; +} + +static const struct regulator_ops usb_otg_reg_ops =3D { + .enable =3D enable_usb_otg, + .disable =3D disable_usb_otg, + .is_enabled =3D usb_otg_status, +}; + +static const struct regulator_desc usb_otg_reg_desc =3D { + .name =3D "usb-otg-vbus", + .of_match =3D of_match_ptr("usb-otg-vbus-regulator"), + .owner =3D THIS_MODULE, + .ops =3D &usb_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; + u32 irq_status, chgint_ok, idx =3D 0; + int ret; + + if (irq =3D=3D chg->irq[0]) + idx =3D 0; + else + idx =3D 1; + + ret =3D regmap_read(chg->regmap, MAX77759_CHGR_REG_CHG_INT + idx, + &irq_status); + if (ret) { + dev_err(chg->dev, "regmap_read_error idx=3D%d ret=3D%d", idx, ret); + return IRQ_HANDLED; + } + + regmap_write(chg->regmap, MAX77759_CHGR_REG_CHG_INT + idx, + irq_status); + regmap_read(chg->regmap, MAX77759_CHGR_REG_CHG_INT_OK, &chgint_ok); + + if (idx =3D=3D 0) { + if (irq_status & MAX77759_CHGR_REG_CHG_INT_AICL) + dev_dbg(chg->dev, "AICL mode: %s", + str_no_yes(chgint_ok & CHG_INT_OK_AICL_OK)); + + if (irq_status & MAX77759_CHGR_REG_CHG_INT_CHGIN) + dev_dbg(chg->dev, "CHGIN input valid: %s", + str_yes_no(chgint_ok & CHG_INT_OK_CHGIN_OK)); + + if (irq_status & MAX77759_CHGR_REG_CHG_INT_CHG) + dev_dbg(chg->dev, "CHG status okay/off: %s", + str_yes_no(chgint_ok & CHG_INT_OK_CHG_OK)); + + if (irq_status & MAX77759_CHGR_REG_CHG_INT_INLIM) + dev_dbg(chg->dev, "Current Limit reached: %s", + str_no_yes(chgint_ok & CHG_INT_OK_INLIM_OK)); + } else { + if (irq_status & MAX77759_CHGR_REG_CHG_INT2_BAT_OILO) + dev_dbg(chg->dev, + "Battery over-current threshold crossed"); + + if (irq_status & MAX77759_CHGR_REG_CHG_INT2_CHG_STA_CC) + dev_dbg(chg->dev, "Charger reached CC stage"); + + if (irq_status & MAX77759_CHGR_REG_CHG_INT2_CHG_STA_CV) + dev_dbg(chg->dev, "Charger reached CV stage"); + + if (irq_status & MAX77759_CHGR_REG_CHG_INT2_CHG_STA_TO) + dev_dbg(chg->dev, "Charger reached TO stage"); + + if (irq_status & MAX77759_CHGR_REG_CHG_INT2_CHG_STA_DONE) + dev_dbg(chg->dev, "Charger reached Done stage"); + } + + power_supply_changed(chg->psy); + return IRQ_HANDLED; +} + +static int max77759_init_irqhandler(struct max77759_charger *chg) +{ + static const char * const irq_res_names[] =3D { "INT1", "INT2" }; + struct device *dev =3D chg->dev; + unsigned long irq_flags; + struct irq_data *irqd; + int *irq =3D chg->irq; + int ret, i; + + for (i =3D 0; i < 2; i++) { + irq[i] =3D platform_get_irq_byname(to_platform_device(dev), + irq_res_names[i]); + if (irq[i] < 0) { + dev_err(dev, "unable to find %s irq", irq_res_names[i]); + return irq[i]; + } + + irq_flags =3D IRQF_ONESHOT | IRQF_SHARED; + irqd =3D irq_get_irq_data(irq[i]); + if (irqd) + irq_flags |=3D irqd_get_trigger_type(irqd); + + ret =3D devm_request_threaded_irq(dev, irq[i], NULL, irq_handler, + irq_flags, dev_name(dev), chg); + if (ret) { + dev_err(dev, "Unable to register threaded irq handler"); + return ret; + } + } + + return 0; +} + +static int max77759_charger_init(struct max77759_charger *chg) +{ + int ret; + u32 regval; + + regmap_read(chg->regmap, MAX77759_CHGR_REG_CHG_CNFG_00, ®val); + chg->mode =3D FIELD_GET(CHG_CNFG_00_MODE, regval); + ret =3D charger_set_mode(chg, CHG_MODE_OFF); + if (ret) + return ret; + + ret =3D set_fast_charge_current_limit(chg, CHG_CC_DEFAULT_UA); + if (ret) + return ret; + + ret =3D set_float_voltage_limit(chg, CHG_FV_DEFAULT_MV); + if (ret) + return ret; + + ret =3D unlock_prot_regs(chg, true); + if (ret) + return ret; + + /* Disable wireless charging input */ + regmap_update_bits(chg->regmap, MAX77759_CHGR_REG_CHG_CNFG_12, + CHG_CNFG_12_WCINSEL, 0); + + regmap_update_bits(chg->regmap, MAX77759_CHGR_REG_CHG_CNFG_18, + CHG_CNFG_18_WDTEN, 0); + + return unlock_prot_regs(chg, false); +} + +static void psy_work_item(struct work_struct *work) +{ + struct max77759_charger *chg =3D + container_of(work, struct max77759_charger, psy_work); + union power_supply_propval current_limit =3D { 0 }, online =3D { 0 }; + int ret; + + power_supply_get_property(chg->tcpm_psy, POWER_SUPPLY_PROP_CURRENT_MAX, + ¤t_limit); + power_supply_get_property(chg->tcpm_psy, POWER_SUPPLY_PROP_ONLINE, + &online); + + 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", ret); + + charger_set_mode(chg, CHG_MODE_CHG_BUCK_ON); + } else { + charger_set_mode(chg, CHG_MODE_OFF); + } +} + +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); + 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; + schedule_work(&chg->psy_work); + 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 usb_otg_reg_cfg; + struct power_supply_config psy_cfg; + struct device *dev =3D &pdev->dev; + struct max77759_charger *chg; + int ret; + + 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"); + + ret =3D devm_mutex_init(dev, &chg->lock); + if (ret) + return dev_err_probe(dev, ret, "Failed to initialize lock"); + + ret =3D max77759_charger_init(chg); + if (ret) + return dev_err_probe(dev, ret, + "Failed to initialize max77759 charger"); + + usb_otg_reg_cfg.dev =3D dev; + usb_otg_reg_cfg.driver_data =3D chg; + usb_otg_reg_cfg.of_node =3D dev_of_node(dev); + chg->usb_otg_rdev =3D devm_regulator_register(dev, &usb_otg_reg_desc, + &usb_otg_reg_cfg); + if (IS_ERR(chg->usb_otg_rdev)) + return dev_err_probe(dev, PTR_ERR(chg->usb_otg_rdev), + "Failed to register usb otg regulator"); + + 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, -EPROBE_DEFER, + "Failed to register psy, ret=3D%ld", + PTR_ERR(chg->psy)); + + ret =3D devm_work_autocancel(dev, &chg->psy_work, psy_work_item); + if (ret) + return dev_err_probe(dev, ret, "Failed to initialize psy work"); + + 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"); + + ret =3D devm_add_action_or_reset(dev, max_tcpci_unregister_psy_notifier, + &chg->nb); + if (ret) + return ret; + + ret =3D max77759_init_irqhandler(chg); + if (ret) + return dev_err_probe(dev, ret, + "Unable to initialize irq handler"); + return 0; +} + +static const struct of_device_id max77759_charger_ids[] =3D { + { .compatible =3D "maxim,max77759-charger", }, + { }, +}; +MODULE_DEVICE_TABLE(of, max77759_charger_ids); + +static struct platform_driver max77759_charger_driver =3D { + .driver =3D { + .name =3D "max77759-charger", + .of_match_table =3D max77759_charger_ids, + }, + .probe =3D max77759_charger_probe, +}; +module_platform_driver(max77759_charger_driver); + +MODULE_AUTHOR("Amit Sunil Dhamne "); +MODULE_DESCRIPTION("Maxim MAX77759 charger driver"); +MODULE_LICENSE("GPL"); --=20 2.52.0.rc2.455.g230fcf2819-goog From nobody Tue Dec 2 01:05:42 2025 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 2CBE02C21EB; Sun, 23 Nov 2025 08:36:24 +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=1763886985; cv=none; b=rx1Y5j4CWy1qAzmN7YVHx4JaB1YBPTBPfN8ClV4txWoRZ7qyfdynrb5gn+nK8zHhHUpEnyyLGvqynoUPFHZ03mIuLELYh0ST+Htw4LF5rk1K4tm0EAuCMdI+UdDaQorecBz8f2rvqpKrpKAB7+zHvpZTw4VYir9uC6A2JTadDeo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763886985; c=relaxed/simple; bh=NSXCge/2gK6HdCYnUhX0JsiC+V4/sPRuifzpNu302Ko=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=PHxk0WO0bn2Lf6FKwW9xT6n9Zo+BzXAnhpOloTW1b2ucy9R4ZokIuKb9ccd8jdiVtr+tca4jHVj0vpwZkIDYq5vHL4ap7WoUs8mZol5wCW4us6Oj/7TtJ2wMWosyApc4X61AcxB+9qvV12x3u8MIyPlyR2Al6MATQiV9wrHnGZU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=MDDOfLXj; 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="MDDOfLXj" Received: by smtp.kernel.org (Postfix) with ESMTPS id BAC6BC2BC87; Sun, 23 Nov 2025 08:36:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1763886984; bh=NSXCge/2gK6HdCYnUhX0JsiC+V4/sPRuifzpNu302Ko=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=MDDOfLXjbmK38iMwtpv6T+bQBMaPpsLpgMksu5fELVHyZ820IvLrQnw+PZH0wa83y wnb2Ykq+mVTRaPXV9J2FpJDH2S6FWJQ42WWb1CWRq5NdkM7nVCiDLHOOYzk30KY3m5 CPCcikTJO8F8Qg1e18utO4Xvk5dSYfgGVpm4hNnNEhdtQL7YY/96vbfMGEaqzsbmGA 3gsSackEVWpGLUrbFdWOdXM4ZXXiv/O44vEvMHsVm4309As/yAtJcSfDbkwCFQAyEa iGDlczPC2/iDwa/LX3sFRS7ArN4IqpnojB7LbMlzF+JA6y0ql2z4ASyobZKg/bJyDH WPX44rAYqnPxA== 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 AE24DCFA46B; Sun, 23 Nov 2025 08:36:24 +0000 (UTC) From: Amit Sunil Dhamne via B4 Relay Date: Sun, 23 Nov 2025 08:35:53 +0000 Subject: [PATCH 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: <20251123-max77759-charger-v1-6-6b2e4b8f7f54@google.com> References: <20251123-max77759-charger-v1-0-6b2e4b8f7f54@google.com> In-Reply-To: <20251123-max77759-charger-v1-0-6b2e4b8f7f54@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 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=1763886983; l=3355; i=amitsd@google.com; s=20241031; h=from:subject:message-id; bh=/TCo7ex1368Y86Fyq12+zxO0JMAaguRjxNQAlVy2Xs4=; b=AbMrYbmLH+QdUL9CL7s7kJK/2G1npTiYCzh32EVJI3e7OLGe8+jBNNLdNv4i9tXM4szINi7cR 4GPEFAgPppFBIjWh14daHEhdhLZRZLO/6tuefrflLnuJBp85smrtfj/ 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 set OTG Boost mode. Signed-off-by: Amit Sunil Dhamne --- drivers/usb/typec/tcpm/tcpci_maxim.h | 1 + drivers/usb/typec/tcpm/tcpci_maxim_core.c | 48 +++++++++++++++++++++------= ---- 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/drivers/usb/typec/tcpm/tcpci_maxim.h b/drivers/usb/typec/tcpm/= tcpci_maxim.h index b33540a42a95..6c82a61efe46 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 *otg_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..6d819a762fa1 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 @@ -202,32 +203,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_otg_regulator_handle(struct max_tcpci_chip *chip) +{ + if (IS_ERR_OR_NULL(chip->otg_reg)) { + chip->otg_reg =3D devm_regulator_get_exclusive(chip->dev, + "otg-vbus"); + if (IS_ERR_OR_NULL(chip->otg_reg)) { + dev_err(chip->dev, + "Failed to get otg regulator handle"); + 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_otg_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->otg_reg)) + ret =3D regulator_enable(chip->otg_reg); + } else { + if (regulator_is_enabled(chip->otg_reg)) + ret =3D regulator_disable(chip->otg_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.52.0.rc2.455.g230fcf2819-goog