From patchwork Fri Aug 5 07:05:58 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: ChiaEn Wu X-Patchwork-Id: 12936941 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 55286C00140 for ; Fri, 5 Aug 2022 07:07:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=u10vAEHFFPV+m/GXeBz2tZsyM176ncPweeKXNtbzC90=; b=I8EEG1tiopl1545vkJcgv6t0RG Y3ExtIURrNTeIMwrWKwlKZeHU/Wzmkx0bPFvqJtMmhgQTa+hcKlYW9B2wOWmucYQ5Lb9MRZoYYYm4 J/WvQiPwTACL3HkGPXLIDfeRhp2K7jl+JfjkpPULiKyWmMcPSFXHmJn9ZHI9of+rgxaSa38WCvEjx PaS/OWGFsbxlr8AWvPq311GMYnOZr7k/c0d6s/3F8RYbkLlIRTwfp0M8yR+GAGTLDhgvOrrrGAQ7q Xr4QA+p/WUbX2Lqe3YfSS3DJLvPhCyRpCO8Qvd7VWO2SIX0nvuLP72Zt5P/WQMkfnFSNQnW5Qq/wj BYhxY+Tw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1oJrQw-00Chaj-TZ; Fri, 05 Aug 2022 07:07:47 +0000 Received: from mail-pj1-x1029.google.com ([2607:f8b0:4864:20::1029]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1oJrPp-00CgrT-CB; Fri, 05 Aug 2022 07:06:38 +0000 Received: by mail-pj1-x1029.google.com with SMTP id x2-20020a17090ab00200b001f4da5cdc9cso7497593pjq.0; Fri, 05 Aug 2022 00:06:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc; bh=u10vAEHFFPV+m/GXeBz2tZsyM176ncPweeKXNtbzC90=; b=lpYlKFaodSrlaln8lz1dUNOI4lQWvJ+cRzzDOYyx7EI8KlAYjZuIitS6HOEUQ55W5f PWtVd6lpKNqO8UwhiTfFWePr3eWySMaJkxBCEYByfZwBKNfy0B1tZ1tF6vY6HRslE4bY smKZ+gY3X3WRx2FXUfAq/ekAOdKBFxwUleaomuQRLg6mMBQkLAeGYUi+ihaAc60ujJja 3qnW8ixtVDSQ8kBKInU/9OJEZj1PRzkU1v+db2Tuizs6WFlkTzLHc4CuqYn3oXAYRsoE MdETGC8tm2553zWhLzOHMWW8CN4c0t1kiT9g2SbHHeWr/92Zyn/6Ulnm0EClXMiT7iSg 3fIA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc; bh=u10vAEHFFPV+m/GXeBz2tZsyM176ncPweeKXNtbzC90=; b=Yzq5m1OswhnMxpz8HCdhm8jwWKINmRS3VTqDW7ewjy6kfe37E4uTc9OynuEtUsYQt6 /6vbzDQX1Lbx7ykLZAqI8hFZZ9KD0miVr3jTF8KZI2CO6tdX5wIo+LFqbSXGVTuRVjyB DY9SeovSM47/xO54qmPN1/TIB8AM29xzjXR9JOiD9pcKHqQ3VId8QwUOlibcysy0MgQ2 Wk0iKlzyhlBQ89HmjKWxkiupbMd8hbQWzxE67xcvzG8TcqCAX3k+dIyYq0R4396Wokwx vLR+u6vXUbxv2h9lJBm/I91iFBo2QT1BTJKRygrNpRGv47BSbhKu9ZNsc01lZJHZn2V9 9EoQ== X-Gm-Message-State: ACgBeo13riVovl18CqMTsemyt14S37FavQBDRjA6wU4N/gLDpXiagvAT 8LNDX6BA7S+bRCk4m61I3dE= X-Google-Smtp-Source: AA6agR6uOX2JJQosvwhOiZcfULuJgPT1rgt3CEKqJiZbC5XzNWkHdOg8QcgsZu7eNgGXLbciVCi0Iw== X-Received: by 2002:a17:903:11d2:b0:167:8a0f:8d4b with SMTP id q18-20020a17090311d200b001678a0f8d4bmr5573656plh.78.1659683194207; Fri, 05 Aug 2022 00:06:34 -0700 (PDT) Received: from RD-3580-24288.rt.l (42-72-229-62.emome-ip.hinet.net. [42.72.229.62]) by smtp.gmail.com with ESMTPSA id i5-20020a056a00224500b00525343b5047sm2191616pfu.76.2022.08.05.00.06.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 05 Aug 2022 00:06:33 -0700 (PDT) From: ChiaEn Wu To: lee.jones@linaro.org, daniel.thompson@linaro.org, jingoohan1@gmail.com, pavel@ucw.cz, robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, matthias.bgg@gmail.com, sre@kernel.org, chunfeng.yun@mediatek.com, gregkh@linuxfoundation.org, jic23@kernel.org, lars@metafoo.de, lgirdwood@gmail.com, broonie@kernel.org, linux@roeck-us.net, heikki.krogerus@linux.intel.com, deller@gmx.de, andy.shevchenko@gmail.com Cc: chiaen_wu@richtek.com, alice_chen@richtek.com, cy_huang@richtek.com, dri-devel@lists.freedesktop.org, linux-leds@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, linux-usb@vger.kernel.org, linux-iio@vger.kernel.org, linux-fbdev@vger.kernel.org, szunichen@gmail.com, Krzysztof Kozlowski Subject: [PATCH v7 01/13] dt-bindings: usb: Add MediaTek MT6370 TCPC Date: Fri, 5 Aug 2022 15:05:58 +0800 Message-Id: <20220805070610.3516-2-peterwu.pub@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220805070610.3516-1-peterwu.pub@gmail.com> References: <20220805070610.3516-1-peterwu.pub@gmail.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220805_000637_482283_BEE189D5 X-CRM114-Status: GOOD ( 10.93 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org From: ChiYuan Huang Add MediaTek MT6370 TCPC binding documentation. Reviewed-by: Krzysztof Kozlowski Signed-off-by: ChiYuan Huang Signed-off-by: ChiaEn Wu --- .../bindings/usb/mediatek,mt6370-tcpc.yaml | 36 ++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 Documentation/devicetree/bindings/usb/mediatek,mt6370-tcpc.yaml diff --git a/Documentation/devicetree/bindings/usb/mediatek,mt6370-tcpc.yaml b/Documentation/devicetree/bindings/usb/mediatek,mt6370-tcpc.yaml new file mode 100644 index 0000000..72f56cc --- /dev/null +++ b/Documentation/devicetree/bindings/usb/mediatek,mt6370-tcpc.yaml @@ -0,0 +1,36 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/usb/mediatek,mt6370-tcpc.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: MediatTek MT6370 Type-C Port Switch and Power Delivery controller + +maintainers: + - ChiYuan Huang + +description: | + MediaTek MT6370 is a multi-functional device. + It integrates charger, ADC, flash, RGB indicators, + regulators (DSV/VIBLDO), and TypeC Port Switch with Power Delivery controller. + This document only describes MT6370 Type-C Port Switch and + Power Delivery controller. + +properties: + compatible: + enum: + - mediatek,mt6370-tcpc + + interrupts: + maxItems: 1 + + connector: + type: object + $ref: /schemas/connector/usb-connector.yaml# + unevaluatedProperties: false + +additionalProperties: false + +required: + - compatible + - interrupts From patchwork Fri Aug 5 07:05:59 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: ChiaEn Wu X-Patchwork-Id: 12936942 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 2300CC00140 for ; Fri, 5 Aug 2022 07:08:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=pmhuNMasJsnu7yKY0wuXEG96SXA8koMOiIgc3LgLhpU=; b=MajSHScoe6/FSVQSjrlnn9iQIl B62l7oty6jxf+sG3faYa+m+INnDsNjsixYnlaEyO+8qvDttVybN71gtvOqZmFtHUBb0b/uzuUg0Hr 4/Dw523YmTfPz3UXTajCT3Xx1gqIPHd2E0AdulvCz3dPXF9ON/F1Y05LaWz7hn3tFBuSe6Qr0RWPU rhfJqMG0dk36/wm6CwIqERwkvDFAvFAO1AGDLqxJo8WTprajYEnU+SgeqhPEAbmYNaGDzXJDd2pYV UE4GHxJbO4ZZnxc7JOCNQzhkJsqE+3ucxF3eVrvGg2GyrZYpdriPUgICikJLYNfamR45fzS7jDfAQ n+T9J/xg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1oJrRk-00Chzr-AK; Fri, 05 Aug 2022 07:08:36 +0000 Received: from mail-pf1-x429.google.com ([2607:f8b0:4864:20::429]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1oJrPu-00CgxP-QS; Fri, 05 Aug 2022 07:06:44 +0000 Received: by mail-pf1-x429.google.com with SMTP id 17so1558913pfy.0; Fri, 05 Aug 2022 00:06:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc; bh=pmhuNMasJsnu7yKY0wuXEG96SXA8koMOiIgc3LgLhpU=; b=nUlwmtCvyVIkUwCwb6FYP3vJvjibV6gtLqk5691mn09kCOpvxtqcf/X3aaqPq73n0h gfoTh4fmoixiCbHkxMuoru52yn+aL/1ZAiIQwoDo6BWxGhVoHixErdA3g4OfzgSkst3S hVp2R5uSGPZOF8lJwF2xzlIQSWrhGUTn50GXDFou46aamCYgQtT2/EBmjeI1qT21RK/Q iqrfyIBzuzVRfeKzTzioJhdCgFbgYNGMUWjgbAyXRL/KL1le2J2T0z5AyqfHnF9AvZvJ B7QTSNRJBWT0zTCK7Mv1KF0s9s97xGZinY28RGBwMN5oLSm/FoTO+Ku8vQ5rFJRdzeK9 7+Kw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc; bh=pmhuNMasJsnu7yKY0wuXEG96SXA8koMOiIgc3LgLhpU=; b=a4Y9/g8dQPlQO+oYFlYj3mpfNIzP2zgQbFp/B7SgFG6fv6x9bqncu3gAE9rUjAcH8H CJdGwUPSxiRJd/csG4wNOfumB382vTKqQck4ZbWjdFpCuZEcF+2c6wBHjHJ4p0a9kx/F OyAch53hmZCQ1NyomCvh3qr0FI+PIo7w8xtAopF0H64aodYBVPhdIf0ef3vkO+/Eebg5 OcP31QPNS7CZxrHXTEiAJcN74tQ7mv2lm0uRcHTO2j+Cv9gtgmna4c9CKUew4m7NV8e6 LgjkZ9Wcn00OPm0VKFcKpTpdXjXGHpnhNNQR4vQIC7cCYpTC9256B9IY8jOAzTvIcdUu kaVA== X-Gm-Message-State: ACgBeo3RjAmyRqGW7oFM7WsY0YULwxjp138ozioS4YCepWaJAXm0mtxt VBE3iY9rD10fr0tlMg2ALX8= X-Google-Smtp-Source: AA6agR6VhklBvSJn5TuPSCr+CU65YQsvP3bd0sBs9mhahisDn9MbyeQJH4+Lgy3EsUMzfnMT/INjcw== X-Received: by 2002:a05:6a00:1709:b0:52e:677b:702b with SMTP id h9-20020a056a00170900b0052e677b702bmr5696757pfc.19.1659683201418; Fri, 05 Aug 2022 00:06:41 -0700 (PDT) Received: from RD-3580-24288.rt.l (42-72-229-62.emome-ip.hinet.net. [42.72.229.62]) by smtp.gmail.com with ESMTPSA id i5-20020a056a00224500b00525343b5047sm2191616pfu.76.2022.08.05.00.06.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 05 Aug 2022 00:06:41 -0700 (PDT) From: ChiaEn Wu To: lee.jones@linaro.org, daniel.thompson@linaro.org, jingoohan1@gmail.com, pavel@ucw.cz, robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, matthias.bgg@gmail.com, sre@kernel.org, chunfeng.yun@mediatek.com, gregkh@linuxfoundation.org, jic23@kernel.org, lars@metafoo.de, lgirdwood@gmail.com, broonie@kernel.org, linux@roeck-us.net, heikki.krogerus@linux.intel.com, deller@gmx.de, andy.shevchenko@gmail.com Cc: chiaen_wu@richtek.com, alice_chen@richtek.com, cy_huang@richtek.com, dri-devel@lists.freedesktop.org, linux-leds@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, linux-usb@vger.kernel.org, linux-iio@vger.kernel.org, linux-fbdev@vger.kernel.org, szunichen@gmail.com, Krzysztof Kozlowski Subject: [PATCH v7 02/13] dt-bindings: power: supply: Add MediaTek MT6370 Charger Date: Fri, 5 Aug 2022 15:05:59 +0800 Message-Id: <20220805070610.3516-3-peterwu.pub@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220805070610.3516-1-peterwu.pub@gmail.com> References: <20220805070610.3516-1-peterwu.pub@gmail.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220805_000642_912858_ACC7DA84 X-CRM114-Status: GOOD ( 12.01 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org From: ChiaEn Wu Add MediaTek MT6370 Charger binding documentation. Reviewed-by: Krzysztof Kozlowski Signed-off-by: ChiaEn Wu --- .../power/supply/mediatek,mt6370-charger.yaml | 88 ++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 Documentation/devicetree/bindings/power/supply/mediatek,mt6370-charger.yaml diff --git a/Documentation/devicetree/bindings/power/supply/mediatek,mt6370-charger.yaml b/Documentation/devicetree/bindings/power/supply/mediatek,mt6370-charger.yaml new file mode 100644 index 0000000..bd09a0a --- /dev/null +++ b/Documentation/devicetree/bindings/power/supply/mediatek,mt6370-charger.yaml @@ -0,0 +1,88 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/power/supply/mediatek,mt6370-charger.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: MediaTek MT6370 Battery Charger + +maintainers: + - ChiaEn Wu + +description: | + This module is part of the MT6370 MFD device. + Provides Battery Charger, Boost for OTG devices and BC1.2 detection. + +properties: + compatible: + const: mediatek,mt6370-charger + + interrupts: + description: | + Specify what irqs are needed to be handled by MT6370 Charger driver. IRQ + "MT6370_IRQ_CHG_MIVR", "MT6370_IRQ_ATTACH" and "MT6370_IRQ_OVPCTRL_UVP_D" + are required. + items: + - description: BC1.2 done irq + - description: usb plug in irq + - description: mivr irq + + interrupt-names: + items: + - const: attach_i + - const: uvp_d_evt + - const: mivr + + io-channels: + description: | + Use ADC channel to read VBUS, IBUS, IBAT, etc., info. + minItems: 1 + items: + - description: | + VBUS voltage with lower accuracy (+-75mV) but higher measure + range (1~22V) + - description: | + VBUS voltage with higher accuracy (+-30mV) but lower measure + range (1~9.76V) + - description: the main system input voltage + - description: battery voltage + - description: battery temperature-sense input voltage + - description: IBUS current (required) + - description: battery current + - description: | + regulated output voltage to supply for the PWM low-side gate driver + and the bootstrap capacitor + - description: IC junction temperature + + io-channel-names: + minItems: 1 + items: + - const: vbusdiv5 + - const: vbusdiv2 + - const: vsys + - const: vbat + - const: ts_bat + - const: ibus + - const: ibat + - const: chg_vddp + - const: temp_jc + + usb-otg-vbus-regulator: + type: object + description: OTG boost regulator. + unevaluatedProperties: false + $ref: /schemas/regulator/regulator.yaml# + + properties: + enable-gpios: + maxItems: 1 + +required: + - compatible + - interrupts + - interrupt-names + - io-channels + +additionalProperties: false + +... From patchwork Fri Aug 5 07:06:00 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: ChiaEn Wu X-Patchwork-Id: 12936943 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 3BA68C00140 for ; Fri, 5 Aug 2022 07:09:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=XZRFVxasDVXXPTfv/lGT5hPcHgNLG3wH8AQQYSGVOn0=; b=U1pR1oohMTkBomulucaoMwsTim V78LdxdLeMtoRTmUryh1ZF+wAqmFlioN06VWVydii+uGurpDNL72a8jpigTD6pk2wH7CDg6UPwg34 i2cIEvbPqE9H5FmJ1tm9w8h6uyklFMt/xsvIHEWd7hSkejiO1rXlpKcJzziV0hx2FNoYDHtLSkdJZ 2Tn/V5SMa/J4Pkj0MEVToXgRigfg9NeVr4dXbOfZab7QbuxDoMiTgc4upd5zFTXrMccA9BoKJMAzW 6+KpxOw+MVJOV0TRVgyW9g7CDzoDCJ19iokDWi/DTo53V6vtxHPpFLzUsqRZ8PsG6lhnJh8pBvZPM iz2x3mZg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1oJrSC-00CiHJ-E7; Fri, 05 Aug 2022 07:09:04 +0000 Received: from mail-pl1-x636.google.com ([2607:f8b0:4864:20::636]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1oJrQ7-00Ch27-Hj; Fri, 05 Aug 2022 07:06:57 +0000 Received: by mail-pl1-x636.google.com with SMTP id x10so1908703plb.3; Fri, 05 Aug 2022 00:06:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc; bh=XZRFVxasDVXXPTfv/lGT5hPcHgNLG3wH8AQQYSGVOn0=; b=gaurTMxUlwEhrVMybVRK+Y2mqgitmjhaNHaV8u4G/7lgdrULPEa6++uuBXU3DoXK3w NkhVMwDRYlZU2XlF8ccBcuLa+qlYDpUpaCYmVqJfK+8+Ol+T0QWUhEllsNnzP+/4x7ir 6meZx03mjHv5SAAWedGqQMrP7RqqyU+nQDXdeXvupowxN++UvImLVPZYwT/f73866CeM s66+mkhRe/Z3OUCzSiWiHjggTvYozjYg69aajTeQKjX3q8BBAc5Qr1/Mv9784dAczKHK zNrHBOi2F8rfWAIzllurUcBURETAOFVPwQLpzBQu++HAcCKorYwJ0uqrOch35mn0S4Sm fV+w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc; bh=XZRFVxasDVXXPTfv/lGT5hPcHgNLG3wH8AQQYSGVOn0=; b=t7YECoKv2g43cf7GBwCDM7JMhJCWJSM1Iy/ZM23CwDiVaDkHW3wkBVCyOzn2Mfs3Nc mxWz3VtZ7hsgewo8pQqILJeoOo7k2aE5sc8qtfytc/3Jg2+7YrVqX7LYCGGfmfTLn4ne Av23cxQZWjpQRrYX0vdmFogE3koLXbMdh2EwU5fouVyZgGPXo8z0jXSLaKEsX5+aFez5 MJh5rhAP7EZ70nCnoxElqqFX2PaDiHs+j2IaG7JZp3dJpEyJw0uHmVHeYg38NmjJreNh MMKeLRCQbLpTdtZvLP8rf4Un5JaSR/0pcKb+CgAnwo0yzHPp9W1rA55wFnlE/2MS5eAw YZWQ== X-Gm-Message-State: ACgBeo3kJhxdHiHgqooucVQyNy+nk0rA6Yh3jyxXYfKrdpdXBvJf+3RT x2iRiH4RqLXvBk0Bge44ne0= X-Google-Smtp-Source: AA6agR69JNirhMZg0pIILXPN55zHDUHG+8kr2E0OgDZ2KcU3fs5VHlPXF4oYXepFdubBURh054sXuQ== X-Received: by 2002:a17:903:449:b0:16d:d781:313a with SMTP id iw9-20020a170903044900b0016dd781313amr5599211plb.75.1659683209089; Fri, 05 Aug 2022 00:06:49 -0700 (PDT) Received: from RD-3580-24288.rt.l (42-72-229-62.emome-ip.hinet.net. [42.72.229.62]) by smtp.gmail.com with ESMTPSA id i5-20020a056a00224500b00525343b5047sm2191616pfu.76.2022.08.05.00.06.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 05 Aug 2022 00:06:48 -0700 (PDT) From: ChiaEn Wu To: lee.jones@linaro.org, daniel.thompson@linaro.org, jingoohan1@gmail.com, pavel@ucw.cz, robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, matthias.bgg@gmail.com, sre@kernel.org, chunfeng.yun@mediatek.com, gregkh@linuxfoundation.org, jic23@kernel.org, lars@metafoo.de, lgirdwood@gmail.com, broonie@kernel.org, linux@roeck-us.net, heikki.krogerus@linux.intel.com, deller@gmx.de, andy.shevchenko@gmail.com Cc: chiaen_wu@richtek.com, alice_chen@richtek.com, cy_huang@richtek.com, dri-devel@lists.freedesktop.org, linux-leds@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, linux-usb@vger.kernel.org, linux-iio@vger.kernel.org, linux-fbdev@vger.kernel.org, szunichen@gmail.com, Krzysztof Kozlowski Subject: [PATCH v7 03/13] dt-bindings: leds: mt6370: Add MediaTek MT6370 current sink type LED indicator Date: Fri, 5 Aug 2022 15:06:00 +0800 Message-Id: <20220805070610.3516-4-peterwu.pub@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220805070610.3516-1-peterwu.pub@gmail.com> References: <20220805070610.3516-1-peterwu.pub@gmail.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220805_000655_637369_23E303FC X-CRM114-Status: GOOD ( 11.06 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org From: ChiYuan Huang Add MediaTek MT6370 current sink type LED indicator binding documentation. Reviewed-by: Krzysztof Kozlowski Signed-off-by: ChiYuan Huang Signed-off-by: ChiaEn Wu --- .../bindings/leds/mediatek,mt6370-indicator.yaml | 81 ++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 Documentation/devicetree/bindings/leds/mediatek,mt6370-indicator.yaml diff --git a/Documentation/devicetree/bindings/leds/mediatek,mt6370-indicator.yaml b/Documentation/devicetree/bindings/leds/mediatek,mt6370-indicator.yaml new file mode 100644 index 0000000..204b103 --- /dev/null +++ b/Documentation/devicetree/bindings/leds/mediatek,mt6370-indicator.yaml @@ -0,0 +1,81 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/leds/mediatek,mt6370-indicator.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: LED driver for MT6370 PMIC from MediaTek Integrated. + +maintainers: + - Alice Chen + +description: | + This module is part of the MT6370 MFD device. + Add MT6370 LED driver include 4-channel RGB LED support Register/PWM/Breath Mode + +allOf: + - $ref: leds-class-multicolor.yaml# + +properties: + compatible: + const: mediatek,mt6370-indicator + + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + +patternProperties: + "^multi-led@[0-3]$": + type: object + + properties: + reg: + enum: [0, 1, 2, 3] + + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + + patternProperties: + "^led@[0-2]$": + type: object + $ref: common.yaml# + unevaluatedProperties: false + + properties: + reg: + enum: [0, 1, 2] + + required: + - reg + - color + + required: + - reg + - color + - "#address-cells" + - "#size-cells" + + "^led@[0-3]$": + type: object + $ref: common.yaml# + unevaluatedProperties: false + + properties: + reg: + enum: [0, 1, 2, 3] + + required: + - reg + - color + +required: + - compatible + - "#address-cells" + - "#size-cells" + +additionalProperties: false From patchwork Fri Aug 5 07:06:01 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: ChiaEn Wu X-Patchwork-Id: 12936944 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 41BB3C25B08 for ; Fri, 5 Aug 2022 07:09:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=CX/0guoh/DjN4wN8JJoOSTPFmeqM5+Xm+kwBd/9d3Ho=; b=ba6B5Joeq5XVKWVohvNYXZx++T PT9lPPX1WSeYGWaBF0kXcaEa695eFd9uxqnL8C3/zuRrmXo18+saOEuZEmrFfRiybsQcSdWVLRMN1 grhabR2jixj50ToTRkJwKZ9KzzNz1Jm/1G0vTp2jVmjppUW3I/FfJpP0TyA8Fi9f0JkxxxSBaOXV0 y9wumUmXdoOwsUpwu3TkARD1b7QfGoyhxD7d5DOtnl2/j5/0amfwkuahtT4ZB09D6Y5Q/vkskGGdg /fmGW5Q2o6r3Pvwssx3jHAR11C3rsFUnSRy2hJ5fvJdfz3tr3xSfFehzhDaBB5NhFD8Kc9vz25+2A x4adeZjw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1oJrSr-00Cige-T3; Fri, 05 Aug 2022 07:09:45 +0000 Received: from mail-pg1-x533.google.com ([2607:f8b0:4864:20::533]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1oJrQB-00Ch5w-IV; Fri, 05 Aug 2022 07:07:02 +0000 Received: by mail-pg1-x533.google.com with SMTP id f65so1921433pgc.12; Fri, 05 Aug 2022 00:06:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc; bh=CX/0guoh/DjN4wN8JJoOSTPFmeqM5+Xm+kwBd/9d3Ho=; b=GbRQHYJWpxNJ5WAA2fCLZDXWImpw8oQErL6RHuLr1qgR3c7cz14qFaq1/bgXHrJcjG aKu4qpdD0z0YDXpWslStuuvY1rLpo8AEnM3CeLgueSF+WIXvcTIhywulOxwF1jM7h0io 6m80d+VHmLR9b3erIIgQlII6EX7Itibg98z4kGEJCQpfyOIfYsSa/dnOm5FjWjSzvFie XgKcW98VZGYkul0QX52UnIfS0LTAwyLZHmgP+jTlF/9dikRHy/3ouBR2tPOay0Lhx6oG isBNJnKmY9kSjYt6sCaunANsLS/R3XdAt7W/7euizUoulhqLNRBXOcRMGFdcLnWieIIW pO5g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc; bh=CX/0guoh/DjN4wN8JJoOSTPFmeqM5+Xm+kwBd/9d3Ho=; b=5iN/VX4BRqH14UnCBEBVZXGTXQq7elNgdtgzdSpCT3AYY1FFyDcFITVxJLUD0fkzQW MKFLKO0stHWk5nZ2uzm/yRyR/Um8l2KOcVcGO5WyLtx3fWkPqZZuI+RGfDDVucBznDIe P3c3ffYL1qGDs8lbgOxx+zThaPCmiQK+BGQiw/n1/0ndZ4Qvq/Bxoq5proRrJjrnAp7j e+QAQR0FcYhyhIP0yegO5IZU0x4U93MtWSYR5PBldskawGd7nYoOtVdVXoehPmMnjOUi kPeaCJ0P+wHiPvjd9qRFE4wvWyKdF/qKc5G7Lpd/gDPZhZM7a4Okd1vhY156iknL3i7U M3aw== X-Gm-Message-State: ACgBeo0SQ3gmT1DfthEz5wMJ+pNZqLKr/JcmejkcLcC+6EzyXvt4eGKp 5nubyi9rfp5Gsn9LVfGPk/U= X-Google-Smtp-Source: AA6agR6DJ/xGXIEp9/SiYGj8B5E5YJ/4TnNDD77+rwk4vvfdS9F22unZx+OW4+D1bIl8u5r1XbFyuw== X-Received: by 2002:a05:6a00:24c7:b0:52e:7181:a8a9 with SMTP id d7-20020a056a0024c700b0052e7181a8a9mr5495612pfv.78.1659683215955; Fri, 05 Aug 2022 00:06:55 -0700 (PDT) Received: from RD-3580-24288.rt.l (42-72-229-62.emome-ip.hinet.net. [42.72.229.62]) by smtp.gmail.com with ESMTPSA id i5-20020a056a00224500b00525343b5047sm2191616pfu.76.2022.08.05.00.06.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 05 Aug 2022 00:06:55 -0700 (PDT) From: ChiaEn Wu To: lee.jones@linaro.org, daniel.thompson@linaro.org, jingoohan1@gmail.com, pavel@ucw.cz, robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, matthias.bgg@gmail.com, sre@kernel.org, chunfeng.yun@mediatek.com, gregkh@linuxfoundation.org, jic23@kernel.org, lars@metafoo.de, lgirdwood@gmail.com, broonie@kernel.org, linux@roeck-us.net, heikki.krogerus@linux.intel.com, deller@gmx.de, andy.shevchenko@gmail.com Cc: chiaen_wu@richtek.com, alice_chen@richtek.com, cy_huang@richtek.com, dri-devel@lists.freedesktop.org, linux-leds@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, linux-usb@vger.kernel.org, linux-iio@vger.kernel.org, linux-fbdev@vger.kernel.org, szunichen@gmail.com, Krzysztof Kozlowski Subject: [PATCH v7 04/13] dt-bindings: leds: Add MediaTek MT6370 flashlight Date: Fri, 5 Aug 2022 15:06:01 +0800 Message-Id: <20220805070610.3516-5-peterwu.pub@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220805070610.3516-1-peterwu.pub@gmail.com> References: <20220805070610.3516-1-peterwu.pub@gmail.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220805_000659_652318_17083774 X-CRM114-Status: GOOD ( 11.26 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org From: Alice Chen Add MediaTek MT6370 flashlight binding documentation. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Alice Chen Signed-off-by: ChiaEn Wu --- .../bindings/leds/mediatek,mt6370-flashlight.yaml | 41 ++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 Documentation/devicetree/bindings/leds/mediatek,mt6370-flashlight.yaml diff --git a/Documentation/devicetree/bindings/leds/mediatek,mt6370-flashlight.yaml b/Documentation/devicetree/bindings/leds/mediatek,mt6370-flashlight.yaml new file mode 100644 index 0000000..e9d02ed --- /dev/null +++ b/Documentation/devicetree/bindings/leds/mediatek,mt6370-flashlight.yaml @@ -0,0 +1,41 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/leds/mediatek,mt6370-flashlight.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Flash LED driver for MT6370 PMIC from MediaTek Integrated. + +maintainers: + - Alice Chen + +description: | + This module is part of the MT6370 MFD device. + Add MT6370 flash LED driver include 2-channel flash LED support Torch/Strobe Mode. + +properties: + compatible: + const: mediatek,mt6370-flashlight + + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + +patternProperties: + "^led@[0-1]$": + type: object + $ref: common.yaml# + unevaluatedProperties: false + + properties: + reg: + enum: [0, 1] + +required: + - compatible + - "#address-cells" + - "#size-cells" + +additionalProperties: false From patchwork Fri Aug 5 07:06:02 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: ChiaEn Wu X-Patchwork-Id: 12936945 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 83565C00140 for ; Fri, 5 Aug 2022 07:10:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=qeopJMMMGQSOM0makhnpPexR2tcMVpSaueKhDF363vc=; b=5AMx1p6hW1P4K/hrhoMDW3l2OH P8G3M8mgRVJ6lGJuMwgd3k08/11Wt0tOKNpM567S97u3uHUafFui4nPvORIj/u29eftM4tT9n/mXh 7CeVblUgiXXLf1F4IluMDCSYCULXkeC60xC2ChXq4xz4lGBcCTAfAg0VXJpiThtvGBIQ96zF8wRNU VfIF/TLKEhcNTiqxCYzCCh6etVAbCdUNyF131bD8P7vR6lindlm5bnsKnH5nQDT7SsKqqu6RL4xLe 249hQWpIL2aK0eI3GNwjsXl9W9ok51qwv1jqPPx4HzrUu7Qn8rQBn3IC5SZWZTP7tsxNrpAqMW2N0 /3dIknFQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1oJrTN-00Ciyx-Q1; Fri, 05 Aug 2022 07:10:17 +0000 Received: from mail-pg1-x535.google.com ([2607:f8b0:4864:20::535]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1oJrQK-00ChAu-Qu; Fri, 05 Aug 2022 07:07:10 +0000 Received: by mail-pg1-x535.google.com with SMTP id r186so1970060pgr.2; Fri, 05 Aug 2022 00:07:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc; bh=qeopJMMMGQSOM0makhnpPexR2tcMVpSaueKhDF363vc=; b=InwB0H0z7UJWx1xHOJC64Z4Kq8Ocdh/v3W/VRRB/TbDkixafeNdBDdpKacr0pCIRU8 j4R8m7lRV3mPaxFZvRp4z6mHXosKZIId+CyYyovhhD8wru0+AHnjANRuCx0X+96EBaaA sC/5pYw/OXnSDy7QuT3LC9G8ssdB8FbOwyMfllMcrovy7a09nEMEsZ4GtEUVxxift4uV xy3vxpy0nENJ4hSrGJ9LjvNM3tzwFrs9Wx3e1a1/YAVkjW76LpBluDW2IENsUjsvznfG n6y9msCnKBmAEYOlHbHJ6UGeQ1wlHztbnb5Res5lVaqFovHmmStPtcqurTo04HNSsSU/ nuAw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc; bh=qeopJMMMGQSOM0makhnpPexR2tcMVpSaueKhDF363vc=; b=x9LorKC4zqV/ZbOTkf6LwKo/uZ8Q9WP6M1jTYpzMmxS+TZqnVrb4ZDYtQuctGhRh4P yknrHGalcJDjBaxcw1xBPC8AJ9GBcj09SnkcnOtAu2bM+dHLgDqgyjnTAXoVQL5QXb01 x0lhSyorXf3fejXGvM8XQwasJ2fRrXEVZD4EXolE+etohd5jG/l5tqBIWxTNsBKM8j+O D/iCQafxPti7HyQUgJcaqpeAu+y1wGEmWQ2cRlI5yTcTYboT891GeRhqAn1gGHp9CNP4 85ZOPAMBDtN6C10ezicyURx1ptWdRY9VjHarRt/kh+7MDBnmeZDOBLQiDo2fOvwITNlS OG5g== X-Gm-Message-State: ACgBeo2ko2rc/b3F6Vl6F2EiUu8+BTDuGERsKJrMvyS8CjomxWNie+ZA YYyN01ymRxbXOsv/NiMqJ/A= X-Google-Smtp-Source: AA6agR4RCWr+OmHvsf5Vj3yHmct3WXBf4k9PSgUYPPdCQTG6FMOvaIn3j7K62RblsN/IOB1K4L4/Kw== X-Received: by 2002:a05:6a00:cc1:b0:52d:a29d:fb1 with SMTP id b1-20020a056a000cc100b0052da29d0fb1mr5663372pfv.56.1659683222769; Fri, 05 Aug 2022 00:07:02 -0700 (PDT) Received: from RD-3580-24288.rt.l (42-72-229-62.emome-ip.hinet.net. [42.72.229.62]) by smtp.gmail.com with ESMTPSA id i5-20020a056a00224500b00525343b5047sm2191616pfu.76.2022.08.05.00.06.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 05 Aug 2022 00:07:02 -0700 (PDT) From: ChiaEn Wu To: lee.jones@linaro.org, daniel.thompson@linaro.org, jingoohan1@gmail.com, pavel@ucw.cz, robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, matthias.bgg@gmail.com, sre@kernel.org, chunfeng.yun@mediatek.com, gregkh@linuxfoundation.org, jic23@kernel.org, lars@metafoo.de, lgirdwood@gmail.com, broonie@kernel.org, linux@roeck-us.net, heikki.krogerus@linux.intel.com, deller@gmx.de, andy.shevchenko@gmail.com Cc: chiaen_wu@richtek.com, alice_chen@richtek.com, cy_huang@richtek.com, dri-devel@lists.freedesktop.org, linux-leds@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, linux-usb@vger.kernel.org, linux-iio@vger.kernel.org, linux-fbdev@vger.kernel.org, szunichen@gmail.com, Rob Herring Subject: [PATCH v7 05/13] dt-bindings: backlight: Add MediaTek MT6370 backlight Date: Fri, 5 Aug 2022 15:06:02 +0800 Message-Id: <20220805070610.3516-6-peterwu.pub@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220805070610.3516-1-peterwu.pub@gmail.com> References: <20220805070610.3516-1-peterwu.pub@gmail.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220805_000708_995196_9BA39547 X-CRM114-Status: GOOD ( 14.20 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org From: ChiYuan Huang Add MT6370 backlight binding documentation. Reviewed-by: Rob Herring Signed-off-by: ChiYuan Huang Signed-off-by: ChiaEn Wu --- v7 - Add the second compatible string for 'mt6372' - Add 'mediatek,bled-exponential-mode-enable' property for enable the exponential mode of backlight brightness - Add validation for the maximum value of 'default-brightness' and 'max-brightness' --- .../leds/backlight/mediatek,mt6370-backlight.yaml | 121 +++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 Documentation/devicetree/bindings/leds/backlight/mediatek,mt6370-backlight.yaml diff --git a/Documentation/devicetree/bindings/leds/backlight/mediatek,mt6370-backlight.yaml b/Documentation/devicetree/bindings/leds/backlight/mediatek,mt6370-backlight.yaml new file mode 100644 index 0000000..5533b65 --- /dev/null +++ b/Documentation/devicetree/bindings/leds/backlight/mediatek,mt6370-backlight.yaml @@ -0,0 +1,121 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/leds/backlight/mediatek,mt6370-backlight.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: MediaTek MT6370 Backlight + +maintainers: + - ChiaEn Wu + +description: | + This module is part of the MT6370 MFD device. + The MT6370 Backlight WLED driver supports up to a 29V output voltage for + 4 channels of 8 series WLEDs. Each channel supports up to 30mA of current + capability with 2048 current steps (11 bits, only for MT6370/MT6371) or + 16384 current steps (14 bits, only for MT6372) in exponential or linear + mapping curves. + +allOf: + - $ref: common.yaml# + +properties: + compatible: + enum: + - mediatek,mt6370-backlight + - mediatek,mt6372-backlight + + default-brightness: + minimum: 0 + + max-brightness: + minimum: 0 + + enable-gpios: + description: External backlight 'enable' pin + maxItems: 1 + + mediatek,bled-pwm-enable: + description: | + Enable external PWM input for backlight dimming + type: boolean + + mediatek,bled-pwm-hys-enable: + description: | + Enable the backlight input-hysteresis for PWM mode + type: boolean + + mediatek,bled-pwm-hys-input-th-steps: + $ref: /schemas/types.yaml#/definitions/uint8 + enum: [1, 4, 16, 64] + description: | + The selection of the upper and lower bounds threshold of backlight + PWM resolution. If we choose selection 64, the variation of PWM + resolution needs more than 64 steps. + + mediatek,bled-ovp-shutdown: + description: | + Enable the backlight shutdown when OVP level triggered + type: boolean + + mediatek,bled-ovp-microvolt: + enum: [17000000, 21000000, 25000000, 29000000] + description: | + Backlight OVP level selection. + + mediatek,bled-ocp-shutdown: + description: | + Enable the backlight shutdown when OCP level triggerred. + type: boolean + + mediatek,bled-ocp-microamp: + enum: [900000, 1200000, 1500000, 1800000] + description: | + Backlight OC level selection. + + mediatek,bled-exponential-mode-enable: + description: | + Enable the exponential mode of backlight brightness. If this property + is not enabled, the default is to use linear mode. + type: boolean + + mediatek,bled-channel-use: + $ref: /schemas/types.yaml#/definitions/uint8 + description: | + Backlight LED channel to be used. + Each bit mapping to: + - 0: CH4 + - 1: CH3 + - 2: CH2 + - 3: CH1 + minimum: 1 + maximum: 15 + +if: + properties: + compatible: + contains: + const: mediatek,mt6372-backlight + +then: + properties: + default-brightness: + maximum: 16384 + + max-brightness: + maximum: 16384 + +else: + properties: + default-brightness: + maximum: 2048 + + max-brightness: + maximum: 2048 + +required: + - compatible + - mediatek,bled-channel-use + +additionalProperties: false From patchwork Fri Aug 5 07:06:03 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: ChiaEn Wu X-Patchwork-Id: 12936946 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 89C25C00140 for ; Fri, 5 Aug 2022 07:11:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=X+1p8Vs8tx/jVm1av3GnvFEpJSM9wBL0GmPT+mI4Y5s=; b=1AQ+FfyUscSQg7oV/WUhFOuOni JaY/7xaAUnwiauW2eBeGfrE71wLmQSlNYdTmY7Zocxzx3v5UUFSTfdvN8/ciQNCM8Us9KQaDwipMF YjQi4VgLLStKZxHGtQYm8TawmNzXR91fx0fqqKvHM8n4eUzTNvEqTAoGY+/sTyww4xS4VbY4t1Hjv s25nHwula0MzlrWdo4x0c/Zy79RnLjBNFk5zL7iVrxvqrFG0IYtViSxk74CJrrA4lySNLoU5NzfvH XUzH70TUx0zUtcvp38AuMg3vR+i+QZ9l2Y8xow8Kbgdrh3SYBhIaOjRD0aphmyApCt7pUuYmCqHX+ 5oHJjdmA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1oJrUI-00CjRY-Ld; Fri, 05 Aug 2022 07:11:14 +0000 Received: from mail-pl1-x62e.google.com ([2607:f8b0:4864:20::62e]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1oJrQP-00ChGg-9y; Fri, 05 Aug 2022 07:07:16 +0000 Received: by mail-pl1-x62e.google.com with SMTP id iw1so1898714plb.6; Fri, 05 Aug 2022 00:07:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc; bh=X+1p8Vs8tx/jVm1av3GnvFEpJSM9wBL0GmPT+mI4Y5s=; b=NIHb8Vu95awvqUMTo2/KvlyiTNJ7UzNeiU2V+lCOfMlgScn7x7Gw+ODY2xoZ+/kZI+ h1X0Squl4H9926iVMpcMmPLFXIn0tz0CK4MmBAYRVK1E7H2XaFcGVCh/FEza/Aujq2yu 08SQNdHEqI3G2YDxKHUKYY65p4AOKn11ri9Bmw0vEtSWQWq4kzvt32bbb/tKNEhpBpnL qwrdwuCtB753EhR0ywNnYegucMgOc9zxY2MAPRRqdCxvn7Uh1swGl8dMu+3kaEMKvKmK 1LXD/o1xN7iCraSxJb90wYux8CJmcg0+Bs+aM+0M+UhETrsdG9N0EbPufnyTqU54yrWC jOpQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc; bh=X+1p8Vs8tx/jVm1av3GnvFEpJSM9wBL0GmPT+mI4Y5s=; b=42/MvOvlKFCO2NIPTQYjAYQo55KPXj15GUhJK5qqaogKQlWTdtpVjSYXnIU+VUaG05 uWWcPN8m5X4HBelepVXil0i1dg6VvaR/hrLLSkB6i9a5pe649yj4qRMW9wan9Ze4jbnv W0eqqb3BGxuvgSqHVYOKOgU1qrshkuDdce3mzN4BWmiPqRxvoF20N/m7V0tTz+XSi0tD aFNoOe6lkVQaygxt6K0Qs4lvVRAc6I326eH8h8WhuHMruEF8W6bZK8VtF8c4YccMrx9M 7BtXQIz/CHrMGKsUcovjXIrGMFrOvaW9BAvE00QtdhYKoe/5790Cv4pqzpvyuE7dXlAl kmMA== X-Gm-Message-State: ACgBeo2a6qshiYFBuUMjk1rYtP5AXIuQAz7waHVO0zZrYcNnM7hcpSCr OpGx8Pwc1DJryLE7sesyIo0= X-Google-Smtp-Source: AA6agR6G0c2kdEwmzw6LnvUYbCgC1yPY+kZr/3B2/lEEPGNs4ClV7SHSDjQsyX3QjudsHcrAARTl5g== X-Received: by 2002:a17:90b:3511:b0:1f4:e0cd:1e04 with SMTP id ls17-20020a17090b351100b001f4e0cd1e04mr15011399pjb.154.1659683230545; Fri, 05 Aug 2022 00:07:10 -0700 (PDT) Received: from RD-3580-24288.rt.l (42-72-229-62.emome-ip.hinet.net. [42.72.229.62]) by smtp.gmail.com with ESMTPSA id i5-20020a056a00224500b00525343b5047sm2191616pfu.76.2022.08.05.00.07.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 05 Aug 2022 00:07:10 -0700 (PDT) From: ChiaEn Wu To: lee.jones@linaro.org, daniel.thompson@linaro.org, jingoohan1@gmail.com, pavel@ucw.cz, robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, matthias.bgg@gmail.com, sre@kernel.org, chunfeng.yun@mediatek.com, gregkh@linuxfoundation.org, jic23@kernel.org, lars@metafoo.de, lgirdwood@gmail.com, broonie@kernel.org, linux@roeck-us.net, heikki.krogerus@linux.intel.com, deller@gmx.de, andy.shevchenko@gmail.com Cc: chiaen_wu@richtek.com, alice_chen@richtek.com, cy_huang@richtek.com, dri-devel@lists.freedesktop.org, linux-leds@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, linux-usb@vger.kernel.org, linux-iio@vger.kernel.org, linux-fbdev@vger.kernel.org, szunichen@gmail.com, Krzysztof Kozlowski Subject: [PATCH v7 06/13] dt-bindings: mfd: Add MediaTek MT6370 Date: Fri, 5 Aug 2022 15:06:03 +0800 Message-Id: <20220805070610.3516-7-peterwu.pub@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220805070610.3516-1-peterwu.pub@gmail.com> References: <20220805070610.3516-1-peterwu.pub@gmail.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220805_000713_463062_11513750 X-CRM114-Status: GOOD ( 14.86 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org From: ChiYuan Huang Add MediaTek MT6370 binding documentation. Reviewed-by: Krzysztof Kozlowski Signed-off-by: ChiYuan Huang Signed-off-by: ChiaEn Wu --- .../devicetree/bindings/mfd/mediatek,mt6370.yaml | 280 +++++++++++++++++++++ include/dt-bindings/iio/adc/mediatek,mt6370_adc.h | 18 ++ 2 files changed, 298 insertions(+) create mode 100644 Documentation/devicetree/bindings/mfd/mediatek,mt6370.yaml create mode 100644 include/dt-bindings/iio/adc/mediatek,mt6370_adc.h diff --git a/Documentation/devicetree/bindings/mfd/mediatek,mt6370.yaml b/Documentation/devicetree/bindings/mfd/mediatek,mt6370.yaml new file mode 100644 index 0000000..410e2d4 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/mediatek,mt6370.yaml @@ -0,0 +1,280 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mfd/mediatek,mt6370.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: MediaTek MT6370 SubPMIC + +maintainers: + - ChiYuan Huang + +description: | + MT6370 is a highly-integrated smart power management IC, which includes a + single cell Li-Ion/Li-Polymer switching battery charger, a USB Type-C & + Power Delivery (PD) controller, dual flash LED current sources, a RGB LED + driver, a backlight WLED driver, a display bias driver and a general LDO for + portable devices. + +properties: + compatible: + const: mediatek,mt6370 + + reg: + maxItems: 1 + + wakeup-source: true + + interrupts: + maxItems: 1 + + interrupt-controller: true + + "#interrupt-cells": + const: 1 + + adc: + type: object + description: | + Provides 9 channels for system monitoring, including VBUSDIV5 (lower + accuracy, higher measure range), VBUSDIV2 (higher accuracy, lower + measure range), VBAT, VSYS, CHG_VDDP, TS_BAT, IBUS, IBAT, and TEMP_JC. + + properties: + compatible: + const: mediatek,mt6370-adc + + "#io-channel-cells": + const: 1 + + required: + - compatible + - "#io-channel-cells" + + backlight: + type: object + $ref: /schemas/leds/backlight/mediatek,mt6370-backlight.yaml# + + charger: + type: object + $ref: /schemas/power/supply/mediatek,mt6370-charger.yaml# + + tcpc: + type: object + $ref: /schemas/usb/mediatek,mt6370-tcpc.yaml# + + indicator: + type: object + $ref: /schemas/leds/mediatek,mt6370-indicator.yaml# + + flashlight: + type: object + $ref: /schemas/leds/mediatek,mt6370-flashlight.yaml# + + regulators: + type: object + description: | + List all supported regulators, which support the control for DisplayBias + voltages and one general purpose LDO which commonly used to drive the + vibrator. + + patternProperties: + "^(dsvbst|vibldo)$": + $ref: /schemas/regulator/regulator.yaml# + type: object + unevaluatedProperties: false + + "^(dsvpos|dsvneg)$": + $ref: /schemas/regulator/regulator.yaml# + type: object + unevaluatedProperties: false + + properties: + enable-gpios: + maxItems: 1 + +required: + - compatible + - reg + - interrupts + - interrupt-controller + - "#interrupt-cells" + - regulators + - adc + - backlight + - indicator + - tcpc + - charger + - flashlight + +additionalProperties: false + +examples: + - | + #include + #include + #include + #include + i2c { + #address-cells = <1>; + #size-cells = <0>; + + pmic@34 { + compatible = "mediatek,mt6370"; + reg = <0x34>; + wakeup-source; + interrupts-extended = <&gpio26 3 IRQ_TYPE_LEVEL_LOW>; + interrupt-controller; + #interrupt-cells = <1>; + + mt6370_adc: adc { + compatible = "mediatek,mt6370-adc"; + #io-channel-cells = <1>; + }; + + backlight { + compatible = "mediatek,mt6370-backlight"; + mediatek,bled-channel-use = /bits/ 8 <15>; + }; + + charger { + compatible = "mediatek,mt6370-charger"; + interrupts = <48>, <68>, <6>; + interrupt-names = "attach_i", "uvp_d_evt", "mivr"; + io-channels = <&mt6370_adc MT6370_CHAN_IBUS>; + + mt6370_otg_vbus: usb-otg-vbus-regulator { + regulator-name = "mt6370-usb-otg-vbus"; + regulator-min-microvolt = <4350000>; + regulator-max-microvolt = <5800000>; + regulator-min-microamp = <500000>; + regulator-max-microamp = <3000000>; + }; + }; + + indicator { + compatible = "mediatek,mt6370-indicator"; + #address-cells = <1>; + #size-cells = <0>; + + multi-led@0 { + reg = <0>; + function = LED_FUNCTION_INDICATOR; + color = ; + led-max-microamp = <24000>; + #address-cells = <1>; + #size-cells = <0>; + led@0 { + reg = <0>; + color = ; + }; + led@1 { + reg = <1>; + color = ; + }; + led@2 { + reg = <2>; + color = ; + }; + }; + led@3 { + reg = <3>; + function = LED_FUNCTION_INDICATOR; + color = ; + led-max-microamp = <6000>; + }; + }; + + flashlight { + compatible = "mediatek,mt6370-flashlight"; + #address-cells = <1>; + #size-cells = <0>; + led@0 { + reg = <0>; + led-sources = <0>; + function = LED_FUNCTION_FLASH; + color = ; + function-enumerator = <1>; + led-max-microamp = <200000>; + flash-max-microamp = <500000>; + flash-max-timeout-us = <1248000>; + }; + led@1 { + reg = <1>; + led-sources = <1>; + function = LED_FUNCTION_FLASH; + color = ; + function-enumerator = <2>; + led-max-microamp = <200000>; + flash-max-microamp = <500000>; + flash-max-timeout-us = <1248000>; + }; + }; + + tcpc { + compatible = "mediatek,mt6370-tcpc"; + interrupts-extended = <&gpio26 4 IRQ_TYPE_LEVEL_LOW>; + + connector { + compatible = "usb-c-connector"; + label = "USB-C"; + vbus-supply = <&mt6370_otg_vbus>; + data-role = "dual"; + power-role = "dual"; + try-power-role = "sink"; + source-pdos = ; + sink-pdos = ; + op-sink-microwatt = <10000000>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + endpoint { + remote-endpoint = <&usb_hs>; + }; + }; + port@1 { + reg = <1>; + endpoint { + remote-endpoint = <&usb_ss>; + }; + }; + port@2 { + reg = <2>; + endpoint { + remote-endpoint = <&dp_aux>; + }; + }; + }; + }; + }; + + regulators { + dsvbst { + regulator-name = "mt6370-dsv-vbst"; + regulator-min-microvolt = <4000000>; + regulator-max-microvolt = <6200000>; + }; + dsvpos { + regulator-name = "mt6370-dsv-vpos"; + regulator-min-microvolt = <4000000>; + regulator-max-microvolt = <6000000>; + regulator-boot-on; + }; + dsvneg { + regulator-name = "mt6370-dsv-vneg"; + regulator-min-microvolt = <4000000>; + regulator-max-microvolt = <6000000>; + regulator-boot-on; + }; + vibldo { + regulator-name = "mt6370-vib-ldo"; + regulator-min-microvolt = <1600000>; + regulator-max-microvolt = <4000000>; + }; + }; + }; + }; diff --git a/include/dt-bindings/iio/adc/mediatek,mt6370_adc.h b/include/dt-bindings/iio/adc/mediatek,mt6370_adc.h new file mode 100644 index 0000000..6ee7255 --- /dev/null +++ b/include/dt-bindings/iio/adc/mediatek,mt6370_adc.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */ + +#ifndef __DT_BINDINGS_MEDIATEK_MT6370_ADC_H__ +#define __DT_BINDINGS_MEDIATEK_MT6370_ADC_H__ + +/* ADC Channel Index */ +#define MT6370_CHAN_VBUSDIV5 0 +#define MT6370_CHAN_VBUSDIV2 1 +#define MT6370_CHAN_VSYS 2 +#define MT6370_CHAN_VBAT 3 +#define MT6370_CHAN_TS_BAT 4 +#define MT6370_CHAN_IBUS 5 +#define MT6370_CHAN_IBAT 6 +#define MT6370_CHAN_CHG_VDDP 7 +#define MT6370_CHAN_TEMP_JC 8 +#define MT6370_CHAN_MAX 9 + +#endif From patchwork Fri Aug 5 07:06:04 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: ChiaEn Wu X-Patchwork-Id: 12936947 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 65E2BC00140 for ; Fri, 5 Aug 2022 07:12:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=jDAc+aMF+FtZiiik9vhKVfAHjJLLW4EwqnGWn9B83Ew=; b=yunWfpK6wF7LtBXr5qYJN2sZfu sBdOZVWfIFDCMyrX8Txq0qq3ZQesr/eIMsj3ZHDKoWvt2TZE9Snk2NzWj7L7ghs1Y5pbtyQLmbWHK LsBo6UNEoSkHz8+Py6qNKldcBTSF5GAETaNQdjbOEIr5+5S23w+yJ4koEuLM8U984rUrqYBcvcD/m 0wtv24JzFze3ddq9l1EODJ1szSPf3JlqKNA0IONdt7KrLXT1ZN77Bon+qW9PShoX6DtYX4OOzw3Ep e9BQPpzS/6O+MeFiTQVKSEYfx0ZkCEHG1P2uzacAs7RKaSe2qhzdRXXnWdGid05Zt9829+o6BxcGP ZUvseb8Q==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1oJrUy-00Cjmz-SG; Fri, 05 Aug 2022 07:11:56 +0000 Received: from mail-pj1-x102d.google.com ([2607:f8b0:4864:20::102d]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1oJrQY-00ChKZ-6k; Fri, 05 Aug 2022 07:07:25 +0000 Received: by mail-pj1-x102d.google.com with SMTP id t22so1924071pjy.1; Fri, 05 Aug 2022 00:07:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc; bh=jDAc+aMF+FtZiiik9vhKVfAHjJLLW4EwqnGWn9B83Ew=; b=T9xkux3pMlHeFfX87zWp3vrLGiOpyfQCVcpMoHLJITE7eIYq9H4aDrs1SCdpMLDQ6e L6LlloQIPKK2Cr8BiJQSKHeGy0RPPZ4nx2O4eIsOU067bHEyEg+pNPrjWgXNMqr4iNnn zLx9Txv/GG7y5iP7BU8Fydifdcoy4JGCrzqF4pfqceW76rAXSCWCx9Gj08g+ZnMuvG/7 BsDjRQMMMAziTD9CUwXUzHNaSx1Wn+51rD6hESZ7FIMMewAKvzA5+UuZ0+a57vYqYJhH k2vMwHxSVb4IELeMOVJbx7+X2kmM8Lc6bFlqZqJ4KdZWQPXfgni/WcF7PTGAYpaZXCDf 0mDA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc; bh=jDAc+aMF+FtZiiik9vhKVfAHjJLLW4EwqnGWn9B83Ew=; b=lfM3LA4XGAQsPS9giEnYKed5Thb9eoZB+NUYhOSKwM4aQiU2vVkfrHcxosj2XjmGYn 8qxjLc21BX2kjAp6EKLeK7P0F41ozIZp8LGYqRkwzWO+wufjl7/CHHGXdvM6XczTjkZU seqfOU0O1B71Rg3WDTIxlcUMzymbxI2hIJxWT9KGw48BgOrj2VfyfYvpv0PCbA3UpvJj yzQm3/ebBamYnnXThmFyjbkoqRBbIXdLKOID7Z9P40Wm/3wYiAR+YG/s5Hq27b2CLUMN rxDcCArfKZ98hy3Bmxv4DNorRP6nRBalAMqvVwOIvN8yNKcpveXi84A9m390ZiZJhiSG ZysA== X-Gm-Message-State: ACgBeo0sYsP5pddN3zYdBN4pMp8eb9vtmgy7Jv/80NuR9RMpDFCKq0KI c/LdFjjXPg6KpYIkRHsvYS8= X-Google-Smtp-Source: AA6agR47feXupDHnpVpBAWuXh3e2o2kp6c2rqYkxAXZdksraqSXgK8h4d323UWINnJT4RMi4oOBNSA== X-Received: by 2002:a17:902:778a:b0:16c:a1c9:7b14 with SMTP id o10-20020a170902778a00b0016ca1c97b14mr5597546pll.116.1659683238236; Fri, 05 Aug 2022 00:07:18 -0700 (PDT) Received: from RD-3580-24288.rt.l (42-72-229-62.emome-ip.hinet.net. [42.72.229.62]) by smtp.gmail.com with ESMTPSA id i5-20020a056a00224500b00525343b5047sm2191616pfu.76.2022.08.05.00.07.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 05 Aug 2022 00:07:17 -0700 (PDT) From: ChiaEn Wu To: lee.jones@linaro.org, daniel.thompson@linaro.org, jingoohan1@gmail.com, pavel@ucw.cz, robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, matthias.bgg@gmail.com, sre@kernel.org, chunfeng.yun@mediatek.com, gregkh@linuxfoundation.org, jic23@kernel.org, lars@metafoo.de, lgirdwood@gmail.com, broonie@kernel.org, linux@roeck-us.net, heikki.krogerus@linux.intel.com, deller@gmx.de, andy.shevchenko@gmail.com Cc: chiaen_wu@richtek.com, alice_chen@richtek.com, cy_huang@richtek.com, dri-devel@lists.freedesktop.org, linux-leds@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, linux-usb@vger.kernel.org, linux-iio@vger.kernel.org, linux-fbdev@vger.kernel.org, szunichen@gmail.com Subject: [PATCH v7 07/13] mfd: mt6370: Add MediaTek MT6370 support Date: Fri, 5 Aug 2022 15:06:04 +0800 Message-Id: <20220805070610.3516-8-peterwu.pub@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220805070610.3516-1-peterwu.pub@gmail.com> References: <20220805070610.3516-1-peterwu.pub@gmail.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220805_000722_328598_9124D27B X-CRM114-Status: GOOD ( 21.63 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org From: ChiYuan Huang This adds support for the MediaTek MT6370 SubPMIC. MediaTek MT6370 is a SubPMIC consisting of a single cell battery charger with ADC monitoring, RGB LEDs, dual channel flashlight, WLED backlight driver, display bias voltage supply, one general purpose LDO, and the USB Type-C & PD controller complies with the latest USB Type-C and PD standards. Reviewed-by: Andy Shevchenko Signed-off-by: ChiYuan Huang Signed-off-by: ChiaEn Wu --- v7 - Move '#define MT6370_REG_MAXADDR' to the next line of '#define MT6370_REG_CHG_MASK1' - Rename 'MT6370_REG_ADDRLEN' to 'MT6370_MAX_ADDRLEN' --- drivers/mfd/Kconfig | 16 +++ drivers/mfd/Makefile | 1 + drivers/mfd/mt6370.c | 312 +++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/mfd/mt6370.h | 99 ++++++++++++++++ 4 files changed, 428 insertions(+) create mode 100644 drivers/mfd/mt6370.c create mode 100644 drivers/mfd/mt6370.h diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 9566341..0666bda 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -938,6 +938,22 @@ config MFD_MT6360 PMIC part includes 2-channel BUCKs and 2-channel LDOs LDO part includes 4-channel LDOs +config MFD_MT6370 + tristate "MediaTek MT6370 SubPMIC" + select MFD_CORE + select REGMAP_I2C + select REGMAP_IRQ + depends on I2C + help + Say Y here to enable MT6370 SubPMIC functional support. + It consists of a single cell battery charger with ADC monitoring, RGB + LEDs, dual channel flashlight, WLED backlight driver, display bias + voltage supply, one general purpose LDO, and the USB Type-C & PD + controller complies with the latest USB Type-C and PD standards. + + This driver can also be built as a module. If so, the module + will be called "mt6370". + config MFD_MT6397 tristate "MediaTek MT6397 PMIC Support" select MFD_CORE diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 8c69867..81dbed3 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -173,6 +173,7 @@ obj-$(CONFIG_MFD_MAX8998) += max8998.o max8998-irq.o obj-$(CONFIG_MFD_MP2629) += mp2629.o obj-$(CONFIG_MFD_MT6360) += mt6360-core.o +obj-$(CONFIG_MFD_MT6370) += mt6370.o mt6397-objs := mt6397-core.o mt6397-irq.o mt6358-irq.o obj-$(CONFIG_MFD_MT6397) += mt6397.o diff --git a/drivers/mfd/mt6370.c b/drivers/mfd/mt6370.c new file mode 100644 index 0000000..cf19cce --- /dev/null +++ b/drivers/mfd/mt6370.c @@ -0,0 +1,312 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2022 Richtek Technology Corp. + * + * Author: ChiYuan Huang + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mt6370.h" + +#define MT6370_REG_DEV_INFO 0x100 +#define MT6370_REG_CHG_IRQ1 0x1C0 +#define MT6370_REG_CHG_MASK1 0x1E0 +#define MT6370_REG_MAXADDR 0x1FF + +#define MT6370_VENID_MASK GENMASK(7, 4) + +#define MT6370_NUM_IRQREGS 16 +#define MT6370_USBC_I2CADDR 0x4E +#define MT6370_MAX_ADDRLEN 2 + +#define MT6370_VENID_RT5081 0x8 +#define MT6370_VENID_RT5081A 0xA +#define MT6370_VENID_MT6370 0xE +#define MT6370_VENID_MT6371 0xF +#define MT6370_VENID_MT6372P 0x9 +#define MT6370_VENID_MT6372CP 0xB + +static const struct regmap_irq mt6370_irqs[] = { + REGMAP_IRQ_REG_LINE(MT6370_IRQ_DIRCHGON, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_TREG, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_AICR, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_MIVR, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_PWR_RDY, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_FL_CHG_VINOVP, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_VSYSUV, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_VSYSOV, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_VBATOV, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_VINOVPCHG, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_TS_BAT_COLD, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_TS_BAT_COOL, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_TS_BAT_WARM, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_TS_BAT_HOT, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_TS_STATC, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_FAULT, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_STATC, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_TMR, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_BATABS, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_ADPBAD, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_RVP, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_TSHUTDOWN, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_IINMEAS, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_ICCMEAS, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHGDET_DONE, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_WDTMR, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_SSFINISH, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_RECHG, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_TERM, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHG_IEOC, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_ADC_DONE, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_PUMPX_DONE, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_BST_BATUV, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_BST_MIDOV, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_BST_OLP, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_ATTACH, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_DETACH, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_HVDCP_STPDONE, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_HVDCP_VBUSDET_DONE, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_HVDCP_DET, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_CHGDET, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_DCDT, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_DIRCHG_VGOK, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_DIRCHG_WDTMR, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_DIRCHG_UC, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_DIRCHG_OC, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_DIRCHG_OV, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_OVPCTRL_SWON, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_OVPCTRL_UVP_D, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_OVPCTRL_UVP, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_OVPCTRL_OVP_D, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_OVPCTRL_OVP, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED_STRBPIN, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED_TORPIN, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED_TX, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED_LVF, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED2_SHORT, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED1_SHORT, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED2_STRB, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED1_STRB, 8), + REGMAP_IRQ_REG_LINE(mT6370_IRQ_FLED2_STRB_TO, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED1_STRB_TO, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED2_TOR, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_FLED1_TOR, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_OTP, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_VDDA_OVP, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_VDDA_UV, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_LDO_OC, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_BLED_OCP, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_BLED_OVP, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_DSV_VNEG_OCP, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_DSV_VPOS_OCP, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_DSV_BST_OCP, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_DSV_VNEG_SCP, 8), + REGMAP_IRQ_REG_LINE(MT6370_IRQ_DSV_VPOS_SCP, 8), +}; + +static const struct regmap_irq_chip mt6370_irq_chip = { + .name = "mt6370-irqs", + .status_base = MT6370_REG_CHG_IRQ1, + .mask_base = MT6370_REG_CHG_MASK1, + .num_regs = MT6370_NUM_IRQREGS, + .irqs = mt6370_irqs, + .num_irqs = ARRAY_SIZE(mt6370_irqs), +}; + +static const struct resource mt6370_regulator_irqs[] = { + DEFINE_RES_IRQ_NAMED(MT6370_IRQ_DSV_VPOS_SCP, "db_vpos_scp"), + DEFINE_RES_IRQ_NAMED(MT6370_IRQ_DSV_VNEG_SCP, "db_vneg_scp"), + DEFINE_RES_IRQ_NAMED(MT6370_IRQ_DSV_BST_OCP, "db_vbst_ocp"), + DEFINE_RES_IRQ_NAMED(MT6370_IRQ_DSV_VPOS_OCP, "db_vpos_ocp"), + DEFINE_RES_IRQ_NAMED(MT6370_IRQ_DSV_VNEG_OCP, "db_vneg_ocp"), + DEFINE_RES_IRQ_NAMED(MT6370_IRQ_LDO_OC, "ldo_oc"), +}; + +static const struct mfd_cell mt6370_devices[] = { + MFD_CELL_OF("mt6370-adc", + NULL, NULL, 0, 0, "mediatek,mt6370-adc"), + MFD_CELL_OF("mt6370-charger", + NULL, NULL, 0, 0, "mediatek,mt6370-charger"), + MFD_CELL_OF("mt6370-flashlight", + NULL, NULL, 0, 0, "mediatek,mt6370-flashlight"), + MFD_CELL_OF("mt6370-indicator", + NULL, NULL, 0, 0, "mediatek,mt6370-indicator"), + MFD_CELL_OF("mt6370-tcpc", + NULL, NULL, 0, 0, "mediatek,mt6370-tcpc"), + MFD_CELL_RES("mt6370-regulator", mt6370_regulator_irqs), +}; + +static const struct mfd_cell mt6370_exclusive_devices[] = { + MFD_CELL_OF("mt6370-backlight", + NULL, NULL, 0, 0, "mediatek,mt6370-backlight"), +}; + +static const struct mfd_cell mt6372_exclusive_devices[] = { + MFD_CELL_OF("mt6370-backlight", + NULL, NULL, 0, 0, "mediatek,mt6372-backlight"), +}; + +static int mt6370_check_vendor_info(struct device *dev, struct regmap *rmap, + int *vid) +{ + unsigned int devinfo; + int ret; + + ret = regmap_read(rmap, MT6370_REG_DEV_INFO, &devinfo); + if (ret) + return ret; + + *vid = FIELD_GET(MT6370_VENID_MASK, devinfo); + switch (*vid) { + case MT6370_VENID_RT5081: + case MT6370_VENID_RT5081A: + case MT6370_VENID_MT6370: + case MT6370_VENID_MT6371: + case MT6370_VENID_MT6372P: + case MT6370_VENID_MT6372CP: + return 0; + default: + dev_err(dev, "Unknown Vendor ID 0x%02x\n", devinfo); + return -ENODEV; + } +} + +static int mt6370_regmap_read(void *context, const void *reg_buf, + size_t reg_size, void *val_buf, size_t val_size) +{ + struct mt6370_info *info = context; + const u8 *u8_buf = reg_buf; + u8 bank_idx, bank_addr; + int ret; + + bank_idx = u8_buf[0]; + bank_addr = u8_buf[1]; + + ret = i2c_smbus_read_i2c_block_data(info->i2c[bank_idx], bank_addr, + val_size, val_buf); + if (ret < 0) + return ret; + + if (ret != val_size) + return -EIO; + + return 0; +} + +static int mt6370_regmap_write(void *context, const void *data, size_t count) +{ + struct mt6370_info *info = context; + const u8 *u8_buf = data; + u8 bank_idx, bank_addr; + int len = count - MT6370_MAX_ADDRLEN; + + bank_idx = u8_buf[0]; + bank_addr = u8_buf[1]; + + return i2c_smbus_write_i2c_block_data(info->i2c[bank_idx], bank_addr, + len, data + MT6370_MAX_ADDRLEN); +} + +static const struct regmap_bus mt6370_regmap_bus = { + .read = mt6370_regmap_read, + .write = mt6370_regmap_write, +}; + +static const struct regmap_config mt6370_regmap_config = { + .reg_bits = 16, + .val_bits = 8, + .reg_format_endian = REGMAP_ENDIAN_BIG, + .max_register = MT6370_REG_MAXADDR, +}; + +static int mt6370_probe(struct i2c_client *i2c) +{ + struct mt6370_info *info; + struct i2c_client *usbc_i2c; + struct regmap *regmap; + struct device *dev = &i2c->dev; + int ret, vid; + + info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + usbc_i2c = devm_i2c_new_dummy_device(dev, i2c->adapter, + MT6370_USBC_I2CADDR); + if (IS_ERR(usbc_i2c)) + return dev_err_probe(dev, PTR_ERR(usbc_i2c), + "Failed to register USBC I2C client\n"); + + /* Assign I2C client for PMU and TypeC */ + info->i2c[MT6370_PMU_I2C] = i2c; + info->i2c[MT6370_USBC_I2C] = usbc_i2c; + + regmap = devm_regmap_init(dev, &mt6370_regmap_bus, + info, &mt6370_regmap_config); + if (IS_ERR(regmap)) + return dev_err_probe(dev, PTR_ERR(regmap), + "Failed to init regmap\n"); + + ret = mt6370_check_vendor_info(dev, regmap, &vid); + if (ret) + return dev_err_probe(dev, ret, "Failed to check vendor info\n"); + + ret = devm_regmap_add_irq_chip(dev, regmap, i2c->irq, + IRQF_ONESHOT, -1, &mt6370_irq_chip, + &info->irq_data); + if (ret) + return dev_err_probe(dev, ret, "Failed to add irq chip\n"); + + switch (vid) { + case MT6370_VENID_MT6372P: + case MT6370_VENID_MT6372CP: + ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, + mt6372_exclusive_devices, + ARRAY_SIZE(mt6372_exclusive_devices), + NULL, 0, + regmap_irq_get_domain(info->irq_data)); + break; + default: + ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, + mt6370_exclusive_devices, + ARRAY_SIZE(mt6370_exclusive_devices), + NULL, 0, + regmap_irq_get_domain(info->irq_data)); + break; + } + + if (ret) + return dev_err_probe(dev, ret, "Failed to add the exclusive devices\n"); + + return devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, + mt6370_devices, ARRAY_SIZE(mt6370_devices), + NULL, 0, + regmap_irq_get_domain(info->irq_data)); +} + +static const struct of_device_id mt6370_match_table[] = { + { .compatible = "mediatek,mt6370" }, + {} +}; +MODULE_DEVICE_TABLE(of, mt6370_match_table); + +static struct i2c_driver mt6370_driver = { + .driver = { + .name = "mt6370", + .of_match_table = mt6370_match_table, + }, + .probe_new = mt6370_probe, +}; +module_i2c_driver(mt6370_driver); + +MODULE_AUTHOR("ChiYuan Huang "); +MODULE_DESCRIPTION("MediaTek MT6370 SubPMIC Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/mfd/mt6370.h b/drivers/mfd/mt6370.h new file mode 100644 index 0000000..094e59e --- /dev/null +++ b/drivers/mfd/mt6370.h @@ -0,0 +1,99 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2022 Richtek Technology Corp. + * + * Author: ChiYuan Huang + */ + +#ifndef __MFD_MT6370_H__ +#define __MFD_MT6370_H__ + +/* IRQ definitions */ +#define MT6370_IRQ_DIRCHGON 0 +#define MT6370_IRQ_CHG_TREG 4 +#define MT6370_IRQ_CHG_AICR 5 +#define MT6370_IRQ_CHG_MIVR 6 +#define MT6370_IRQ_PWR_RDY 7 +#define MT6370_IRQ_FL_CHG_VINOVP 11 +#define MT6370_IRQ_CHG_VSYSUV 12 +#define MT6370_IRQ_CHG_VSYSOV 13 +#define MT6370_IRQ_CHG_VBATOV 14 +#define MT6370_IRQ_CHG_VINOVPCHG 15 +#define MT6370_IRQ_TS_BAT_COLD 20 +#define MT6370_IRQ_TS_BAT_COOL 21 +#define MT6370_IRQ_TS_BAT_WARM 22 +#define MT6370_IRQ_TS_BAT_HOT 23 +#define MT6370_IRQ_TS_STATC 24 +#define MT6370_IRQ_CHG_FAULT 25 +#define MT6370_IRQ_CHG_STATC 26 +#define MT6370_IRQ_CHG_TMR 27 +#define MT6370_IRQ_CHG_BATABS 28 +#define MT6370_IRQ_CHG_ADPBAD 29 +#define MT6370_IRQ_CHG_RVP 30 +#define MT6370_IRQ_TSHUTDOWN 31 +#define MT6370_IRQ_CHG_IINMEAS 32 +#define MT6370_IRQ_CHG_ICCMEAS 33 +#define MT6370_IRQ_CHGDET_DONE 34 +#define MT6370_IRQ_WDTMR 35 +#define MT6370_IRQ_SSFINISH 36 +#define MT6370_IRQ_CHG_RECHG 37 +#define MT6370_IRQ_CHG_TERM 38 +#define MT6370_IRQ_CHG_IEOC 39 +#define MT6370_IRQ_ADC_DONE 40 +#define MT6370_IRQ_PUMPX_DONE 41 +#define MT6370_IRQ_BST_BATUV 45 +#define MT6370_IRQ_BST_MIDOV 46 +#define MT6370_IRQ_BST_OLP 47 +#define MT6370_IRQ_ATTACH 48 +#define MT6370_IRQ_DETACH 49 +#define MT6370_IRQ_HVDCP_STPDONE 51 +#define MT6370_IRQ_HVDCP_VBUSDET_DONE 52 +#define MT6370_IRQ_HVDCP_DET 53 +#define MT6370_IRQ_CHGDET 54 +#define MT6370_IRQ_DCDT 55 +#define MT6370_IRQ_DIRCHG_VGOK 59 +#define MT6370_IRQ_DIRCHG_WDTMR 60 +#define MT6370_IRQ_DIRCHG_UC 61 +#define MT6370_IRQ_DIRCHG_OC 62 +#define MT6370_IRQ_DIRCHG_OV 63 +#define MT6370_IRQ_OVPCTRL_SWON 67 +#define MT6370_IRQ_OVPCTRL_UVP_D 68 +#define MT6370_IRQ_OVPCTRL_UVP 69 +#define MT6370_IRQ_OVPCTRL_OVP_D 70 +#define MT6370_IRQ_OVPCTRL_OVP 71 +#define MT6370_IRQ_FLED_STRBPIN 72 +#define MT6370_IRQ_FLED_TORPIN 73 +#define MT6370_IRQ_FLED_TX 74 +#define MT6370_IRQ_FLED_LVF 75 +#define MT6370_IRQ_FLED2_SHORT 78 +#define MT6370_IRQ_FLED1_SHORT 79 +#define MT6370_IRQ_FLED2_STRB 80 +#define MT6370_IRQ_FLED1_STRB 81 +#define mT6370_IRQ_FLED2_STRB_TO 82 +#define MT6370_IRQ_FLED1_STRB_TO 83 +#define MT6370_IRQ_FLED2_TOR 84 +#define MT6370_IRQ_FLED1_TOR 85 +#define MT6370_IRQ_OTP 93 +#define MT6370_IRQ_VDDA_OVP 94 +#define MT6370_IRQ_VDDA_UV 95 +#define MT6370_IRQ_LDO_OC 103 +#define MT6370_IRQ_BLED_OCP 118 +#define MT6370_IRQ_BLED_OVP 119 +#define MT6370_IRQ_DSV_VNEG_OCP 123 +#define MT6370_IRQ_DSV_VPOS_OCP 124 +#define MT6370_IRQ_DSV_BST_OCP 125 +#define MT6370_IRQ_DSV_VNEG_SCP 126 +#define MT6370_IRQ_DSV_VPOS_SCP 127 + +enum { + MT6370_USBC_I2C = 0, + MT6370_PMU_I2C, + MT6370_MAX_I2C +}; + +struct mt6370_info { + struct i2c_client *i2c[MT6370_MAX_I2C]; + struct regmap_irq_chip_data *irq_data; +}; + +#endif /* __MFD_MT6375_H__ */ From patchwork Fri Aug 5 07:06:05 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: ChiaEn Wu X-Patchwork-Id: 12936966 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 95113C00140 for ; Fri, 5 Aug 2022 07:12:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=417XP0VUaPHr28qOEx+tO3462l1fmx7MuN2VICDrfwA=; b=uG9vl7YaEVMxSKyQ+pJfbIY8FU zRxIEAc8Qwf4TxC8TUmtoCGTm0DEJ2U480Im3+BjcALgmS4VBN/I8CvRsgChnkrc4hFzxoaLGGpYt qeAr+JXLRFHlhIOIHiHV9c7fnkisfGZ07CZBLXvHjEro5IeX3735SwGGFz+rq79qVcECGE9OQkCBT zA8Yx6Z+exvwfwgf8Sd8N+0k1NGCIYG4Z/hAjPrMt8h5KUohXUguCTf0VMM4mOvrJFQoaCIB+iPsN NfwaiEzBuPsosh0z/j0yVFbhP3n0yxFpOrxl9gCUZmrJ7PD5XlUQOxQ7ntaG7i/xsuoGCyJiUPpOK 94skW9vw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1oJrVi-00Ck8g-Qs; Fri, 05 Aug 2022 07:12:42 +0000 Received: from mail-pj1-x1032.google.com ([2607:f8b0:4864:20::1032]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1oJrQg-00ChOn-Ug; Fri, 05 Aug 2022 07:07:32 +0000 Received: by mail-pj1-x1032.google.com with SMTP id p14-20020a17090a74ce00b001f4d04492faso1967439pjl.4; Fri, 05 Aug 2022 00:07:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc; bh=417XP0VUaPHr28qOEx+tO3462l1fmx7MuN2VICDrfwA=; b=hlcX5ARqYXbcodPXrrwTrSfCXtDRzFWh59mDy+qRZwVOBUGwuhJ64tEIQ+9vhUkiRr M2pFmdOv5YokV7Fz/Bc3GTgADLMRG1Y1ndfnJOJHW693fzSruRPLV0q3qKCrSKjRjbLZ 4fWfLtmIAsOy/n/mGjJ3yKvd3HmOaHYUJJ4SpDs0PML9TcKgkzAgx7G/aTE/Ci9z+D2B 1Gu3rYSJKuEZYo1lI0t2FupxFfWYdENn+aqopaqFyDRC2sunlhrHRDT080vZta1nQQ9P 1VLFq39P4NXrkwzfcWtMWHlcUmUMb41fgfDlUEQDIPFWkAB7wVa894PTqkagCxa7E6fw kMbA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc; bh=417XP0VUaPHr28qOEx+tO3462l1fmx7MuN2VICDrfwA=; b=ZZD0N/itW9GOK69wSRZsQEhsY9ess0X/rdD9jZsRkzF/IOh2wHnRiF1UgvpMcZb79Z peL0XpOOc0D93IvO8gKvnMCWhoXC7DAtVoBD+1k1JU8ytIAzFvr78zc28eoglelbdtus Q0zNrfj4PSdFiLqMyxQOD0fQHSYygvstdSrBa7k6IEl7vFAq6rIEQ5UDmYXncdVbRxA3 oIsmb20xhzIEMy5jrikGoIizpbTu6GT2u4biR0+45Kj8XoKrPOvAF5VKUTu0pfEO/733 BKMY8BDbXw1OR+mvyOfD4VRneHBaEWZ7aSRnIue/U9nn9vhBaZkJgpecEzr9+c2J9Den hhjA== X-Gm-Message-State: ACgBeo1rKDDr+3/nU4k/HdEeAsxxhAPjANTngTtgw1fGIlSrN7G18vuh 1xwWdwcnqkRhjJaSr3B+C1k= X-Google-Smtp-Source: AA6agR7sLdYbldfWGmFXluGl1w4qbpxl1uqy/AE/SBXgssrZTmYD9dsOrwVN78p6tqY4JsculuvrjA== X-Received: by 2002:a17:90b:f8c:b0:1f2:ea98:a273 with SMTP id ft12-20020a17090b0f8c00b001f2ea98a273mr6234868pjb.155.1659683245059; Fri, 05 Aug 2022 00:07:25 -0700 (PDT) Received: from RD-3580-24288.rt.l (42-72-229-62.emome-ip.hinet.net. [42.72.229.62]) by smtp.gmail.com with ESMTPSA id i5-20020a056a00224500b00525343b5047sm2191616pfu.76.2022.08.05.00.07.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 05 Aug 2022 00:07:24 -0700 (PDT) From: ChiaEn Wu To: lee.jones@linaro.org, daniel.thompson@linaro.org, jingoohan1@gmail.com, pavel@ucw.cz, robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, matthias.bgg@gmail.com, sre@kernel.org, chunfeng.yun@mediatek.com, gregkh@linuxfoundation.org, jic23@kernel.org, lars@metafoo.de, lgirdwood@gmail.com, broonie@kernel.org, linux@roeck-us.net, heikki.krogerus@linux.intel.com, deller@gmx.de, andy.shevchenko@gmail.com Cc: chiaen_wu@richtek.com, alice_chen@richtek.com, cy_huang@richtek.com, dri-devel@lists.freedesktop.org, linux-leds@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, linux-usb@vger.kernel.org, linux-iio@vger.kernel.org, linux-fbdev@vger.kernel.org, szunichen@gmail.com, AngeloGioacchino Del Regno Subject: [PATCH v7 08/13] usb: typec: tcpci_mt6370: Add MediaTek MT6370 tcpci driver Date: Fri, 5 Aug 2022 15:06:05 +0800 Message-Id: <20220805070610.3516-9-peterwu.pub@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220805070610.3516-1-peterwu.pub@gmail.com> References: <20220805070610.3516-1-peterwu.pub@gmail.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220805_000731_056026_40A65A00 X-CRM114-Status: GOOD ( 23.16 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org From: ChiYuan Huang The MediaTek MT6370 is a highly-integrated smart power management IC, which includes a single cell Li-Ion/Li-Polymer switching battery charger, a USB Type-C & Power Delivery (PD) controller, dual Flash LED current sources, a RGB LED driver, a backlight WLED driver, a display bias driver and a general LDO for portable devices. Add a support for the Type-C & Power Delivery controller in MediaTek MT6370 IC. Reviewed-by: AngeloGioacchino Del Regno Reviewed-by: Guenter Roeck Signed-off-by: ChiYuan Huang Signed-off-by: ChiaEn Wu Reviewed-by: Andy Shevchenko Reviewed-by: Heikki Krogerus --- v7 - Revise 'devm_add_action_or_reset(dev, ...)' to one line - Revise 'return regmap_update_bits(...)' with using positive conditional --- drivers/usb/typec/tcpm/Kconfig | 11 ++ drivers/usb/typec/tcpm/Makefile | 1 + drivers/usb/typec/tcpm/tcpci_mt6370.c | 207 ++++++++++++++++++++++++++++++++++ 3 files changed, 219 insertions(+) create mode 100644 drivers/usb/typec/tcpm/tcpci_mt6370.c diff --git a/drivers/usb/typec/tcpm/Kconfig b/drivers/usb/typec/tcpm/Kconfig index 073fd2e..e6b88ca 100644 --- a/drivers/usb/typec/tcpm/Kconfig +++ b/drivers/usb/typec/tcpm/Kconfig @@ -35,6 +35,17 @@ config TYPEC_MT6360 USB Type-C. It works with Type-C Port Controller Manager to provide USB PD and USB Type-C functionalities. +config TYPEC_TCPCI_MT6370 + tristate "MediaTek MT6370 Type-C driver" + depends on MFD_MT6370 + help + MediaTek MT6370 is a multi-functional IC that includes + USB Type-C. It works with Type-C Port Controller Manager + to provide USB PD and USB Type-C functionalities. + + This driver can also be built as a module. The module + will be called "tcpci_mt6370". + config TYPEC_TCPCI_MAXIM tristate "Maxim TCPCI based Type-C chip driver" help diff --git a/drivers/usb/typec/tcpm/Makefile b/drivers/usb/typec/tcpm/Makefile index 7d499f3..906d9dc 100644 --- a/drivers/usb/typec/tcpm/Makefile +++ b/drivers/usb/typec/tcpm/Makefile @@ -6,4 +6,5 @@ typec_wcove-y := wcove.o obj-$(CONFIG_TYPEC_TCPCI) += tcpci.o obj-$(CONFIG_TYPEC_RT1711H) += tcpci_rt1711h.o obj-$(CONFIG_TYPEC_MT6360) += tcpci_mt6360.o +obj-$(CONFIG_TYPEC_TCPCI_MT6370) += tcpci_mt6370.o obj-$(CONFIG_TYPEC_TCPCI_MAXIM) += tcpci_maxim.o diff --git a/drivers/usb/typec/tcpm/tcpci_mt6370.c b/drivers/usb/typec/tcpm/tcpci_mt6370.c new file mode 100644 index 0000000..c5bb201 --- /dev/null +++ b/drivers/usb/typec/tcpm/tcpci_mt6370.c @@ -0,0 +1,207 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2022 Richtek Technology Corp. + * + * Author: ChiYuan Huang + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MT6370_REG_SYSCTRL8 0x9B + +#define MT6370_AUTOIDLE_MASK BIT(3) + +#define MT6370_VENDOR_ID 0x29CF +#define MT6370_TCPC_DID_A 0x2170 + +struct mt6370_priv { + struct device *dev; + struct regulator *vbus; + struct tcpci *tcpci; + struct tcpci_data tcpci_data; +}; + +static const struct reg_sequence mt6370_reg_init[] = { + REG_SEQ(0xA0, 0x1, 1000), + REG_SEQ(0x81, 0x38, 0), + REG_SEQ(0x82, 0x82, 0), + REG_SEQ(0xBA, 0xFC, 0), + REG_SEQ(0xBB, 0x50, 0), + REG_SEQ(0x9E, 0x8F, 0), + REG_SEQ(0xA1, 0x5, 0), + REG_SEQ(0xA2, 0x4, 0), + REG_SEQ(0xA3, 0x4A, 0), + REG_SEQ(0xA4, 0x01, 0), + REG_SEQ(0x95, 0x01, 0), + REG_SEQ(0x80, 0x71, 0), + REG_SEQ(0x9B, 0x3A, 1000), +}; + +static int mt6370_tcpc_init(struct tcpci *tcpci, struct tcpci_data *data) +{ + u16 did; + int ret; + + ret = regmap_register_patch(data->regmap, mt6370_reg_init, + ARRAY_SIZE(mt6370_reg_init)); + if (ret) + return ret; + + ret = regmap_raw_read(data->regmap, TCPC_BCD_DEV, &did, sizeof(u16)); + if (ret) + return ret; + + if (did == MT6370_TCPC_DID_A) + return regmap_write(data->regmap, TCPC_FAULT_CTRL, 0x80); + + return 0; +} + +static int mt6370_tcpc_set_vconn(struct tcpci *tcpci, struct tcpci_data *data, + bool enable) +{ + return regmap_update_bits(data->regmap, MT6370_REG_SYSCTRL8, + MT6370_AUTOIDLE_MASK, + enable ? 0 : MT6370_AUTOIDLE_MASK); +} + +static int mt6370_tcpc_set_vbus(struct tcpci *tcpci, struct tcpci_data *data, + bool source, bool sink) +{ + struct mt6370_priv *priv = container_of(data, struct mt6370_priv, + tcpci_data); + int ret; + + ret = regulator_is_enabled(priv->vbus); + if (ret < 0) + return ret; + + if (ret && !source) + return regulator_disable(priv->vbus); + + if (!ret && source) + return regulator_enable(priv->vbus); + + return 0; +} + +static irqreturn_t mt6370_irq_handler(int irq, void *dev_id) +{ + struct mt6370_priv *priv = dev_id; + + return tcpci_irq(priv->tcpci); +} + +static int mt6370_check_vendor_info(struct mt6370_priv *priv) +{ + struct regmap *regmap = priv->tcpci_data.regmap; + u16 vid; + int ret; + + ret = regmap_raw_read(regmap, TCPC_VENDOR_ID, &vid, sizeof(u16)); + if (ret) + return ret; + + if (vid != MT6370_VENDOR_ID) + return dev_err_probe(priv->dev, -ENODEV, + "Vendor ID not correct 0x%02x\n", vid); + + return 0; +} + +static void mt6370_unregister_tcpci_port(void *tcpci) +{ + tcpci_unregister_port(tcpci); +} + +static int mt6370_tcpc_probe(struct platform_device *pdev) +{ + struct mt6370_priv *priv; + struct device *dev = &pdev->dev; + int irq, ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->dev = dev; + + priv->tcpci_data.regmap = dev_get_regmap(dev->parent, NULL); + if (!priv->tcpci_data.regmap) + return dev_err_probe(dev, -ENODEV, "Failed to init regmap\n"); + + ret = mt6370_check_vendor_info(priv); + if (ret) + return ret; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return dev_err_probe(dev, irq, "Failed to get irq\n"); + + /* Assign TCPCI feature and ops */ + priv->tcpci_data.auto_discharge_disconnect = 1; + priv->tcpci_data.init = mt6370_tcpc_init; + priv->tcpci_data.set_vconn = mt6370_tcpc_set_vconn; + + priv->vbus = devm_regulator_get_optional(dev, "vbus"); + if (!IS_ERR(priv->vbus)) + priv->tcpci_data.set_vbus = mt6370_tcpc_set_vbus; + + priv->tcpci = tcpci_register_port(dev, &priv->tcpci_data); + if (IS_ERR(priv->tcpci)) + return dev_err_probe(dev, PTR_ERR(priv->tcpci), + "Failed to register tcpci port\n"); + + ret = devm_add_action_or_reset(dev, mt6370_unregister_tcpci_port, priv->tcpci); + if (ret) + return ret; + + ret = devm_request_threaded_irq(dev, irq, NULL, mt6370_irq_handler, + IRQF_ONESHOT, dev_name(dev), priv); + if (ret) + return dev_err_probe(dev, ret, "Failed to allocate irq\n"); + + device_init_wakeup(dev, true); + dev_pm_set_wake_irq(dev, irq); + + return 0; +} + +static int mt6370_tcpc_remove(struct platform_device *pdev) +{ + dev_pm_clear_wake_irq(&pdev->dev); + device_init_wakeup(&pdev->dev, false); + + return 0; +} + +static const struct of_device_id mt6370_tcpc_devid_table[] = { + { .compatible = "mediatek,mt6370-tcpc" }, + {} +}; +MODULE_DEVICE_TABLE(of, mt6370_tcpc_devid_table); + +static struct platform_driver mt6370_tcpc_driver = { + .driver = { + .name = "mt6370-tcpc", + .of_match_table = mt6370_tcpc_devid_table, + }, + .probe = mt6370_tcpc_probe, + .remove = mt6370_tcpc_remove, +}; +module_platform_driver(mt6370_tcpc_driver); + +MODULE_AUTHOR("ChiYuan Huang "); +MODULE_DESCRIPTION("MT6370 USB Type-C Port Controller Interface Driver"); +MODULE_LICENSE("GPL v2"); From patchwork Fri Aug 5 07:06:06 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: ChiaEn Wu X-Patchwork-Id: 12936967 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 56CA1C00140 for ; Fri, 5 Aug 2022 07:13:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=PLxVmqRYbJJRcM/p8kC1Ho2TKKsFIrAdhnTf5h50b1c=; b=rD685bYkCQhndctpMXOMDIYLfP KqA0cP6P5Q7PqGyp2L6N3lEqb2Q6UweeoQOyW62VBwV96i6GCe/YhOr674uOvZKdp9nFSVsdgW6zM h50atTTswyNYA++YLQqdRhhZD6Vu5WyEqyZOKFjFyPAy7Bl5lKd1sugsYHOpLrpQx3oKmYULS6pCI 7Gkvee2CNersVbhNeMhLq/yTPGc3UOOpIQAboQLtS9fkJOAoUJUkV740lIS6u4XVaoJNZQXjgEKgK Rta1gabBQ2T1ux+aVgDEbsRz2poyUzAwn7hCWgetK+rm0cZxG+NeC7hPWLSAM1wOYr2pmHaC0HLk2 gbSso6RA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1oJrWa-00CkX9-52; Fri, 05 Aug 2022 07:13:36 +0000 Received: from mail-pg1-x534.google.com ([2607:f8b0:4864:20::534]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1oJrQk-00ChTt-Gs; Fri, 05 Aug 2022 07:07:40 +0000 Received: by mail-pg1-x534.google.com with SMTP id 73so1939787pgb.9; Fri, 05 Aug 2022 00:07:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc; bh=PLxVmqRYbJJRcM/p8kC1Ho2TKKsFIrAdhnTf5h50b1c=; b=pZWhyB79muXvo6w4bXMUzQBSanLI0RpJn+jKJG48kPuZzpfXyGebfopCELFDjBZaOJ E2STC+TBYa2G+ONXrAIsi7FEWZqlylGkAnTJWUI5oFaxiImAcDBKq+kUwVs9zi+9WT8j 83OCRyqXfQs51JiLwLjdgiAZUQvQRzcFFyZnugl+tzWcRUyiO/ucTaA/rIfS33MtmHEe j4k/YPFYonlHtB0njNjVLLTucckrYNUXCTgp2Sh5v7zq9bMY5L/Xl+Nc2R484S8cmAzs DrIlTicJ3fMA3IfSrTtH0KzbrZ5tFmuQNIDR/CpHtCgsGB300jktpGFf+wGAdgtR3BIe N4Aw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc; bh=PLxVmqRYbJJRcM/p8kC1Ho2TKKsFIrAdhnTf5h50b1c=; b=muFejQ0px3tisKJ9P5WM7pfGk3+W4IcvojuHfyjqoz223cuLJ09piMp5ckNbV1cliz 1qaDX7XPK25+ytcZ2hn0BT4PhYUf6ogwbyKwTbndZm0EnwsRZdjBAZll7JxTLYLMVAvW jBk4GSpn9UG0nO+RmHg6tV4asM8D+WD0ORo+fFRdLdwaHlUGBnrNJFwYozbI/rl89l60 TS10uJcjD+N+hQ9tz+eGaH9E4aLC6Xc0zpj0Sbi2MTA4P3KE0Rz1BW+0IO5g5o4PUACX KJslfxglYSXzZmu+We9ViENMIfOPEEz/+0xPAlYPwiYTjvipzfThGbBVLOtxtVbfrhCg k1NQ== X-Gm-Message-State: ACgBeo2tY49vGR30dLkZsfL3YmlPtMnLL6bqcyE4pcrbOPaZVQ/XyTs7 vKkdrtEQnscolWjlveeJjlQ= X-Google-Smtp-Source: AA6agR7LlZekoEWjZ5n/Wg/GDgLpru5Gphl27BzfTxD6/MFEeRDitbNtP1h9GWe2GssjwEnfpdtsMg== X-Received: by 2002:a05:6a00:8c8:b0:52c:887d:fa25 with SMTP id s8-20020a056a0008c800b0052c887dfa25mr5525719pfu.86.1659683252061; Fri, 05 Aug 2022 00:07:32 -0700 (PDT) Received: from RD-3580-24288.rt.l (42-72-229-62.emome-ip.hinet.net. [42.72.229.62]) by smtp.gmail.com with ESMTPSA id i5-20020a056a00224500b00525343b5047sm2191616pfu.76.2022.08.05.00.07.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 05 Aug 2022 00:07:31 -0700 (PDT) From: ChiaEn Wu To: lee.jones@linaro.org, daniel.thompson@linaro.org, jingoohan1@gmail.com, pavel@ucw.cz, robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, matthias.bgg@gmail.com, sre@kernel.org, chunfeng.yun@mediatek.com, gregkh@linuxfoundation.org, jic23@kernel.org, lars@metafoo.de, lgirdwood@gmail.com, broonie@kernel.org, linux@roeck-us.net, heikki.krogerus@linux.intel.com, deller@gmx.de, andy.shevchenko@gmail.com Cc: chiaen_wu@richtek.com, alice_chen@richtek.com, cy_huang@richtek.com, dri-devel@lists.freedesktop.org, linux-leds@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, linux-usb@vger.kernel.org, linux-iio@vger.kernel.org, linux-fbdev@vger.kernel.org, szunichen@gmail.com, AngeloGioacchino Del Regno Subject: [PATCH v7 09/13] iio: adc: mt6370: Add MediaTek MT6370 support Date: Fri, 5 Aug 2022 15:06:06 +0800 Message-Id: <20220805070610.3516-10-peterwu.pub@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220805070610.3516-1-peterwu.pub@gmail.com> References: <20220805070610.3516-1-peterwu.pub@gmail.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220805_000734_690917_8B0DC585 X-CRM114-Status: GOOD ( 25.10 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org From: ChiaEn Wu MediaTek MT6370 is a SubPMIC consisting of a single cell battery charger with ADC monitoring, RGB LEDs, dual channel flashlight, WLED backlight driver, display bias voltage supply, one general purpose LDO, and the USB Type-C & PD controller complies with the latest USB Type-C and PD standards. Add a support for the MT6370 ADC driver for system monitoring, including charger current, voltage, and temperature. Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: ChiaEn Wu Reviewed-by: Andy Shevchenko Acked-by: Jonathan Cameron --- v7 - Add AICR(100mA ~ 350mA), ICHG(100mA ~ 800mA) macros - Remove 400mA AICR and 900mA ICHG macros - Revise using 'if-else' to 'switch-case' in mt6370_adc_read_scale() where the adc channel is ibus or ibat --- drivers/iio/adc/Kconfig | 12 ++ drivers/iio/adc/Makefile | 1 + drivers/iio/adc/mt6370-adc.c | 305 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 318 insertions(+) create mode 100644 drivers/iio/adc/mt6370-adc.c diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 7fe5930..995cbb5 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -736,6 +736,18 @@ config MEDIATEK_MT6360_ADC is used in smartphones and tablets and supports a 11 channel general purpose ADC. +config MEDIATEK_MT6370_ADC + tristate "MediaTek MT6370 ADC driver" + depends on MFD_MT6370 + help + Say yes here to enable MediaTek MT6370 ADC support. + + This ADC driver provides 9 channels for system monitoring (charger + current, voltage, and temperature). + + This driver can also be built as a module. If so, the module + will be called "mt6370-adc". + config MEDIATEK_MT6577_AUXADC tristate "MediaTek AUXADC driver" depends on ARCH_MEDIATEK || COMPILE_TEST diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 1772a54..c6bc35f 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -68,6 +68,7 @@ obj-$(CONFIG_MCP320X) += mcp320x.o obj-$(CONFIG_MCP3422) += mcp3422.o obj-$(CONFIG_MCP3911) += mcp3911.o obj-$(CONFIG_MEDIATEK_MT6360_ADC) += mt6360-adc.o +obj-$(CONFIG_MEDIATEK_MT6370_ADC) += mt6370-adc.o obj-$(CONFIG_MEDIATEK_MT6577_AUXADC) += mt6577_auxadc.o obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o obj-$(CONFIG_MESON_SARADC) += meson_saradc.o diff --git a/drivers/iio/adc/mt6370-adc.c b/drivers/iio/adc/mt6370-adc.c new file mode 100644 index 0000000..2a46471 --- /dev/null +++ b/drivers/iio/adc/mt6370-adc.c @@ -0,0 +1,305 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2022 Richtek Technology Corp. + * + * Author: ChiaEn Wu + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define MT6370_REG_CHG_CTRL3 0x113 +#define MT6370_REG_CHG_CTRL7 0x117 +#define MT6370_REG_CHG_ADC 0x121 +#define MT6370_REG_ADC_DATA_H 0x14C + +#define MT6370_ADC_START_MASK BIT(0) +#define MT6370_ADC_IN_SEL_MASK GENMASK(7, 4) +#define MT6370_AICR_ICHG_MASK GENMASK(7, 2) + +#define MT6370_AICR_100_mA 0x0 +#define MT6370_AICR_150_mA 0x1 +#define MT6370_AICR_200_mA 0x2 +#define MT6370_AICR_250_mA 0x3 +#define MT6370_AICR_300_mA 0x4 +#define MT6370_AICR_350_mA 0x5 + +#define MT6370_ICHG_100_mA 0x0 +#define MT6370_ICHG_200_mA 0x1 +#define MT6370_ICHG_300_mA 0x2 +#define MT6370_ICHG_400_mA 0x3 +#define MT6370_ICHG_500_mA 0x4 +#define MT6370_ICHG_600_mA 0x5 +#define MT6370_ICHG_700_mA 0x6 +#define MT6370_ICHG_800_mA 0x7 + +#define ADC_CONV_TIME_MS 35 +#define ADC_CONV_POLLING_TIME_US 1000 + +struct mt6370_adc_data { + struct device *dev; + struct regmap *regmap; + /* + * This mutex lock is for preventing the different ADC channels + * from being read at the same time. + */ + struct mutex adc_lock; +}; + +static int mt6370_adc_read_channel(struct mt6370_adc_data *priv, int chan, + unsigned long addr, int *val) +{ + unsigned int reg_val; + __be16 be_val; + int ret; + + mutex_lock(&priv->adc_lock); + + reg_val = MT6370_ADC_START_MASK | + FIELD_PREP(MT6370_ADC_IN_SEL_MASK, addr); + ret = regmap_write(priv->regmap, MT6370_REG_CHG_ADC, reg_val); + if (ret) + goto adc_unlock; + + msleep(ADC_CONV_TIME_MS); + + ret = regmap_read_poll_timeout(priv->regmap, + MT6370_REG_CHG_ADC, reg_val, + !(reg_val & MT6370_ADC_START_MASK), + ADC_CONV_POLLING_TIME_US, + ADC_CONV_TIME_MS * MILLI * 3); + if (ret) { + dev_err(priv->dev, "Failed to read ADC register (%d)\n", ret); + goto adc_unlock; + } + + ret = regmap_raw_read(priv->regmap, MT6370_REG_ADC_DATA_H, + &be_val, sizeof(be_val)); + if (ret) + goto adc_unlock; + + *val = be16_to_cpu(be_val); + ret = IIO_VAL_INT; + +adc_unlock: + mutex_unlock(&priv->adc_lock); + + return ret; +} + +static int mt6370_adc_read_scale(struct mt6370_adc_data *priv, + int chan, int *val1, int *val2) +{ + unsigned int reg_val; + int ret; + + switch (chan) { + case MT6370_CHAN_VBAT: + case MT6370_CHAN_VSYS: + case MT6370_CHAN_CHG_VDDP: + *val1 = 5; + return IIO_VAL_INT; + case MT6370_CHAN_IBUS: + ret = regmap_read(priv->regmap, MT6370_REG_CHG_CTRL3, ®_val); + if (ret) + return ret; + + reg_val = FIELD_GET(MT6370_AICR_ICHG_MASK, reg_val); + switch (reg_val) { + case MT6370_AICR_100_mA: + case MT6370_AICR_150_mA: + case MT6370_AICR_200_mA: + case MT6370_AICR_250_mA: + case MT6370_AICR_300_mA: + case MT6370_AICR_350_mA: + *val1 = 3350; + break; + default: + *val1 = 5000; + break; + } + + *val2 = 100; + + return IIO_VAL_FRACTIONAL; + case MT6370_CHAN_IBAT: + ret = regmap_read(priv->regmap, MT6370_REG_CHG_CTRL7, ®_val); + if (ret) + return ret; + + reg_val = FIELD_GET(MT6370_AICR_ICHG_MASK, reg_val); + switch (reg_val) { + case MT6370_ICHG_100_mA: + case MT6370_ICHG_200_mA: + case MT6370_ICHG_300_mA: + case MT6370_ICHG_400_mA: + *val1 = 2375; + break; + case MT6370_ICHG_500_mA: + case MT6370_ICHG_600_mA: + case MT6370_ICHG_700_mA: + case MT6370_ICHG_800_mA: + *val1 = 2680; + break; + default: + *val1 = 5000; + break; + } + + *val2 = 100; + + return IIO_VAL_FRACTIONAL; + case MT6370_CHAN_VBUSDIV5: + *val1 = 25; + return IIO_VAL_INT; + case MT6370_CHAN_VBUSDIV2: + *val1 = 50; + return IIO_VAL_INT; + case MT6370_CHAN_TS_BAT: + *val1 = 25; + *val2 = 10000; + return IIO_VAL_FRACTIONAL; + case MT6370_CHAN_TEMP_JC: + *val1 = 2000; + return IIO_VAL_FRACTIONAL; + default: + return -EINVAL; + } +} + +static int mt6370_adc_read_offset(struct mt6370_adc_data *priv, + int chan, int *val) +{ + *val = -20; + + return IIO_VAL_INT; +} + +static int mt6370_adc_read_raw(struct iio_dev *iio_dev, + const struct iio_chan_spec *chan, + int *val, int *val2, long mask) +{ + struct mt6370_adc_data *priv = iio_priv(iio_dev); + + switch (mask) { + case IIO_CHAN_INFO_RAW: + return mt6370_adc_read_channel(priv, chan->channel, + chan->address, val); + case IIO_CHAN_INFO_SCALE: + return mt6370_adc_read_scale(priv, chan->channel, val, val2); + case IIO_CHAN_INFO_OFFSET: + return mt6370_adc_read_offset(priv, chan->channel, val); + default: + return -EINVAL; + } +} + +static const char * const mt6370_channel_labels[MT6370_CHAN_MAX] = { + [MT6370_CHAN_VBUSDIV5] = "vbusdiv5", + [MT6370_CHAN_VBUSDIV2] = "vbusdiv2", + [MT6370_CHAN_VSYS] = "vsys", + [MT6370_CHAN_VBAT] = "vbat", + [MT6370_CHAN_TS_BAT] = "ts_bat", + [MT6370_CHAN_IBUS] = "ibus", + [MT6370_CHAN_IBAT] = "ibat", + [MT6370_CHAN_CHG_VDDP] = "chg_vddp", + [MT6370_CHAN_TEMP_JC] = "temp_jc", +}; + +static int mt6370_adc_read_label(struct iio_dev *iio_dev, + struct iio_chan_spec const *chan, char *label) +{ + return sysfs_emit(label, "%s\n", mt6370_channel_labels[chan->channel]); +} + +static const struct iio_info mt6370_adc_iio_info = { + .read_raw = mt6370_adc_read_raw, + .read_label = mt6370_adc_read_label, +}; + +#define MT6370_ADC_CHAN(_idx, _type, _addr, _extra_info) { \ + .type = _type, \ + .channel = MT6370_CHAN_##_idx, \ + .address = _addr, \ + .scan_index = MT6370_CHAN_##_idx, \ + .indexed = 1, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE) | \ + _extra_info, \ +} + +static const struct iio_chan_spec mt6370_adc_channels[] = { + MT6370_ADC_CHAN(VBUSDIV5, IIO_VOLTAGE, 1, 0), + MT6370_ADC_CHAN(VBUSDIV2, IIO_VOLTAGE, 2, 0), + MT6370_ADC_CHAN(VSYS, IIO_VOLTAGE, 3, 0), + MT6370_ADC_CHAN(VBAT, IIO_VOLTAGE, 4, 0), + MT6370_ADC_CHAN(TS_BAT, IIO_VOLTAGE, 6, 0), + MT6370_ADC_CHAN(IBUS, IIO_CURRENT, 8, 0), + MT6370_ADC_CHAN(IBAT, IIO_CURRENT, 9, 0), + MT6370_ADC_CHAN(CHG_VDDP, IIO_VOLTAGE, 11, 0), + MT6370_ADC_CHAN(TEMP_JC, IIO_TEMP, 12, BIT(IIO_CHAN_INFO_OFFSET)), +}; + +static int mt6370_adc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct mt6370_adc_data *priv; + struct iio_dev *indio_dev; + struct regmap *regmap; + int ret; + + regmap = dev_get_regmap(pdev->dev.parent, NULL); + if (!regmap) + return dev_err_probe(dev, -ENODEV, "Failed to get regmap\n"); + + indio_dev = devm_iio_device_alloc(dev, sizeof(*priv)); + if (!indio_dev) + return -ENOMEM; + + priv = iio_priv(indio_dev); + priv->dev = dev; + priv->regmap = regmap; + mutex_init(&priv->adc_lock); + + ret = regmap_write(priv->regmap, MT6370_REG_CHG_ADC, 0); + if (ret) + return dev_err_probe(dev, ret, "Failed to reset ADC\n"); + + indio_dev->name = "mt6370-adc"; + indio_dev->info = &mt6370_adc_iio_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = mt6370_adc_channels; + indio_dev->num_channels = ARRAY_SIZE(mt6370_adc_channels); + + return devm_iio_device_register(dev, indio_dev); +} + +static const struct of_device_id mt6370_adc_of_id[] = { + { .compatible = "mediatek,mt6370-adc", }, + {} +}; +MODULE_DEVICE_TABLE(of, mt6370_adc_of_id); + +static struct platform_driver mt6370_adc_driver = { + .driver = { + .name = "mt6370-adc", + .of_match_table = mt6370_adc_of_id, + }, + .probe = mt6370_adc_probe, +}; +module_platform_driver(mt6370_adc_driver); + +MODULE_AUTHOR("ChiaEn Wu "); +MODULE_DESCRIPTION("MT6370 ADC Driver"); +MODULE_LICENSE("GPL v2"); From patchwork Fri Aug 5 07:06:07 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: ChiaEn Wu X-Patchwork-Id: 12936968 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 94D77C00140 for ; Fri, 5 Aug 2022 07:15:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=dbGHVvUYKvbuVSsnrhim3prrdXI99LOCDU37DwQaC7Q=; b=ACX8yT3JwsemnhZ/fduqec8gGw FtxAvu3dXXO+DLxDonsGq18hQFFJM5nV/xiD+g6edxdVQvhAAFnbV7Po3J8V+c4+RTQzn6Uk+8zSG 2K1H+MRgglkFzzO7l8yivCY60d8AUhfN6PGSX7V7Gb+1+bzttTmXjOO3odcUCC9+IKln/DrkNv3LP hxsdfsEU6mf1M1jKcCZTOeKvsVdRDismwBisZG80xcXwMkR0tojNYd4Rn3Z+UTafFuLhQQsLO093L HV3iTk40uYLhEPxsSVamkIwnpkFGv86zymPV/umnrou3alVINFZitDR4T1gMEPY/+btr8zpSUyUMW p5iMko6A==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1oJrYE-00ClHy-Vu; Fri, 05 Aug 2022 07:15:19 +0000 Received: from mail-pg1-x529.google.com ([2607:f8b0:4864:20::529]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1oJrQv-00ChXL-9e; Fri, 05 Aug 2022 07:07:50 +0000 Received: by mail-pg1-x529.google.com with SMTP id f65so1922787pgc.12; Fri, 05 Aug 2022 00:07:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc; bh=dbGHVvUYKvbuVSsnrhim3prrdXI99LOCDU37DwQaC7Q=; b=H85gpgMP/nOryhKccb4uKFVmE4U6lKXGSPMGzbcKnLuT4FM35MUlAUzeheVqi9CN42 01w78HMvQwfRNVPhxu7cNEDtTLvZJk+qMINRFW6+wzSYgZ1stAu8nCP9rz8LF280Itol +djVM1lLgjOrKnRTLWxgKVu2MN7PMXAc6g9Z3344Rux5T0Kn6mJUbdVTodFRGS6P+nZK QRVj/JbeGNbwdOr5pQl6MxKRGeZ/DFj8sL7bMdGJLcGjyYLmjFRW9mCi930BtF/JBos2 IjVPOqEaKkwBScQn1s5aH/J7hkjKP3x3vHN7Eq1gDVtioRLz8fx8Yahp5GEatCm02QfO jeMw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc; bh=dbGHVvUYKvbuVSsnrhim3prrdXI99LOCDU37DwQaC7Q=; b=bE7Pr0qbnVVRVMozhrko4xiyS3yAtPUOA/WB6W3ur/mR8MzPYpjBZvHT4t6ICYVnxw 9baPkSnIPMpfXsLMWwbu6+JzkNZPVESInF841VDge8MvFLRls5zh3AuNelhJ4ezfj9fK jaB8vcw5vM43+n6QKHjnOd4dD6Eg50F7jXYiQn4uxfBL1/sxg24oMLJzTndBlKbhbv0J NBAhSH5eh9UcB+JMSkZqAVPQEWsPcdgHBHHGXkeAA3GOlPVJJa6U9hJcKCO67mpcUW1W 1dUNComJ1SfYRhNeodthtUiEr1ysfbwsSp3wz4ZOVVA8LgfZhWt0zgc4q+VOOC6kEpZ7 Jx4g== X-Gm-Message-State: ACgBeo3Yqt/bo8Jb5krchjYASD9bTtrhpj1DjxQTRqZDhwDRODtyTuMT dzCDJ0BgJ3tLE3GyfGTNCRuTZ0+9sWQ= X-Google-Smtp-Source: AA6agR4SoHrg3NJHQpVOE7U7mCh7lWYb78k8fNS+FYqolGTW5EnRWZHMFv9gcuF1dkqwq3odLN3yNQ== X-Received: by 2002:a05:6a00:188e:b0:52e:2606:a805 with SMTP id x14-20020a056a00188e00b0052e2606a805mr5384831pfh.49.1659683259008; Fri, 05 Aug 2022 00:07:39 -0700 (PDT) Received: from RD-3580-24288.rt.l (42-72-229-62.emome-ip.hinet.net. [42.72.229.62]) by smtp.gmail.com with ESMTPSA id i5-20020a056a00224500b00525343b5047sm2191616pfu.76.2022.08.05.00.07.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 05 Aug 2022 00:07:38 -0700 (PDT) From: ChiaEn Wu To: lee.jones@linaro.org, daniel.thompson@linaro.org, jingoohan1@gmail.com, pavel@ucw.cz, robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, matthias.bgg@gmail.com, sre@kernel.org, chunfeng.yun@mediatek.com, gregkh@linuxfoundation.org, jic23@kernel.org, lars@metafoo.de, lgirdwood@gmail.com, broonie@kernel.org, linux@roeck-us.net, heikki.krogerus@linux.intel.com, deller@gmx.de, andy.shevchenko@gmail.com Cc: chiaen_wu@richtek.com, alice_chen@richtek.com, cy_huang@richtek.com, dri-devel@lists.freedesktop.org, linux-leds@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, linux-usb@vger.kernel.org, linux-iio@vger.kernel.org, linux-fbdev@vger.kernel.org, szunichen@gmail.com Subject: [PATCH v7 10/13] power: supply: mt6370: Add MediaTek MT6370 charger driver Date: Fri, 5 Aug 2022 15:06:07 +0800 Message-Id: <20220805070610.3516-11-peterwu.pub@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220805070610.3516-1-peterwu.pub@gmail.com> References: <20220805070610.3516-1-peterwu.pub@gmail.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220805_000745_456215_B2F3B2AB X-CRM114-Status: GOOD ( 21.87 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org From: ChiaEn Wu MediaTek MT6370 is a SubPMIC consisting of a single cell battery charger with ADC monitoring, RGB LEDs, dual channel flashlight, WLED backlight driver, display bias voltage supply, one general purpose LDO, and the USB Type-C & PD controller complies with the latest USB Type-C and PD standards. Add a support for the MediaTek MT6370 Charger driver. The charger module of MT6370 supports High-Accuracy Voltage/Current Regulation, Average Input Current Regulation, Battery Temperature Sensing, Over-Temperature Protection, DPDM Detection for BC1.2. Signed-off-by: ChiaEn Wu Reviewed-by: Andy Shevchenko --- v7 - Revise the method to enable/disable irq - Revise all 'if (ret < 0)' to 'if (ret)' after using mt6370_chg_field_set/get() - Revise all 'OTG' text --- drivers/power/supply/Kconfig | 14 + drivers/power/supply/Makefile | 1 + drivers/power/supply/mt6370-charger.c | 965 ++++++++++++++++++++++++++++++++++ 3 files changed, 980 insertions(+) create mode 100644 drivers/power/supply/mt6370-charger.c diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig index 1aa8323..591deb8 100644 --- a/drivers/power/supply/Kconfig +++ b/drivers/power/supply/Kconfig @@ -619,6 +619,20 @@ config CHARGER_MT6360 Average Input Current Regulation, Battery Temperature Sensing, Over-Temperature Protection, DPDM Detection for BC1.2. +config CHARGER_MT6370 + tristate "MediaTek MT6370 Charger Driver" + depends on MFD_MT6370 + depends on REGULATOR + select LINEAR_RANGES + help + Say Y here to enable MT6370 Charger Part. + The device supports High-Accuracy Voltage/Current Regulation, + Average Input Current Regulation, Battery Temperature Sensing, + Over-Temperature Protection, DPDM Detection for BC1.2. + + This driver can also be built as a module. If so, the module + will be called "mt6370-charger". + config CHARGER_QCOM_SMBB tristate "Qualcomm Switch-Mode Battery Charger and Boost" depends on MFD_SPMI_PMIC || COMPILE_TEST diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile index 7f02f36..8c95276 100644 --- a/drivers/power/supply/Makefile +++ b/drivers/power/supply/Makefile @@ -82,6 +82,7 @@ obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o obj-$(CONFIG_CHARGER_MP2629) += mp2629_charger.o obj-$(CONFIG_CHARGER_MT6360) += mt6360_charger.o +obj-$(CONFIG_CHARGER_MT6370) += mt6370-charger.o obj-$(CONFIG_CHARGER_QCOM_SMBB) += qcom_smbb.o obj-$(CONFIG_CHARGER_BQ2415X) += bq2415x_charger.o obj-$(CONFIG_CHARGER_BQ24190) += bq24190_charger.o diff --git a/drivers/power/supply/mt6370-charger.c b/drivers/power/supply/mt6370-charger.c new file mode 100644 index 0000000..42fddc3 --- /dev/null +++ b/drivers/power/supply/mt6370-charger.c @@ -0,0 +1,965 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2022 Richtek Technology Corp. + * + * Author: ChiaEn Wu + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MT6370_REG_CHG_CTRL1 0x111 +#define MT6370_REG_CHG_CTRL2 0x112 +#define MT6370_REG_CHG_CTRL3 0x113 +#define MT6370_REG_CHG_CTRL4 0x114 +#define MT6370_REG_CHG_CTRL5 0x115 +#define MT6370_REG_CHG_CTRL6 0x116 +#define MT6370_REG_CHG_CTRL7 0x117 +#define MT6370_REG_CHG_CTRL8 0x118 +#define MT6370_REG_CHG_CTRL9 0x119 +#define MT6370_REG_CHG_CTRL10 0x11A +#define MT6370_REG_DEVICE_TYPE 0x122 +#define MT6370_REG_USB_STATUS1 0x127 +#define MT6370_REG_CHG_STAT 0x14A +#define MT6370_REG_FLED_EN 0x17E +#define MT6370_REG_CHG_STAT1 0X1D0 +#define MT6370_REG_OVPCTRL_STAT 0x1D8 + +#define MT6370_VOBST_MASK GENMASK(7, 2) +#define MT6370_OTG_PIN_EN_MASK BIT(1) +#define MT6370_OPA_MODE_MASK BIT(0) +#define MT6370_OTG_OC_MASK GENMASK(2, 0) + +#define MT6370_MIVR_IBUS_TH_100_mA 100000 +#define MT6370_ADC_CHAN_IBUS 5 +#define MT6370_ADC_CHAN_MAX 9 + +enum mt6370_chg_reg_field { + /* MT6370_REG_CHG_CTRL2 */ + F_IINLMTSEL, F_CFO_EN, F_CHG_EN, + /* MT6370_REG_CHG_CTRL3 */ + F_IAICR, F_AICR_EN, F_ILIM_EN, + /* MT6370_REG_CHG_CTRL4 */ + F_VOREG, + /* MT6370_REG_CHG_CTRL6 */ + F_VMIVR, + /* MT6370_REG_CHG_CTRL7 */ + F_ICHG, + /* MT6370_REG_CHG_CTRL8 */ + F_IPREC, + /* MT6370_REG_CHG_CTRL9 */ + F_IEOC, + /* MT6370_REG_DEVICE_TYPE */ + F_USBCHGEN, + /* MT6370_REG_USB_STATUS1 */ + F_USB_STAT, F_CHGDET, + /* MT6370_REG_CHG_STAT */ + F_CHG_STAT, F_BOOST_STAT, F_VBAT_LVL, + /* MT6370_REG_FLED_EN */ + F_FL_STROBE, + /* MT6370_REG_CHG_STAT1 */ + F_CHG_MIVR_STAT, + /* MT6370_REG_OVPCTRL_STAT */ + F_UVP_D_STAT, + F_MAX +}; + +enum mt6370_irq { + MT6370_IRQ_ATTACH_I = 0, + MT6370_IRQ_UVP_D_EVT, + MT6370_IRQ_MIVR, + MT6370_IRQ_MAX +}; + +struct mt6370_priv { + struct device *dev; + struct iio_channel *iio_adcs; + struct mutex attach_lock; + struct power_supply *psy; + struct regmap *regmap; + struct regmap_field *rmap_fields[F_MAX]; + struct regulator_dev *rdev; + struct workqueue_struct *wq; + struct work_struct bc12_work; + struct delayed_work mivr_dwork; + unsigned int irq_nums[MT6370_IRQ_MAX]; + int attach; + int psy_usb_type; + bool pwr_rdy; +}; + +enum mt6370_usb_status { + MT6370_USB_STAT_NO_VBUS = 0, + MT6370_USB_STAT_VBUS_FLOW_IS_UNDER_GOING, + MT6370_USB_STAT_SDP, + MT6370_USB_STAT_SDP_NSTD, + MT6370_USB_STAT_DCP, + MT6370_USB_STAT_CDP, + MT6370_USB_STAT_MAX +}; + +struct mt6370_chg_field { + const char *name; + const struct linear_range *range; + struct reg_field field; +}; + +enum { + MT6370_RANGE_F_IAICR = 0, + MT6370_RANGE_F_VOREG, + MT6370_RANGE_F_VMIVR, + MT6370_RANGE_F_ICHG, + MT6370_RANGE_F_IPREC, + MT6370_RANGE_F_IEOC, + MT6370_RANGE_F_MAX +}; + +#define MT6370_CHG_LINEAR_RANGE(_rfd, _min, _min_sel, _max_sel, _step) \ +[_rfd] = { \ + .min = _min, \ + .min_sel = _min_sel, \ + .max_sel = _max_sel, \ + .step = _step, \ +} + +static const struct linear_range mt6370_chg_ranges[MT6370_RANGE_F_MAX] = { + MT6370_CHG_LINEAR_RANGE(MT6370_RANGE_F_IAICR, 100000, 0x0, 0x3F, 50000), + MT6370_CHG_LINEAR_RANGE(MT6370_RANGE_F_VOREG, 3900000, 0x0, 0x51, 10000), + MT6370_CHG_LINEAR_RANGE(MT6370_RANGE_F_VMIVR, 3900000, 0x0, 0x5F, 100000), + MT6370_CHG_LINEAR_RANGE(MT6370_RANGE_F_ICHG, 900000, 0x08, 0x31, 100000), + MT6370_CHG_LINEAR_RANGE(MT6370_RANGE_F_IPREC, 100000, 0x0, 0x0F, 50000), + MT6370_CHG_LINEAR_RANGE(MT6370_RANGE_F_IEOC, 100000, 0x0, 0x0F, 50000), +}; + +#define MT6370_CHG_FIELD(_fd, _reg, _lsb, _msb) \ +[_fd] = { \ + .name = #_fd, \ + .range = NULL, \ + .field = REG_FIELD(_reg, _lsb, _msb), \ +} + +#define MT6370_CHG_FIELD_RANGE(_fd, _reg, _lsb, _msb) \ +[_fd] = { \ + .name = #_fd, \ + .range = &mt6370_chg_ranges[MT6370_RANGE_##_fd], \ + .field = REG_FIELD(_reg, _lsb, _msb), \ +} + +static const struct mt6370_chg_field mt6370_chg_fields[F_MAX] = { + MT6370_CHG_FIELD(F_IINLMTSEL, MT6370_REG_CHG_CTRL2, 2, 3), + MT6370_CHG_FIELD(F_CFO_EN, MT6370_REG_CHG_CTRL2, 1, 1), + MT6370_CHG_FIELD(F_CHG_EN, MT6370_REG_CHG_CTRL2, 0, 0), + MT6370_CHG_FIELD_RANGE(F_IAICR, MT6370_REG_CHG_CTRL3, 2, 7), + MT6370_CHG_FIELD(F_AICR_EN, MT6370_REG_CHG_CTRL3, 1, 1), + MT6370_CHG_FIELD(F_ILIM_EN, MT6370_REG_CHG_CTRL3, 0, 0), + MT6370_CHG_FIELD_RANGE(F_VOREG, MT6370_REG_CHG_CTRL4, 1, 7), + MT6370_CHG_FIELD_RANGE(F_VMIVR, MT6370_REG_CHG_CTRL6, 1, 7), + MT6370_CHG_FIELD_RANGE(F_ICHG, MT6370_REG_CHG_CTRL7, 2, 7), + MT6370_CHG_FIELD_RANGE(F_IPREC, MT6370_REG_CHG_CTRL8, 0, 3), + MT6370_CHG_FIELD_RANGE(F_IEOC, MT6370_REG_CHG_CTRL9, 4, 7), + MT6370_CHG_FIELD(F_USBCHGEN, MT6370_REG_DEVICE_TYPE, 7, 7), + MT6370_CHG_FIELD(F_USB_STAT, MT6370_REG_USB_STATUS1, 4, 6), + MT6370_CHG_FIELD(F_CHGDET, MT6370_REG_USB_STATUS1, 3, 3), + MT6370_CHG_FIELD(F_CHG_STAT, MT6370_REG_CHG_STAT, 6, 7), + MT6370_CHG_FIELD(F_BOOST_STAT, MT6370_REG_CHG_STAT, 3, 3), + MT6370_CHG_FIELD(F_VBAT_LVL, MT6370_REG_CHG_STAT, 5, 5), + MT6370_CHG_FIELD(F_FL_STROBE, MT6370_REG_FLED_EN, 2, 2), + MT6370_CHG_FIELD(F_CHG_MIVR_STAT, MT6370_REG_CHG_STAT1, 6, 6), + MT6370_CHG_FIELD(F_UVP_D_STAT, MT6370_REG_OVPCTRL_STAT, 4, 4), +}; + +static inline int mt6370_chg_field_get(struct mt6370_priv *priv, + enum mt6370_chg_reg_field fd, + unsigned int *val) +{ + int ret; + unsigned int reg_val; + + ret = regmap_field_read(priv->rmap_fields[fd], ®_val); + if (ret) + return ret; + + if (mt6370_chg_fields[fd].range) + return linear_range_get_value(mt6370_chg_fields[fd].range, + reg_val, val); + + *val = reg_val; + return 0; +} + +static inline int mt6370_chg_field_set(struct mt6370_priv *priv, + enum mt6370_chg_reg_field fd, + unsigned int val) +{ + int ret; + bool f; + const struct linear_range *r; + + if (mt6370_chg_fields[fd].range) { + r = mt6370_chg_fields[fd].range; + + if (fd == F_VMIVR) { + ret = linear_range_get_selector_high(r, val, &val, &f); + if (ret) + val = r->max_sel; + } else { + linear_range_get_selector_within(r, val, &val); + } + } + + return regmap_field_write(priv->rmap_fields[fd], val); +} + +enum { + MT6370_CHG_STAT_READY = 0, + MT6370_CHG_STAT_CHARGE_IN_PROGRESS, + MT6370_CHG_STAT_DONE, + MT6370_CHG_STAT_FAULT, + MT6370_CHG_STAT_MAX +}; + +enum { + MT6370_ATTACH_STAT_DETACH = 0, + MT6370_ATTACH_STAT_ATTACH_BC12_NOT_DONE, + MT6370_ATTACH_STAT_ATTACH_BC12_DONE, + MT6370_ATTACH_STAT_ATTACH_MAX +}; + +static int mt6370_chg_otg_of_parse_cb(struct device_node *of, + const struct regulator_desc *rdesc, + struct regulator_config *rcfg) +{ + struct mt6370_priv *priv = rcfg->driver_data; + + rcfg->ena_gpiod = fwnode_gpiod_get_index(of_fwnode_handle(of), + "enable", 0, GPIOD_OUT_LOW | + GPIOD_FLAGS_BIT_NONEXCLUSIVE, + rdesc->name); + if (IS_ERR(rcfg->ena_gpiod)) { + rcfg->ena_gpiod = NULL; + return 0; + } + + return regmap_update_bits(priv->regmap, MT6370_REG_CHG_CTRL1, + MT6370_OTG_PIN_EN_MASK, + MT6370_OTG_PIN_EN_MASK); +} + +static void mt6370_chg_bc12_work_func(struct work_struct *work) +{ + struct mt6370_priv *priv = container_of(work, struct mt6370_priv, + bc12_work); + int ret; + bool rpt_psy = false; + unsigned int attach, usb_stat; + + mutex_lock(&priv->attach_lock); + attach = priv->attach; + + switch (attach) { + case MT6370_ATTACH_STAT_DETACH: + usb_stat = 0; + break; + case MT6370_ATTACH_STAT_ATTACH_BC12_DONE: + ret = mt6370_chg_field_get(priv, F_USB_STAT, &usb_stat); + if (ret) { + dev_err(priv->dev, "Failed to get USB status\n"); + goto bc12_work_func_out; + } + break; + case MT6370_ATTACH_STAT_ATTACH_BC12_NOT_DONE: + ret = mt6370_chg_field_set(priv, F_USBCHGEN, attach); + if (ret) + dev_err(priv->dev, "Failed to enable USB CHG EN\n"); + goto bc12_work_func_out; + default: + dev_err(priv->dev, "Invalid attach state\n"); + goto bc12_work_func_out; + } + + rpt_psy = true; + + switch (usb_stat) { + case MT6370_USB_STAT_SDP: + case MT6370_USB_STAT_SDP_NSTD: + priv->psy_usb_type = POWER_SUPPLY_USB_TYPE_SDP; + break; + case MT6370_USB_STAT_DCP: + priv->psy_usb_type = POWER_SUPPLY_USB_TYPE_DCP; + break; + case MT6370_USB_STAT_CDP: + priv->psy_usb_type = POWER_SUPPLY_USB_TYPE_CDP; + break; + case MT6370_USB_STAT_NO_VBUS: + case MT6370_USB_STAT_VBUS_FLOW_IS_UNDER_GOING: + default: + priv->psy_usb_type = POWER_SUPPLY_USB_TYPE_UNKNOWN; + break; + } + +bc12_work_func_out: + mutex_unlock(&priv->attach_lock); + + if (rpt_psy) + power_supply_changed(priv->psy); +} + +static int mt6370_chg_toggle_cfo(struct mt6370_priv *priv) +{ + int ret; + unsigned int fl_strobe; + + /* check if flash led in strobe mode */ + ret = mt6370_chg_field_get(priv, F_FL_STROBE, &fl_strobe); + if (ret) { + dev_err(priv->dev, "Failed to get FL_STROBE_EN\n"); + return ret; + } + + if (fl_strobe) { + dev_err(priv->dev, "Flash led is still in strobe mode\n"); + return ret; + } + + /* cfo off */ + ret = mt6370_chg_field_set(priv, F_CFO_EN, 0); + if (ret) { + dev_err(priv->dev, "Failed to disable CFO_EN\n"); + return ret; + } + + /* cfo on */ + ret = mt6370_chg_field_set(priv, F_CFO_EN, 1); + if (ret) + dev_err(priv->dev, "Failed to enable CFO_EN\n"); + + return ret; +} + +static int mt6370_chg_read_adc_chan(struct mt6370_priv *priv, unsigned int chan, + int *val) +{ + int ret; + + if (chan >= MT6370_ADC_CHAN_MAX) + return -EINVAL; + + ret = iio_read_channel_processed(&priv->iio_adcs[chan], val); + if (ret) + dev_err(priv->dev, "Failed to read ADC\n"); + + return ret; +} + +static void mt6370_chg_mivr_dwork_func(struct work_struct *work) +{ + struct mt6370_priv *priv = container_of(work, struct mt6370_priv, + mivr_dwork.work); + int ret; + unsigned int mivr_stat, ibus; + + ret = mt6370_chg_field_get(priv, F_CHG_MIVR_STAT, &mivr_stat); + if (ret) { + dev_err(priv->dev, "Failed to get mivr state\n"); + goto mivr_handler_out; + } + + if (!mivr_stat) + goto mivr_handler_out; + + ret = mt6370_chg_read_adc_chan(priv, MT6370_ADC_CHAN_IBUS, &ibus); + if (ret) { + dev_err(priv->dev, "Failed to get ibus\n"); + goto mivr_handler_out; + } + + if (ibus < MT6370_MIVR_IBUS_TH_100_mA) { + ret = mt6370_chg_toggle_cfo(priv); + if (ret) + dev_err(priv->dev, "Failed to toggle cfo\n"); + } + +mivr_handler_out: + enable_irq(priv->irq_nums[MT6370_IRQ_MIVR]); + pm_relax(priv->dev); +} + +static void mt6370_chg_pwr_rdy_check(struct mt6370_priv *priv) +{ + int ret; + unsigned int pwr_rdy, otg_en; + union power_supply_propval val; + + /* Check in OTG mode or not */ + ret = mt6370_chg_field_get(priv, F_BOOST_STAT, &otg_en); + if (ret) { + dev_err(priv->dev, "Failed to get OTG state\n"); + return; + } + + if (otg_en) + return; + + ret = mt6370_chg_field_get(priv, F_UVP_D_STAT, &pwr_rdy); + if (ret) { + dev_err(priv->dev, "Failed to get pwr_rdy state reg\n"); + return; + } + + val.intval = !pwr_rdy; + + ret = power_supply_set_property(priv->psy, POWER_SUPPLY_PROP_ONLINE, + &val); + if (ret) + dev_err(priv->dev, "Failed to start attach/detach flow\n"); +} + +static int mt6370_chg_get_online(struct mt6370_priv *priv, + union power_supply_propval *val) +{ + mutex_lock(&priv->attach_lock); + val->intval = !!priv->attach; + mutex_unlock(&priv->attach_lock); + + return 0; +} + +static int mt6370_chg_get_status(struct mt6370_priv *priv, + union power_supply_propval *val) +{ + int ret; + unsigned int chg_stat; + union power_supply_propval online; + + ret = power_supply_get_property(priv->psy, POWER_SUPPLY_PROP_ONLINE, + &online); + if (ret) { + dev_err(priv->dev, "Failed to get online status\n"); + return ret; + } + + if (!online.intval) { + val->intval = POWER_SUPPLY_STATUS_DISCHARGING; + return 0; + } + + ret = mt6370_chg_field_get(priv, F_CHG_STAT, &chg_stat); + if (ret) + return ret; + + switch (chg_stat) { + case MT6370_CHG_STAT_READY: + case MT6370_CHG_STAT_FAULT: + val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; + return ret; + case MT6370_CHG_STAT_CHARGE_IN_PROGRESS: + val->intval = POWER_SUPPLY_STATUS_CHARGING; + return ret; + case MT6370_CHG_STAT_DONE: + val->intval = POWER_SUPPLY_STATUS_FULL; + return ret; + default: + val->intval = POWER_SUPPLY_STATUS_UNKNOWN; + return ret; + } +} + +static int mt6370_chg_get_charge_type(struct mt6370_priv *priv, + union power_supply_propval *val) +{ + int type, ret; + unsigned int chg_stat, vbat_lvl; + + ret = mt6370_chg_field_get(priv, F_CHG_STAT, &chg_stat); + if (ret) + return ret; + + ret = mt6370_chg_field_get(priv, F_VBAT_LVL, &vbat_lvl); + if (ret) + return ret; + + switch (chg_stat) { + case MT6370_CHG_STAT_CHARGE_IN_PROGRESS: + if (vbat_lvl) + type = POWER_SUPPLY_CHARGE_TYPE_FAST; + else + type = POWER_SUPPLY_CHARGE_TYPE_TRICKLE; + break; + case MT6370_CHG_STAT_READY: + case MT6370_CHG_STAT_DONE: + case MT6370_CHG_STAT_FAULT: + default: + type = POWER_SUPPLY_CHARGE_TYPE_NONE; + break; + } + + val->intval = type; + + return 0; +} + +static int mt6370_chg_set_online(struct mt6370_priv *priv, + const union power_supply_propval *val) +{ + bool pwr_rdy = !!val->intval; + + mutex_lock(&priv->attach_lock); + if (pwr_rdy == !!priv->attach) { + dev_err(priv->dev, "pwr_rdy is same(%d)\n", pwr_rdy); + mutex_unlock(&priv->attach_lock); + return 0; + } + + priv->attach = pwr_rdy; + mutex_unlock(&priv->attach_lock); + + if (!queue_work(priv->wq, &priv->bc12_work)) + dev_err(priv->dev, "bc12 work has already queued\n"); + + return 0; +} + +static int mt6370_chg_get_property(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct mt6370_priv *priv = power_supply_get_drvdata(psy); + + switch (psp) { + case POWER_SUPPLY_PROP_ONLINE: + return mt6370_chg_get_online(priv, val); + case POWER_SUPPLY_PROP_STATUS: + return mt6370_chg_get_status(priv, val); + case POWER_SUPPLY_PROP_CHARGE_TYPE: + return mt6370_chg_get_charge_type(priv, val); + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: + return mt6370_chg_field_get(priv, F_ICHG, &val->intval); + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: + val->intval = linear_range_get_max_value(&mt6370_chg_ranges[MT6370_RANGE_F_ICHG]); + return 0; + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: + return mt6370_chg_field_get(priv, F_VOREG, &val->intval); + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX: + val->intval = linear_range_get_max_value(&mt6370_chg_ranges[MT6370_RANGE_F_VOREG]); + return 0; + case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: + return mt6370_chg_field_get(priv, F_IAICR, &val->intval); + case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT: + return mt6370_chg_field_get(priv, F_VMIVR, &val->intval); + case POWER_SUPPLY_PROP_PRECHARGE_CURRENT: + return mt6370_chg_field_get(priv, F_IPREC, &val->intval); + case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT: + return mt6370_chg_field_get(priv, F_IEOC, &val->intval); + case POWER_SUPPLY_PROP_USB_TYPE: + val->intval = priv->psy_usb_type; + return 0; + default: + return -EINVAL; + } +} + +static int mt6370_chg_set_property(struct power_supply *psy, + enum power_supply_property psp, + const union power_supply_propval *val) +{ + struct mt6370_priv *priv = power_supply_get_drvdata(psy); + + switch (psp) { + case POWER_SUPPLY_PROP_ONLINE: + return mt6370_chg_set_online(priv, val); + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: + return mt6370_chg_field_set(priv, F_ICHG, val->intval); + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: + return mt6370_chg_field_set(priv, F_VOREG, val->intval); + case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: + return mt6370_chg_field_set(priv, F_IAICR, val->intval); + case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT: + return mt6370_chg_field_set(priv, F_VMIVR, val->intval); + case POWER_SUPPLY_PROP_PRECHARGE_CURRENT: + return mt6370_chg_field_set(priv, F_IPREC, val->intval); + case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT: + return mt6370_chg_field_set(priv, F_IEOC, val->intval); + default: + return -EINVAL; + } +} + +static int mt6370_chg_property_is_writeable(struct power_supply *psy, + enum power_supply_property psp) +{ + switch (psp) { + case POWER_SUPPLY_PROP_ONLINE: + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: + case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: + case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT: + case POWER_SUPPLY_PROP_PRECHARGE_CURRENT: + case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT: + return 1; + default: + return 0; + } +} + +static enum power_supply_property mt6370_chg_properties[] = { + POWER_SUPPLY_PROP_ONLINE, + POWER_SUPPLY_PROP_STATUS, + POWER_SUPPLY_PROP_CHARGE_TYPE, + POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT, + POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, + POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, + POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX, + POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, + POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT, + POWER_SUPPLY_PROP_PRECHARGE_CURRENT, + POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT, + POWER_SUPPLY_PROP_USB_TYPE, +}; + +static enum power_supply_usb_type mt6370_chg_usb_types[] = { + POWER_SUPPLY_USB_TYPE_UNKNOWN, + POWER_SUPPLY_USB_TYPE_SDP, + POWER_SUPPLY_USB_TYPE_CDP, + POWER_SUPPLY_USB_TYPE_DCP, +}; + +static const struct power_supply_desc mt6370_chg_psy_desc = { + .name = "mt6370-charger", + .type = POWER_SUPPLY_TYPE_USB, + .properties = mt6370_chg_properties, + .num_properties = ARRAY_SIZE(mt6370_chg_properties), + .get_property = mt6370_chg_get_property, + .set_property = mt6370_chg_set_property, + .property_is_writeable = mt6370_chg_property_is_writeable, + .usb_types = mt6370_chg_usb_types, + .num_usb_types = ARRAY_SIZE(mt6370_chg_usb_types), +}; + +static const struct regulator_ops mt6370_chg_otg_ops = { + .list_voltage = regulator_list_voltage_linear, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_current_limit = regulator_set_current_limit_regmap, + .get_current_limit = regulator_get_current_limit_regmap, +}; + +static const u32 mt6370_chg_otg_oc_ma[] = { + 500000, 700000, 1100000, 1300000, 1800000, 2100000, 2400000, +}; + +static const struct regulator_desc mt6370_chg_otg_rdesc = { + .of_match = "usb-otg-vbus-regulator", + .of_parse_cb = mt6370_chg_otg_of_parse_cb, + .name = "mt6370-usb-otg-vbus", + .ops = &mt6370_chg_otg_ops, + .owner = THIS_MODULE, + .type = REGULATOR_VOLTAGE, + .min_uV = 4425000, + .uV_step = 25000, + .n_voltages = 57, + .vsel_reg = MT6370_REG_CHG_CTRL5, + .vsel_mask = MT6370_VOBST_MASK, + .enable_reg = MT6370_REG_CHG_CTRL1, + .enable_mask = MT6370_OPA_MODE_MASK, + .curr_table = mt6370_chg_otg_oc_ma, + .n_current_limits = ARRAY_SIZE(mt6370_chg_otg_oc_ma), + .csel_reg = MT6370_REG_CHG_CTRL10, + .csel_mask = MT6370_OTG_OC_MASK, +}; + +static int mt6370_chg_init_rmap_fields(struct mt6370_priv *priv) +{ + int i; + const struct mt6370_chg_field *fds = mt6370_chg_fields; + + for (i = 0; i < F_MAX; i++) { + priv->rmap_fields[i] = devm_regmap_field_alloc(priv->dev, + priv->regmap, + fds[i].field); + if (IS_ERR(priv->rmap_fields[i])) + return dev_err_probe(priv->dev, + PTR_ERR(priv->rmap_fields[i]), + "Failed to allocate regmapfield[%s]\n", + fds[i].name); + } + + return 0; +} + +static int mt6370_chg_init_setting(struct mt6370_priv *priv) +{ + int ret; + + /* Disable usb_chg_en */ + ret = mt6370_chg_field_set(priv, F_USBCHGEN, 0); + if (ret) { + dev_err(priv->dev, "Failed to disable usb_chg_en\n"); + return ret; + } + + /* ICHG/IEOC Workaround, ICHG can not be set less than 900mA */ + ret = mt6370_chg_field_set(priv, F_ICHG, 900000); + if (ret) { + dev_err(priv->dev, "Failed to set ICHG to 900mA"); + return ret; + } + + /* Change input current limit selection to using IAICR results */ + ret = mt6370_chg_field_set(priv, F_IINLMTSEL, 3); + if (ret) { + dev_err(priv->dev, "Failed to set IINLMTSEL\n"); + return ret; + } + + return 0; +} + +#define MT6370_CHG_DT_PROP_DECL(_name, _type, _field) \ +{ \ + .name = "mediatek,chg-" #_name, \ + .type = MT6370_PARSE_TYPE_##_type, \ + .fd = _field, \ +} + +static int mt6370_chg_init_otg_regulator(struct mt6370_priv *priv) +{ + struct regulator_config rcfg = { + .dev = priv->dev, + .regmap = priv->regmap, + .driver_data = priv, + }; + + priv->rdev = devm_regulator_register(priv->dev, &mt6370_chg_otg_rdesc, + &rcfg); + + return PTR_ERR_OR_ZERO(priv->rdev); +} + +static int mt6370_chg_init_psy(struct mt6370_priv *priv) +{ + struct power_supply_config cfg = { + .drv_data = priv, + .of_node = dev_of_node(priv->dev), + }; + + priv->psy = devm_power_supply_register(priv->dev, &mt6370_chg_psy_desc, + &cfg); + + return PTR_ERR_OR_ZERO(priv->psy); +} + +static void mt6370_chg_destroy_attach_lock(void *data) +{ + struct mutex *attach_lock = data; + + mutex_destroy(attach_lock); +} + +static void mt6370_chg_destroy_wq(void *data) +{ + struct workqueue_struct *wq = data; + + flush_workqueue(wq); + destroy_workqueue(wq); +} + +static void mt6370_chg_cancel_mivr_dwork(void *data) +{ + struct delayed_work *mivr_dwork = data; + + cancel_delayed_work_sync(mivr_dwork); +} + +static irqreturn_t mt6370_attach_i_handler(int irq, void *data) +{ + struct mt6370_priv *priv = data; + unsigned int otg_en; + int ret; + + /* Check in OTG mode or not */ + ret = mt6370_chg_field_get(priv, F_BOOST_STAT, &otg_en); + if (ret) { + dev_err(priv->dev, "Failed to get OTG state\n"); + return IRQ_NONE; + } + + if (otg_en) + return IRQ_HANDLED; + + mutex_lock(&priv->attach_lock); + priv->attach = MT6370_ATTACH_STAT_ATTACH_BC12_DONE; + mutex_unlock(&priv->attach_lock); + + if (!queue_work(priv->wq, &priv->bc12_work)) + dev_err(priv->dev, "bc12 work has already queued\n"); + + return IRQ_HANDLED; +} + +static irqreturn_t mt6370_uvp_d_evt_handler(int irq, void *data) +{ + struct mt6370_priv *priv = data; + + mt6370_chg_pwr_rdy_check(priv); + + return IRQ_HANDLED; +} + +static irqreturn_t mt6370_mivr_handler(int irq, void *data) +{ + struct mt6370_priv *priv = data; + + pm_stay_awake(priv->dev); + disable_irq_nosync(priv->irq_nums[MT6370_IRQ_MIVR]); + schedule_delayed_work(&priv->mivr_dwork, msecs_to_jiffies(200)); + + return IRQ_HANDLED; +} + +#define MT6370_CHG_IRQ(_name) \ +{ \ + .name = #_name, \ + .handler = mt6370_##_name##_handler, \ +} + +static int mt6370_chg_init_irq(struct mt6370_priv *priv) +{ + int i, ret; + const struct { + char *name; + irq_handler_t handler; + } mt6370_chg_irqs[] = { + MT6370_CHG_IRQ(attach_i), + MT6370_CHG_IRQ(uvp_d_evt), + MT6370_CHG_IRQ(mivr), + }; + + for (i = 0; i < ARRAY_SIZE(mt6370_chg_irqs); i++) { + ret = platform_get_irq_byname(to_platform_device(priv->dev), + mt6370_chg_irqs[i].name); + if (ret < 0) + return dev_err_probe(priv->dev, ret, + "Failed to get irq %s\n", + mt6370_chg_irqs[i].name); + + priv->irq_nums[i] = ret; + ret = devm_request_threaded_irq(priv->dev, ret, NULL, + mt6370_chg_irqs[i].handler, + IRQF_TRIGGER_FALLING, + dev_name(priv->dev), priv); + if (ret) + return dev_err_probe(priv->dev, ret, + "Failed to request irq %s\n", + mt6370_chg_irqs[i].name); + } + + return 0; +} + +static int mt6370_chg_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct mt6370_priv *priv; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->dev = &pdev->dev; + + priv->regmap = dev_get_regmap(pdev->dev.parent, NULL); + if (!priv->regmap) + return dev_err_probe(dev, -ENODEV, "Failed to get regmap\n"); + + ret = mt6370_chg_init_rmap_fields(priv); + if (ret) + return dev_err_probe(dev, ret, "Failed to init regmap fields\n"); + + platform_set_drvdata(pdev, priv); + + priv->iio_adcs = devm_iio_channel_get_all(priv->dev); + if (IS_ERR(priv->iio_adcs)) + return dev_err_probe(dev, PTR_ERR(priv->iio_adcs), + "Failed to get iio adc\n"); + + ret = mt6370_chg_init_otg_regulator(priv); + if (ret) + return dev_err_probe(dev, ret, "Failed to init OTG regulator\n"); + + ret = mt6370_chg_init_psy(priv); + if (ret) + return dev_err_probe(dev, ret, "Failed to init psy\n"); + + mutex_init(&priv->attach_lock); + ret = devm_add_action_or_reset(dev, mt6370_chg_destroy_attach_lock, + &priv->attach_lock); + if (ret) + return dev_err_probe(dev, ret, "Failed to init attach lock\n"); + + priv->attach = MT6370_ATTACH_STAT_DETACH; + + priv->wq = create_singlethread_workqueue(dev_name(priv->dev)); + if (IS_ERR(priv->wq)) + return dev_err_probe(dev, PTR_ERR(priv->wq), + "Failed to create workqueue\n"); + + ret = devm_add_action_or_reset(dev, mt6370_chg_destroy_wq, priv->wq); + if (ret) + return dev_err_probe(dev, ret, "Failed to init wq\n"); + + INIT_WORK(&priv->bc12_work, mt6370_chg_bc12_work_func); + INIT_DELAYED_WORK(&priv->mivr_dwork, mt6370_chg_mivr_dwork_func); + ret = devm_add_action_or_reset(dev, mt6370_chg_cancel_mivr_dwork, + &priv->mivr_dwork); + if (ret) + return dev_err_probe(dev, ret, "Failed to init mivr dwork\n"); + + ret = mt6370_chg_init_setting(priv); + if (ret) + return dev_err_probe(dev, ret, + "Failed to init mt6370 charger setting\n"); + + ret = mt6370_chg_init_irq(priv); + if (ret) + return ret; + + mt6370_chg_pwr_rdy_check(priv); + + return 0; +} + +static const struct of_device_id mt6370_chg_of_match[] = { + { .compatible = "mediatek,mt6370-charger", }, + {} +}; +MODULE_DEVICE_TABLE(of, mt6370_chg_of_match); + +static struct platform_driver mt6370_chg_driver = { + .probe = mt6370_chg_probe, + .driver = { + .name = "mt6370-charger", + .of_match_table = mt6370_chg_of_match, + }, +}; +module_platform_driver(mt6370_chg_driver); + +MODULE_AUTHOR("ChiaEn Wu "); +MODULE_DESCRIPTION("MediaTek MT6370 Charger Driver"); +MODULE_LICENSE("GPL v2"); From patchwork Fri Aug 5 07:06:08 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: ChiaEn Wu X-Patchwork-Id: 12936981 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id A9600C00140 for ; Fri, 5 Aug 2022 07:16:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=x+D+upR/FpD1MTZlP6fOc+FqA6IV/ONxMbTSfHPRLko=; b=ITizA6Fws/UVqmP25ayxKMRM0p dYw8UbGA0e7w9dkobND02AVvIHDobo8hpzT5+qPgTdcZzGU9oCskXriOPSwuNF8E8nMUeoFxC4BOI wviAvl9Tq4Nu17EO5abuvf3Syw1Fu6aA8ZNEQ/e5EHp6WtrpK6ikdEmXigIW6i5yEmnvmMPjstnXZ CjWi6cqA4dpCVOOVL4p/fIQZwu86MMNaDrm0qVm03BXh3/rfuj5D3qgkiwYcEcBf3aZ0f3gqMsZ5D BnAkP0Q26h2HrLy+wrQqL4UUkEuslFS4yFcEObvoRFp1CiLlGnrN4lbGXhOfGHOnuj9WD3SwxOud6 Gd0UR9Wg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1oJrZU-00ClpT-H4; Fri, 05 Aug 2022 07:16:36 +0000 Received: from mail-pl1-x634.google.com ([2607:f8b0:4864:20::634]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1oJrQy-00Chav-MB; Fri, 05 Aug 2022 07:07:59 +0000 Received: by mail-pl1-x634.google.com with SMTP id w14so1885606plp.9; Fri, 05 Aug 2022 00:07:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc; bh=x+D+upR/FpD1MTZlP6fOc+FqA6IV/ONxMbTSfHPRLko=; b=RXmj3fHN+hGOK6/3wwyUAOliBPQTe47F90E3ch9UsDSJAKdMN3sckqchZJFzype+7U Almox2MxZQE4EJAxj6XGM/eiM5yDPE7BeyBU/pOifVtYAhvDfJJv+Qg9U2zaepOFR47N JCNCYnPrp7yE/R3eaTVyj77GJnbiwPfmtUaiF6uFfdRZmEILf/an2/AD9smCH6DjHx5y ub0y6rn0gv5k6c9/+0GiOKVH8k5BihRb3Zr3/BtxYazVVBjY66in/ej7SeoBlav3ia+o U8kPngP5MaEcey+uKpYn0RiXwoklrgzPBjkYY2PO6gpp1YQsXHFOrx6vQU4wGJMSRRVf 8uAA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc; bh=x+D+upR/FpD1MTZlP6fOc+FqA6IV/ONxMbTSfHPRLko=; b=0EBbzESm5Hkf0FqPHH3KBZrrevijHQwrk6hE7Yk42tNE8qX0NyB7Or5XlX0pqs9vBs xjPoEb1ODlCorQsanc8F8gvcyKxumt11q0am8rdJCVDo5WG6CmnJG7CKfj+ruIg3Nr1r 7sRMIUnJi1T0Cx5fVlqLxAgYirhaOizdMtnkVDAofRoIy0XTydJaJPuz+dO+GODCC9qx V2p8iXAA/iiDENAhEru1Mn6xRF1PFMw749oyFSlUzQEqmrMVLqrfLWUtZK1xNrBuZwqY /tT/woxSznNDxN82A3S8VFnoSfHPtB6lREjzs0Fr+RMhR+bxspCdA62DqWKlmpwHcnv2 8vRQ== X-Gm-Message-State: ACgBeo1plSEnBEkuz5FStwW6HHfrlml2tkb90mpMi6jValVFjMFiY0KE 4yV+kCg7ECLx7gQ7ijwtSg8= X-Google-Smtp-Source: AA6agR5TedvSFK9YhWQ4VmRIoMkQdFcQVF+W27FDrjCsL6mrmbemF9qjmKt2qsOJClEBYehcqhmKKQ== X-Received: by 2002:a17:902:d509:b0:16f:1e1:2063 with SMTP id b9-20020a170902d50900b0016f01e12063mr5450042plg.131.1659683266074; Fri, 05 Aug 2022 00:07:46 -0700 (PDT) Received: from RD-3580-24288.rt.l (42-72-229-62.emome-ip.hinet.net. [42.72.229.62]) by smtp.gmail.com with ESMTPSA id i5-20020a056a00224500b00525343b5047sm2191616pfu.76.2022.08.05.00.07.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 05 Aug 2022 00:07:45 -0700 (PDT) From: ChiaEn Wu To: lee.jones@linaro.org, daniel.thompson@linaro.org, jingoohan1@gmail.com, pavel@ucw.cz, robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, matthias.bgg@gmail.com, sre@kernel.org, chunfeng.yun@mediatek.com, gregkh@linuxfoundation.org, jic23@kernel.org, lars@metafoo.de, lgirdwood@gmail.com, broonie@kernel.org, linux@roeck-us.net, heikki.krogerus@linux.intel.com, deller@gmx.de, andy.shevchenko@gmail.com Cc: chiaen_wu@richtek.com, alice_chen@richtek.com, cy_huang@richtek.com, dri-devel@lists.freedesktop.org, linux-leds@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, linux-usb@vger.kernel.org, linux-iio@vger.kernel.org, linux-fbdev@vger.kernel.org, szunichen@gmail.com, AngeloGioacchino Del Regno Subject: [PATCH v7 11/13] leds: rgb: mt6370: Add MediaTek MT6370 current sink type LED Indicator support Date: Fri, 5 Aug 2022 15:06:08 +0800 Message-Id: <20220805070610.3516-12-peterwu.pub@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220805070610.3516-1-peterwu.pub@gmail.com> References: <20220805070610.3516-1-peterwu.pub@gmail.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220805_000748_871893_B55B9658 X-CRM114-Status: GOOD ( 24.02 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org From: ChiYuan Huang The MediaTek MT6370 is a highly-integrated smart power management IC, which includes a single cell Li-Ion/Li-Polymer switching battery charger, a USB Type-C & Power Delivery (PD) controller, dual Flash LED current sources, a RGB LED driver, a backlight WLED driver, a display bias driver and a general LDO for portable devices. Add a support for the MediaTek MT6370 Current Sink Type LED Indicator driver. It can control four channels current-sink RGB LEDs with 3 modes, constant current, PWM, and breath mode. Reviewed-by: AngeloGioacchino Del Regno Co-developed-by: Alice Chen Signed-off-by: Alice Chen Signed-off-by: ChiYuan Huang Signed-off-by: ChiaEn Wu --- v7 - Add the comment for the union of 'struct mt6370_led' - Revise the wrong description of 'Authors' - Revise some typos (e.g. led --> LED) - Revise 'if (!fwnode_property_read_string())' to 'ret = fwnode_property_read_string()' - Replace 'memcpy(...)' with 'put_unaligned_be24()' in mt6370_gen_breath_pattern() - Replace all 'LED_OFF' with 0 - Remove the redundant assignment in mt6370_mc_pattern_clear() --- drivers/leds/rgb/Kconfig | 13 + drivers/leds/rgb/Makefile | 1 + drivers/leds/rgb/leds-mt6370-rgb.c | 1022 ++++++++++++++++++++++++++++++++++++ 3 files changed, 1036 insertions(+) create mode 100644 drivers/leds/rgb/leds-mt6370-rgb.c diff --git a/drivers/leds/rgb/Kconfig b/drivers/leds/rgb/Kconfig index 204cf47..7d86bb2 100644 --- a/drivers/leds/rgb/Kconfig +++ b/drivers/leds/rgb/Kconfig @@ -26,4 +26,17 @@ config LEDS_QCOM_LPG If compiled as a module, the module will be named leds-qcom-lpg. +config LEDS_MT6370_RGB + tristate "LED Support for MediaTek MT6370 PMIC" + depends on MFD_MT6370 + select LINEAR_RANGE + help + Say Y here to enable support for MT6370_RGB LED device. + In MT6370, there are four channel current-sink LED drivers that + support hardware pattern for constant current, PWM, and breath mode. + Isink4 channel can also be used as a CHG_VIN power good indicator. + + This driver can also be built as a module. If so, the module + will be called "leds-mt6370-rgb". + endif # LEDS_CLASS_MULTICOLOR diff --git a/drivers/leds/rgb/Makefile b/drivers/leds/rgb/Makefile index 0675bc0..8c01daf 100644 --- a/drivers/leds/rgb/Makefile +++ b/drivers/leds/rgb/Makefile @@ -2,3 +2,4 @@ obj-$(CONFIG_LEDS_PWM_MULTICOLOR) += leds-pwm-multicolor.o obj-$(CONFIG_LEDS_QCOM_LPG) += leds-qcom-lpg.o +obj-$(CONFIG_LEDS_MT6370_RGB) += leds-mt6370-rgb.o diff --git a/drivers/leds/rgb/leds-mt6370-rgb.c b/drivers/leds/rgb/leds-mt6370-rgb.c new file mode 100644 index 0000000..42cc13a --- /dev/null +++ b/drivers/leds/rgb/leds-mt6370-rgb.c @@ -0,0 +1,1022 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2022 Richtek Technology Corp. + * + * Authors: + * ChiYuan Huang + * Alice Chen + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +enum { + MT6370_LED_ISNK1 = 0, + MT6370_LED_ISNK2, + MT6370_LED_ISNK3, + MT6370_LED_ISNK4, + MT6370_MAX_LEDS +}; + +enum mt6370_led_mode { + MT6370_LED_PWM_MODE = 0, + MT6370_LED_BREATH_MODE, + MT6370_LED_REG_MODE, + MT6370_LED_MAX_MODE +}; + +enum mt6370_led_field { + F_RGB_EN = 0, + F_CHGIND_EN, + F_LED1_CURR, + F_LED2_CURR, + F_LED3_CURR, + F_LED4_CURR, + F_LED1_MODE, + F_LED2_MODE, + F_LED3_MODE, + F_LED4_MODE, + F_LED1_DUTY, + F_LED2_DUTY, + F_LED3_DUTY, + F_LED4_DUTY, + F_LED1_FREQ, + F_LED2_FREQ, + F_LED3_FREQ, + F_LED4_FREQ, + F_MAX_FIELDS +}; + +enum mt6370_led_ranges { + R_LED123_CURR = 0, + R_LED4_CURR, + R_LED_TRFON, + R_LED_TOFF, + R_MAX_RANGES +}; + +enum mt6370_pattern { + P_LED_TR1 = 0, + P_LED_TR2, + P_LED_TF1, + P_LED_TF2, + P_LED_TON, + P_LED_TOFF, + P_MAX_PATTERNS +}; + +enum mt6370_state { + STATE_OFF = 0, + STATE_KEEP, + STATE_ON, + STATE_MAX +}; + +#define MT6370_REG_DEV_INFO 0x100 +#define MT6370_REG_RGB1_DIM 0x182 +#define MT6370_REG_RGB2_DIM 0x183 +#define MT6370_REG_RGB3_DIM 0x184 +#define MT6370_REG_RGB_EN 0x185 +#define MT6370_REG_RGB1_ISNK 0x186 +#define MT6370_REG_RGB2_ISNK 0x187 +#define MT6370_REG_RGB3_ISNK 0x188 +#define MT6370_REG_RGB1_TR 0x189 +#define MT6370_REG_RGB_CHRIND_DIM 0x192 +#define MT6370_REG_RGB_CHRIND_CTRL 0x193 +#define MT6370_REG_RGB_CHRIND_TR 0x194 + +#define MT6372_REG_RGB_EN 0x182 +#define MT6372_REG_RGB1_ISNK 0x183 +#define MT6372_REG_RGB2_ISNK 0x184 +#define MT6372_REG_RGB3_ISNK 0x185 +#define MT6372_REG_RGB4_ISNK 0x186 +#define MT6372_REG_RGB1_DIM 0x187 +#define MT6372_REG_RGB2_DIM 0x188 +#define MT6372_REG_RGB3_DIM 0x189 +#define MT6372_REG_RGB4_DIM 0x18A +#define MT6372_REG_RGB12_FREQ 0x18B +#define MT6372_REG_RGB34_FREQ 0x18C +#define MT6372_REG_RGB1_TR 0x18D + +#define MT6370_VENID_MASK GENMASK(7, 4) +#define MT6370_CHEN_BIT(id) BIT(MT6370_LED_ISNK4 - id) +#define MT6370_VIRTUAL_MULTICOLOR 5 +#define MC_CHANNEL_NUM 3 +#define MT6370_PWM_DUTY (BIT(5) - 1) +#define MT6372_PWM_DUTY (BIT(8) - 1) + +struct mt6370_led { + /* + * If the color of the LED in DT is set to + * - 'LED_COLOR_ID_RGB' + * - 'LED_COLOR_ID_MULTI' + * The member 'index' of this struct will be set to + * 'MT6370_VIRTUAL_MULTICOLOR'. + * If so, this LED will choose 'struct led_classdev_mc mc' to use. + * Instead, if the member 'index' of this struct is set to + * 'MT6370_LED_ISNK1' ~ 'MT6370_LED_ISNK4', then this LED will choose + * 'struct led_classdev isink' to use. + */ + union { + struct led_classdev isink; + struct led_classdev_mc mc; + }; + struct mt6370_priv *priv; + u32 default_state; + u32 index; +}; + +struct mt6370_pdata { + const unsigned int *tfreq; + unsigned int tfreq_len; + u8 pwm_duty; + u16 reg_rgb1_tr; + s16 reg_rgb_chrind_tr; +}; + +struct mt6370_priv { + /* Per LED access lock */ + struct mutex lock; + struct device *dev; + struct regmap *regmap; + struct regmap_field *fields[F_MAX_FIELDS]; + const struct reg_field *reg_fields; + const struct linear_range *ranges; + struct reg_cfg *reg_cfgs; + const struct mt6370_pdata *pdata; + unsigned int leds_count; + unsigned int leds_active; + struct mt6370_led leds[]; +}; + +static const struct reg_field common_reg_fields[F_MAX_FIELDS] = { + [F_RGB_EN] = REG_FIELD(MT6370_REG_RGB_EN, 4, 7), + [F_CHGIND_EN] = REG_FIELD(MT6370_REG_RGB_CHRIND_DIM, 7, 7), + [F_LED1_CURR] = REG_FIELD(MT6370_REG_RGB1_ISNK, 0, 2), + [F_LED2_CURR] = REG_FIELD(MT6370_REG_RGB2_ISNK, 0, 2), + [F_LED3_CURR] = REG_FIELD(MT6370_REG_RGB3_ISNK, 0, 2), + [F_LED4_CURR] = REG_FIELD(MT6370_REG_RGB_CHRIND_CTRL, 0, 1), + [F_LED1_MODE] = REG_FIELD(MT6370_REG_RGB1_DIM, 5, 6), + [F_LED2_MODE] = REG_FIELD(MT6370_REG_RGB2_DIM, 5, 6), + [F_LED3_MODE] = REG_FIELD(MT6370_REG_RGB3_DIM, 5, 6), + [F_LED4_MODE] = REG_FIELD(MT6370_REG_RGB_CHRIND_DIM, 5, 6), + [F_LED1_DUTY] = REG_FIELD(MT6370_REG_RGB1_DIM, 0, 4), + [F_LED2_DUTY] = REG_FIELD(MT6370_REG_RGB2_DIM, 0, 4), + [F_LED3_DUTY] = REG_FIELD(MT6370_REG_RGB3_DIM, 0, 4), + [F_LED4_DUTY] = REG_FIELD(MT6370_REG_RGB_CHRIND_DIM, 0, 4), + [F_LED1_FREQ] = REG_FIELD(MT6370_REG_RGB1_ISNK, 3, 5), + [F_LED2_FREQ] = REG_FIELD(MT6370_REG_RGB2_ISNK, 3, 5), + [F_LED3_FREQ] = REG_FIELD(MT6370_REG_RGB3_ISNK, 3, 5), + [F_LED4_FREQ] = REG_FIELD(MT6370_REG_RGB_CHRIND_CTRL, 2, 4), +}; + +static const struct reg_field mt6372_reg_fields[F_MAX_FIELDS] = { + [F_RGB_EN] = REG_FIELD(MT6372_REG_RGB_EN, 4, 7), + [F_CHGIND_EN] = REG_FIELD(MT6372_REG_RGB_EN, 3, 3), + [F_LED1_CURR] = REG_FIELD(MT6372_REG_RGB1_ISNK, 0, 3), + [F_LED2_CURR] = REG_FIELD(MT6372_REG_RGB2_ISNK, 0, 3), + [F_LED3_CURR] = REG_FIELD(MT6372_REG_RGB3_ISNK, 0, 3), + [F_LED4_CURR] = REG_FIELD(MT6372_REG_RGB4_ISNK, 0, 3), + [F_LED1_MODE] = REG_FIELD(MT6372_REG_RGB1_ISNK, 6, 7), + [F_LED2_MODE] = REG_FIELD(MT6372_REG_RGB2_ISNK, 6, 7), + [F_LED3_MODE] = REG_FIELD(MT6372_REG_RGB3_ISNK, 6, 7), + [F_LED4_MODE] = REG_FIELD(MT6372_REG_RGB4_ISNK, 6, 7), + [F_LED1_DUTY] = REG_FIELD(MT6372_REG_RGB1_DIM, 0, 7), + [F_LED2_DUTY] = REG_FIELD(MT6372_REG_RGB2_DIM, 0, 7), + [F_LED3_DUTY] = REG_FIELD(MT6372_REG_RGB3_DIM, 0, 7), + [F_LED4_DUTY] = REG_FIELD(MT6372_REG_RGB4_DIM, 0, 7), + [F_LED1_FREQ] = REG_FIELD(MT6372_REG_RGB12_FREQ, 5, 7), + [F_LED2_FREQ] = REG_FIELD(MT6372_REG_RGB12_FREQ, 2, 4), + [F_LED3_FREQ] = REG_FIELD(MT6372_REG_RGB34_FREQ, 5, 7), + [F_LED4_FREQ] = REG_FIELD(MT6372_REG_RGB34_FREQ, 2, 4), +}; + +/* Current unit: microamp, time unit: millisecond */ +static const struct linear_range common_led_ranges[R_MAX_RANGES] = { + [R_LED123_CURR] = { 4000, 1, 6, 4000 }, + [R_LED4_CURR] = { 2000, 1, 3, 2000 }, + [R_LED_TRFON] = { 125, 0, 15, 200 }, + [R_LED_TOFF] = { 250, 0, 15, 400 }, +}; + +static const struct linear_range mt6372_led_ranges[R_MAX_RANGES] = { + [R_LED123_CURR] = { 2000, 1, 14, 2000 }, + [R_LED4_CURR] = { 2000, 1, 14, 2000 }, + [R_LED_TRFON] = { 125, 0, 15, 250 }, + [R_LED_TOFF] = { 250, 0, 15, 500 }, +}; + +static const unsigned int common_tfreqs[] = { + 10000, 5000, 2000, 1000, 500, 200, 5, 1, +}; + +static const unsigned int mt6372_tfreqs[] = { + 8000, 4000, 2000, 1000, 500, 250, 8, 4, +}; + +static const struct mt6370_pdata common_pdata = { + .tfreq = common_tfreqs, + .tfreq_len = ARRAY_SIZE(common_tfreqs), + .pwm_duty = MT6370_PWM_DUTY, + .reg_rgb1_tr = MT6370_REG_RGB1_TR, + .reg_rgb_chrind_tr = MT6370_REG_RGB_CHRIND_TR, +}; + +static const struct mt6370_pdata mt6372_pdata = { + .tfreq = mt6372_tfreqs, + .tfreq_len = ARRAY_SIZE(mt6372_tfreqs), + .pwm_duty = MT6372_PWM_DUTY, + .reg_rgb1_tr = MT6372_REG_RGB1_TR, + .reg_rgb_chrind_tr = -1, +}; + +static enum mt6370_led_field mt6370_get_led_current_field(unsigned int led_no) +{ + switch (led_no) { + case MT6370_LED_ISNK1: + return F_LED1_CURR; + case MT6370_LED_ISNK2: + return F_LED2_CURR; + case MT6370_LED_ISNK3: + return F_LED3_CURR; + default: + return F_LED4_CURR; + } +} + +static int mt6370_set_led_brightness(struct mt6370_priv *priv, + unsigned int led_no, unsigned int level) +{ + enum mt6370_led_field sel_field; + + sel_field = mt6370_get_led_current_field(led_no); + + return regmap_field_write(priv->fields[sel_field], level); +} + +static int mt6370_get_led_brightness(struct mt6370_priv *priv, + unsigned int led_no, unsigned int *level) +{ + enum mt6370_led_field sel_field; + + sel_field = mt6370_get_led_current_field(led_no); + + return regmap_field_read(priv->fields[sel_field], level); +} + +static int mt6370_set_led_duty(struct mt6370_priv *priv, unsigned int led_no, + unsigned int ton, unsigned int toff) +{ + const struct mt6370_pdata *pdata = priv->pdata; + enum mt6370_led_field sel_field; + unsigned int divisor, ratio; + + divisor = pdata->pwm_duty; + ratio = ton * divisor / (ton + toff); + + switch (led_no) { + case MT6370_LED_ISNK1: + sel_field = F_LED1_DUTY; + break; + case MT6370_LED_ISNK2: + sel_field = F_LED2_DUTY; + break; + case MT6370_LED_ISNK3: + sel_field = F_LED3_DUTY; + break; + default: + sel_field = F_LED4_DUTY; + break; + } + + return regmap_field_write(priv->fields[sel_field], ratio); +} + +static int mt6370_set_led_freq(struct mt6370_priv *priv, unsigned int led_no, + unsigned int ton, unsigned int toff) +{ + const struct mt6370_pdata *pdata = priv->pdata; + enum mt6370_led_field sel_field; + unsigned int tfreq_len = pdata->tfreq_len; + unsigned int tsum, sel; + + tsum = ton + toff; + + if (tsum > pdata->tfreq[0] || tsum < pdata->tfreq[tfreq_len - 1]) + return -EOPNOTSUPP; + + sel = find_closest_descending(tsum, pdata->tfreq, tfreq_len); + + switch (led_no) { + case MT6370_LED_ISNK1: + sel_field = F_LED1_FREQ; + break; + case MT6370_LED_ISNK2: + sel_field = F_LED2_FREQ; + break; + case MT6370_LED_ISNK3: + sel_field = F_LED3_FREQ; + break; + default: + sel_field = F_LED4_FREQ; + break; + } + + return regmap_field_write(priv->fields[sel_field], sel); +} + +static void mt6370_get_breath_reg_base(struct mt6370_priv *priv, + unsigned int led_no, unsigned int *base) +{ + const struct mt6370_pdata *pdata = priv->pdata; + + if (pdata->reg_rgb_chrind_tr < 0) { + *base = pdata->reg_rgb1_tr + led_no * 3; + return; + } + + switch (led_no) { + case MT6370_LED_ISNK1: + case MT6370_LED_ISNK2: + case MT6370_LED_ISNK3: + *base = pdata->reg_rgb1_tr + led_no * 3; + break; + default: + *base = pdata->reg_rgb_chrind_tr; + break; + } +} + +static int mt6370_gen_breath_pattern(struct mt6370_priv *priv, + struct led_pattern *pattern, u32 len, + u8 *pattern_val, u32 val_len) +{ + enum mt6370_led_ranges sel_range; + struct led_pattern *curr; + unsigned int sel; + u32 val = 0; + int i; + + if (len < P_MAX_PATTERNS && val_len < P_MAX_PATTERNS / 2) + return -EINVAL; + + /* + * Pattern list + * tr1: byte 0, b'[7: 4] + * tr2: byte 0, b'[3: 0] + * tf1: byte 1, b'[7: 4] + * tf2: byte 1, b'[3: 0] + * ton: byte 2, b'[7: 4] + * toff: byte 2, b'[3: 0] + */ + for (i = 0; i < P_MAX_PATTERNS; i++) { + curr = pattern + i; + + sel_range = i == P_LED_TOFF ? R_LED_TOFF : R_LED_TRFON; + + linear_range_get_selector_within(priv->ranges + sel_range, + curr->delta_t, &sel); + + val <<= i % 2 == 0 ? 8 : 0; + val |= sel << (i % 2 == 0 ? 4 : 0); + } + + put_unaligned_be24(val, pattern_val); + + return 0; +} + +static int mt6370_set_led_mode(struct mt6370_priv *priv, unsigned int led_no, + enum mt6370_led_mode mode) +{ + enum mt6370_led_field sel_field; + + switch (led_no) { + case MT6370_LED_ISNK1: + sel_field = F_LED1_MODE; + break; + case MT6370_LED_ISNK2: + sel_field = F_LED2_MODE; + break; + case MT6370_LED_ISNK3: + sel_field = F_LED3_MODE; + break; + default: + sel_field = F_LED4_MODE; + break; + } + + return regmap_field_write(priv->fields[sel_field], mode); +} + +static int mt6370_mc_brightness_set(struct led_classdev *lcdev, + enum led_brightness level) +{ + struct led_classdev_mc *mccdev = lcdev_to_mccdev(lcdev); + struct mt6370_led *led = container_of(mccdev, struct mt6370_led, mc); + struct mt6370_priv *priv = led->priv; + struct mc_subled *subled; + unsigned int enable, disable; + int i, ret; + + mutex_lock(&priv->lock); + + led_mc_calc_color_components(mccdev, level); + + ret = regmap_field_read(priv->fields[F_RGB_EN], &enable); + if (ret) + goto out_unlock; + + disable = enable; + + for (i = 0; i < mccdev->num_colors; i++) { + u32 brightness; + + subled = mccdev->subled_info + i; + brightness = min(subled->brightness, lcdev->max_brightness); + disable &= ~MT6370_CHEN_BIT(subled->channel); + + if (level == 0) { + enable &= ~MT6370_CHEN_BIT(subled->channel); + + ret = mt6370_set_led_mode(priv, subled->channel, + MT6370_LED_REG_MODE); + if (ret) + goto out_unlock; + + continue; + } + + if (brightness == 0) { + enable &= ~MT6370_CHEN_BIT(subled->channel); + continue; + } + + enable |= MT6370_CHEN_BIT(subled->channel); + + ret = mt6370_set_led_brightness(priv, subled->channel, + brightness); + if (ret) + goto out_unlock; + } + + ret = regmap_field_write(priv->fields[F_RGB_EN], disable); + if (ret) + goto out_unlock; + + ret = regmap_field_write(priv->fields[F_RGB_EN], enable); + +out_unlock: + mutex_unlock(&priv->lock); + + return ret; +} + +static int mt6370_mc_blink_set(struct led_classdev *lcdev, + unsigned long *delay_on, + unsigned long *delay_off) +{ + struct led_classdev_mc *mccdev = lcdev_to_mccdev(lcdev); + struct mt6370_led *led = container_of(mccdev, struct mt6370_led, mc); + struct mt6370_priv *priv = led->priv; + struct mc_subled *subled; + unsigned int enable, disable; + int i, ret; + + mutex_lock(&priv->lock); + + if (!*delay_on && !*delay_off) + *delay_on = *delay_off = 500; + + ret = regmap_field_read(priv->fields[F_RGB_EN], &enable); + if (ret) + goto out_unlock; + + disable = enable; + + for (i = 0; i < mccdev->num_colors; i++) { + subled = mccdev->subled_info + i; + + disable &= ~MT6370_CHEN_BIT(subled->channel); + + ret = mt6370_set_led_duty(priv, subled->channel, *delay_on, + *delay_off); + if (ret) + goto out_unlock; + + ret = mt6370_set_led_freq(priv, subled->channel, *delay_on, + *delay_off); + if (ret) + goto out_unlock; + + ret = mt6370_set_led_mode(priv, subled->channel, + MT6370_LED_PWM_MODE); + if (ret) + goto out_unlock; + } + + /* Toggle to make pattern timing the same */ + ret = regmap_field_write(priv->fields[F_RGB_EN], disable); + if (ret) + goto out_unlock; + + ret = regmap_field_write(priv->fields[F_RGB_EN], enable); + +out_unlock: + mutex_unlock(&priv->lock); + + return ret; +} + +static int mt6370_mc_pattern_set(struct led_classdev *lcdev, + struct led_pattern *pattern, u32 len, int repeat) +{ + struct led_classdev_mc *mccdev = lcdev_to_mccdev(lcdev); + struct mt6370_led *led = container_of(mccdev, struct mt6370_led, mc); + struct mt6370_priv *priv = led->priv; + struct mc_subled *subled; + unsigned int reg_base, enable, disable; + u8 params[P_MAX_PATTERNS / 2]; + int i, ret; + + mutex_lock(&priv->lock); + + ret = mt6370_gen_breath_pattern(priv, pattern, len, params, + sizeof(params)); + if (ret) + goto out_unlock; + + ret = regmap_field_read(priv->fields[F_RGB_EN], &enable); + if (ret) + goto out_unlock; + + disable = enable; + + for (i = 0; i < mccdev->num_colors; i++) { + subled = mccdev->subled_info + i; + + mt6370_get_breath_reg_base(priv, subled->channel, ®_base); + disable &= ~MT6370_CHEN_BIT(subled->channel); + + ret = regmap_raw_write(priv->regmap, reg_base, params, + sizeof(params)); + if (ret) + goto out_unlock; + + ret = mt6370_set_led_mode(priv, subled->channel, + MT6370_LED_BREATH_MODE); + if (ret) + goto out_unlock; + } + + /* Toggle to make pattern timing be the same */ + ret = regmap_field_write(priv->fields[F_RGB_EN], disable); + if (ret) + goto out_unlock; + + ret = regmap_field_write(priv->fields[F_RGB_EN], enable); + +out_unlock: + mutex_unlock(&priv->lock); + + return ret; +} + +static inline int mt6370_mc_pattern_clear(struct led_classdev *lcdev) +{ + struct led_classdev_mc *mccdev = lcdev_to_mccdev(lcdev); + struct mt6370_led *led = container_of(mccdev, struct mt6370_led, mc); + struct mt6370_priv *priv = led->priv; + struct mc_subled *subled; + int i, ret; + + mutex_lock(&led->priv->lock); + + for (i = 0; i < mccdev->num_colors; i++) { + subled = mccdev->subled_info + i; + + ret = mt6370_set_led_mode(priv, subled->channel, + MT6370_LED_REG_MODE); + if (ret) + break; + } + + mutex_unlock(&led->priv->lock); + + return ret; +} + +static int mt6370_isnk_brightness_set(struct led_classdev *lcdev, + enum led_brightness level) +{ + struct mt6370_led *led = container_of(lcdev, struct mt6370_led, isink); + struct mt6370_priv *priv = led->priv; + unsigned int enable; + int ret; + + mutex_lock(&priv->lock); + + ret = regmap_field_read(priv->fields[F_RGB_EN], &enable); + if (ret) + goto out_unlock; + + if (level == 0) { + enable &= ~MT6370_CHEN_BIT(led->index); + + ret = mt6370_set_led_mode(priv, led->index, + MT6370_LED_REG_MODE); + if (ret) + goto out_unlock; + + ret = regmap_field_write(priv->fields[F_RGB_EN], enable); + } else { + enable |= MT6370_CHEN_BIT(led->index); + + ret = mt6370_set_led_brightness(priv, led->index, level); + if (ret) + goto out_unlock; + + ret = regmap_field_write(priv->fields[F_RGB_EN], enable); + } + +out_unlock: + mutex_unlock(&priv->lock); + + return ret; +} + +static int mt6370_isnk_blink_set(struct led_classdev *lcdev, + unsigned long *delay_on, + unsigned long *delay_off) +{ + struct mt6370_led *led = container_of(lcdev, struct mt6370_led, isink); + struct mt6370_priv *priv = led->priv; + int ret; + + mutex_lock(&priv->lock); + + if (!*delay_on && !*delay_off) + *delay_on = *delay_off = 500; + + ret = mt6370_set_led_duty(priv, led->index, *delay_on, *delay_off); + if (ret) + goto out_unlock; + + ret = mt6370_set_led_freq(priv, led->index, *delay_on, *delay_off); + if (ret) + goto out_unlock; + + ret = mt6370_set_led_mode(priv, led->index, MT6370_LED_PWM_MODE); + +out_unlock: + mutex_unlock(&priv->lock); + + return ret; +} + +static int mt6370_isnk_pattern_set(struct led_classdev *lcdev, + struct led_pattern *pattern, u32 len, + int repeat) +{ + struct mt6370_led *led = container_of(lcdev, struct mt6370_led, isink); + struct mt6370_priv *priv = led->priv; + unsigned int reg_base; + u8 params[P_MAX_PATTERNS / 2]; + int ret; + + mutex_lock(&priv->lock); + + ret = mt6370_gen_breath_pattern(priv, pattern, len, params, + sizeof(params)); + if (ret) + goto out_unlock; + + mt6370_get_breath_reg_base(priv, led->index, ®_base); + + ret = regmap_raw_write(priv->regmap, reg_base, params, sizeof(params)); + if (ret) + goto out_unlock; + + ret = mt6370_set_led_mode(priv, led->index, MT6370_LED_BREATH_MODE); + +out_unlock: + mutex_unlock(&priv->lock); + + return ret; +} + +static inline int mt6370_isnk_pattern_clear(struct led_classdev *lcdev) +{ + struct mt6370_led *led = container_of(lcdev, struct mt6370_led, isink); + struct mt6370_priv *priv = led->priv; + int ret; + + mutex_lock(&led->priv->lock); + ret = mt6370_set_led_mode(priv, led->index, MT6370_LED_REG_MODE); + mutex_unlock(&led->priv->lock); + + return ret; +} + +static int mt6370_init_led_properties(struct mt6370_led *led, + struct led_init_data *init_data) +{ + struct mt6370_priv *priv = led->priv; + struct device *dev = priv->dev; + struct led_classdev *lcdev; + struct fwnode_handle *child; + enum mt6370_led_ranges sel_range; + u32 max_uA, max_level; + const char * const states[] = { "off", "keep", "on" }; + const char *stat_str; + int ret; + + if (led->index == MT6370_VIRTUAL_MULTICOLOR) { + struct mc_subled *sub_led; + u32 num_color = 0; + + sub_led = devm_kcalloc(dev, MC_CHANNEL_NUM, sizeof(*sub_led), + GFP_KERNEL); + if (!sub_led) + return -ENOMEM; + + fwnode_for_each_child_node(init_data->fwnode, child) { + u32 reg, color; + + ret = fwnode_property_read_u32(child, "reg", ®); + if (ret || reg > MT6370_LED_ISNK3 || + priv->leds_active & BIT(reg)) + return -EINVAL; + + ret = fwnode_property_read_u32(child, "color", &color); + if (ret) + return dev_err_probe(dev, ret, + "LED %d, no color specified\n", + led->index); + + priv->leds_active |= BIT(reg); + sub_led[num_color].color_index = color; + sub_led[num_color].channel = reg; + sub_led[num_color].intensity = 0; + num_color++; + } + + if (num_color < 2) + return dev_err_probe(dev, -EINVAL, + "Multicolor must include 2 or more LED channels\n"); + + led->mc.num_colors = num_color; + led->mc.subled_info = sub_led; + + lcdev = &led->mc.led_cdev; + lcdev->brightness_set_blocking = mt6370_mc_brightness_set; + lcdev->blink_set = mt6370_mc_blink_set; + lcdev->pattern_set = mt6370_mc_pattern_set; + lcdev->pattern_clear = mt6370_mc_pattern_clear; + } else { + lcdev = &led->isink; + lcdev->brightness_set_blocking = mt6370_isnk_brightness_set; + lcdev->blink_set = mt6370_isnk_blink_set; + lcdev->pattern_set = mt6370_isnk_pattern_set; + lcdev->pattern_clear = mt6370_isnk_pattern_clear; + } + + ret = fwnode_property_read_u32(init_data->fwnode, "led-max-microamp", + &max_uA); + if (ret) { + dev_warn(dev, + "Not specified led-max-microamp, config to the minimum\n"); + max_uA = 0; + } + + if (led->index == MT6370_LED_ISNK4) + sel_range = R_LED4_CURR; + else + sel_range = R_LED123_CURR; + + linear_range_get_selector_within(priv->ranges + sel_range, max_uA, + &max_level); + + lcdev->max_brightness = max_level; + + fwnode_property_read_string(init_data->fwnode, "linux,default-trigger", + &lcdev->default_trigger); + + ret = fwnode_property_read_string(init_data->fwnode, "default-state", + &stat_str); + if (!ret) { + ret = match_string(states, ARRAY_SIZE(states), stat_str); + if (ret < 0) + ret = STATE_OFF; + + led->default_state = ret; + } + + return 0; +} + +static int mt6370_isnk_init_default_state(struct mt6370_led *led) +{ + struct mt6370_priv *priv = led->priv; + unsigned int enable, level; + int ret; + + ret = mt6370_get_led_brightness(priv, led->index, &level); + if (ret) + return ret; + + ret = regmap_field_read(priv->fields[F_RGB_EN], &enable); + if (ret) + return ret; + + if (!(enable & MT6370_CHEN_BIT(led->index))) + level = 0; + + switch (led->default_state) { + case STATE_ON: + led->isink.brightness = led->isink.max_brightness; + break; + case STATE_KEEP: + led->isink.brightness = min(level, led->isink.max_brightness); + break; + default: + led->isink.brightness = 0; + break; + } + + return mt6370_isnk_brightness_set(&led->isink, led->isink.brightness); +} + +static int mt6370_led_register(struct device *parent, struct mt6370_led *led, + struct led_init_data *init_data) +{ + struct mt6370_priv *priv = led->priv; + int ret; + + if (led->index == MT6370_VIRTUAL_MULTICOLOR) { + ret = mt6370_mc_brightness_set(&led->mc.led_cdev, 0); + if (ret) + return dev_err_probe(parent, ret, + "Couldn't set multicolor brightness\n"); + + ret = devm_led_classdev_multicolor_register_ext(parent, + &led->mc, + init_data); + if (ret) + return dev_err_probe(parent, ret, + "Couldn't register multicolor\n"); + } else { + if (led->index == MT6370_LED_ISNK4) { + ret = regmap_field_write(priv->fields[F_CHGIND_EN], 1); + if (ret) + return dev_err_probe(parent, ret, + "Failed to set CHRIND to SW\n"); + } + + ret = mt6370_isnk_init_default_state(led); + if (ret) + return dev_err_probe(parent, ret, + "Failed to init %d isnk state\n", + led->index); + + ret = devm_led_classdev_register_ext(parent, &led->isink, + init_data); + if (ret) + return dev_err_probe(parent, ret, + "Couldn't register isink %d\n", + led->index); + } + + return 0; +} + +static int mt6370_check_vendor_info(struct mt6370_priv *priv) +{ + unsigned int devinfo, vid; + int ret; + + ret = regmap_read(priv->regmap, MT6370_REG_DEV_INFO, &devinfo); + if (ret) + return ret; + + vid = FIELD_GET(MT6370_VENID_MASK, devinfo); + if (vid == 0x9 || vid == 0xb) { + priv->reg_fields = mt6372_reg_fields; + priv->ranges = mt6372_led_ranges; + priv->pdata = &mt6372_pdata; + } else { + /* Common for MT6370/71 */ + priv->reg_fields = common_reg_fields; + priv->ranges = common_led_ranges; + priv->pdata = &common_pdata; + } + + return 0; +} + +static int mt6370_leds_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct mt6370_priv *priv; + struct fwnode_handle *child; + size_t count; + unsigned int i = 0; + int ret; + + count = device_get_child_node_count(dev); + if (!count || count > MT6370_MAX_LEDS) + return dev_err_probe(dev, -EINVAL, + "No child node or node count over max LED number %zu\n", + count); + + priv = devm_kzalloc(dev, struct_size(priv, leds, count), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->leds_count = count; + priv->dev = dev; + mutex_init(&priv->lock); + + priv->regmap = dev_get_regmap(dev->parent, NULL); + if (!priv->regmap) + return dev_err_probe(dev, -ENODEV, "Failed to get parent regmap\n"); + + ret = mt6370_check_vendor_info(priv); + if (ret) + return dev_err_probe(dev, ret, "Failed to check vendor info\n"); + + ret = devm_regmap_field_bulk_alloc(dev, priv->regmap, priv->fields, + priv->reg_fields, F_MAX_FIELDS); + if (ret) + return dev_err_probe(dev, ret, "Failed to allocate regmap field\n"); + + device_for_each_child_node(dev, child) { + struct mt6370_led *led = priv->leds + i++; + struct led_init_data init_data = { .fwnode = child }; + u32 reg, color; + + ret = fwnode_property_read_u32(child, "reg", ®); + if (ret) + return dev_err_probe(dev, ret, "Failed to parse reg property\n"); + + if (reg >= MT6370_MAX_LEDS) + return dev_err_probe(dev, -EINVAL, "Error reg property number\n"); + + ret = fwnode_property_read_u32(child, "color", &color); + if (ret) + return dev_err_probe(dev, ret, "Failed to parse color property\n"); + + if (color == LED_COLOR_ID_RGB || color == LED_COLOR_ID_MULTI) + reg = MT6370_VIRTUAL_MULTICOLOR; + + if (priv->leds_active & BIT(reg)) + return dev_err_probe(dev, -EINVAL, "Duplicate reg property\n"); + + priv->leds_active |= BIT(reg); + + led->index = reg; + led->priv = priv; + + ret = mt6370_init_led_properties(led, &init_data); + if (ret) + return ret; + + ret = mt6370_led_register(&pdev->dev, led, &init_data); + if (ret) + return ret; + } + + return 0; +} + +static const struct of_device_id mt6370_rgbled_device_table[] = { + { .compatible = "mediatek,mt6370-indicator" }, + {} +}; +MODULE_DEVICE_TABLE(of, mt6370_rgbled_device_table); + +static struct platform_driver mt6370_rgbled_driver = { + .driver = { + .name = "mt6370-indicator", + .of_match_table = mt6370_rgbled_device_table, + }, + .probe = mt6370_leds_probe, +}; +module_platform_driver(mt6370_rgbled_driver); + +MODULE_AUTHOR("Alice Chen "); +MODULE_AUTHOR("ChiYuan Huang "); +MODULE_DESCRIPTION("MediaTek MT6370 RGB LED Driver"); +MODULE_LICENSE("GPL v2"); From patchwork Fri Aug 5 07:06:09 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: ChiaEn Wu X-Patchwork-Id: 12936982 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 14E53C00140 for ; Fri, 5 Aug 2022 07:18:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=pfL0QO+JfvZzO4BTq3EpFy7ibJ1VXkKz6nkMFy+aePI=; b=DGFae7dFoI9IG/gd3QAigJ5c31 3wN9pYAcCv3UTmOsCyCUUfXq3JJwFoC/RUEHVuy2qCPEHYbLakdej6sMSXzcikBFlt5+qxAUZtp25 DCS0Ssf6UkY52iev37Sun4XkNr7EIW62AlGWiLpXflIxCgbbfAkm78wiyQw5Aii69lv5tn+Fq/bZ2 4ycC3zrd1mxyf0zse2q11aiiK0qH5a4xieF1qJPnTK0hggtIZ+YkVRrMZLyKE06m5YYuGBxn4TeaU gz3qUHBMkakv4Xz5WmAY+BTeJX5PlrY09/xYegbGdhmlDBQsq8VGSWSnme9+0ZBuZ6svNKU7iT1y8 TTHx8olQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1oJrb9-00CmXP-PI; Fri, 05 Aug 2022 07:18:19 +0000 Received: from mail-pj1-x102b.google.com ([2607:f8b0:4864:20::102b]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1oJrR7-00Chf2-99; Fri, 05 Aug 2022 07:08:03 +0000 Received: by mail-pj1-x102b.google.com with SMTP id b4so1896645pji.4; Fri, 05 Aug 2022 00:07:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc; bh=pfL0QO+JfvZzO4BTq3EpFy7ibJ1VXkKz6nkMFy+aePI=; b=AH3jjXiC4FReqnadod6ZAaUbKYOtl90uZk1tSrKBcsX2VFqQxrqjEYq3oMIhbEVb5S 8X3f91OWh8EhCcCcIQ4bytrxDYPEHxNo6af/7Wag+soqDnxjfwFWRDYWdUVQY6bzuzHy zZfGOxh3Pr4O+HGTBHAvJf74JnnPiZsj2Y+TShlRBy6+gZD6MTjm/pvZMF1GqXddkfGo 26tvqGwR4J1759hnyX2krtb6In08kjcR4oXJgLEtrPtlyGi2X0WFSSAN5DSM1N47BStX 4gEGfEd/IWxXNvU0pjZXX6ABnwIj1gnx47YziG9r3JNMDGgGEF+26BNULhTdOdzgnJwC uGDw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc; bh=pfL0QO+JfvZzO4BTq3EpFy7ibJ1VXkKz6nkMFy+aePI=; b=Q2EuGhFvtJFh+qAn3DpftCE9485YV7vh/jBlkRJtYTHYRuxVx8I9d3ga62vvudiGbB pB1xrji5tTiAd7hKDNQ9u30y/RNqyM38CUEFQfOhRUwh7h4WoYKQUQZ/zx8nJlHNpv6q H8YGG3F/qohxCfr5zU94Kp1Of/KnoJyyTe9SrfiH4YfN/EXEBPo868/EZcXpMyejvZnT MzUEkQXL3blTcOiHqbrR0xy+RlFc7aWtM5wjxgf4lRGvZZr0RXk2cPlIQ4PK14VdAh91 3zfqMQ/zOxQncZ2kzhee+tIQmfORsvJg+Sfj1ErFTsZq6fAyaQBy6s4V/GCym0Ur/Iu8 vmUA== X-Gm-Message-State: ACgBeo2p32mQPxntm3x9WwMz1sxOmwM9A0gQhPquMJiIHVhd43fVhrrt q8ww9WBL5Wcu24iY9/VLLvQ= X-Google-Smtp-Source: AA6agR6HcijcID1ZXj16zWWjNI4BaGj6lKBUm5HX6mBzON/c4gupbDT01TpfgsNlNnO7fv8fgNyo5g== X-Received: by 2002:a17:90a:d783:b0:1f4:e30b:ece with SMTP id z3-20020a17090ad78300b001f4e30b0ecemr6224500pju.165.1659683273448; Fri, 05 Aug 2022 00:07:53 -0700 (PDT) Received: from RD-3580-24288.rt.l (42-72-229-62.emome-ip.hinet.net. [42.72.229.62]) by smtp.gmail.com with ESMTPSA id i5-20020a056a00224500b00525343b5047sm2191616pfu.76.2022.08.05.00.07.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 05 Aug 2022 00:07:53 -0700 (PDT) From: ChiaEn Wu To: lee.jones@linaro.org, daniel.thompson@linaro.org, jingoohan1@gmail.com, pavel@ucw.cz, robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, matthias.bgg@gmail.com, sre@kernel.org, chunfeng.yun@mediatek.com, gregkh@linuxfoundation.org, jic23@kernel.org, lars@metafoo.de, lgirdwood@gmail.com, broonie@kernel.org, linux@roeck-us.net, heikki.krogerus@linux.intel.com, deller@gmx.de, andy.shevchenko@gmail.com Cc: chiaen_wu@richtek.com, alice_chen@richtek.com, cy_huang@richtek.com, dri-devel@lists.freedesktop.org, linux-leds@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, linux-usb@vger.kernel.org, linux-iio@vger.kernel.org, linux-fbdev@vger.kernel.org, szunichen@gmail.com Subject: [PATCH v7 12/13] leds: flash: mt6370: Add MediaTek MT6370 flashlight support Date: Fri, 5 Aug 2022 15:06:09 +0800 Message-Id: <20220805070610.3516-13-peterwu.pub@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220805070610.3516-1-peterwu.pub@gmail.com> References: <20220805070610.3516-1-peterwu.pub@gmail.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220805_000757_518524_70A0ADC3 X-CRM114-Status: GOOD ( 29.35 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org From: Alice Chen The MediaTek MT6370 is a highly-integrated smart power management IC, which includes a single cell Li-Ion/Li-Polymer switching battery charger, a USB Type-C & Power Delivery (PD) controller, dual Flash LED current sources, a RGB LED driver, a backlight WLED driver, a display bias driver and a general LDO for portable devices. Add a support for the MT6370 Flash LED driver. Flash LED in MT6370 has 2 channels and support torch/strobe mode. Signed-off-by: Alice Chen Signed-off-by: ChiaEn Wu --- v7 - Fix the indentation. - For the well defined macro, the parenthesis is needed for input parameters. - Replace some dev_warn to dev_info in 'init_flash_properties'. - Add sentinel comment for the terminator entry of of_device_id. - Use priv->fled_torch_used directly. - Delete 0 in {}. - Use _uA instead of _UA in definition. - Refine the description. - Use usleep_range instead of udelay. - Rename config to LEDS_MT6370_FLASH. - Add missing ">" in copyright. - Change the Kconfig order --- drivers/leds/flash/Kconfig | 12 + drivers/leds/flash/Makefile | 1 + drivers/leds/flash/leds-mt6370-flash.c | 632 +++++++++++++++++++++++++++++++++ 3 files changed, 645 insertions(+) create mode 100644 drivers/leds/flash/leds-mt6370-flash.c diff --git a/drivers/leds/flash/Kconfig b/drivers/leds/flash/Kconfig index d3eb689..4b1afc1 100644 --- a/drivers/leds/flash/Kconfig +++ b/drivers/leds/flash/Kconfig @@ -61,6 +61,18 @@ config LEDS_MT6360 Independent current sources supply for each flash LED support torch and strobe mode. +config LEDS_MT6370_FLASH + tristate "Flash LED Support for MediaTek MT6370 PMIC" + depends on LEDS_CLASS + depends on MFD_MT6370 + help + Support 2 channels and torch/strobe mode. + Say Y here to enable support for + MT6370_FLASH_LED device. + + This driver can also be built as a module. If so, the module + will be called "leds-mt6370-flash". + config LEDS_RT4505 tristate "LED support for RT4505 flashlight controller" depends on I2C && OF diff --git a/drivers/leds/flash/Makefile b/drivers/leds/flash/Makefile index 0acbddc..0c1f3c5 100644 --- a/drivers/leds/flash/Makefile +++ b/drivers/leds/flash/Makefile @@ -9,3 +9,4 @@ obj-$(CONFIG_LEDS_MAX77693) += leds-max77693.o obj-$(CONFIG_LEDS_RT4505) += leds-rt4505.o obj-$(CONFIG_LEDS_RT8515) += leds-rt8515.o obj-$(CONFIG_LEDS_SGM3140) += leds-sgm3140.o +obj-$(CONFIG_LEDS_MT6370_FLASH) += leds-mt6370-flash.o diff --git a/drivers/leds/flash/leds-mt6370-flash.c b/drivers/leds/flash/leds-mt6370-flash.c new file mode 100644 index 0000000..e36e264 --- /dev/null +++ b/drivers/leds/flash/leds-mt6370-flash.c @@ -0,0 +1,632 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2022 Richtek Technology Corp. + * + * Author: Alice Chen + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +enum { + MT6370_LED_FLASH1, + MT6370_LED_FLASH2, + MT6370_MAX_LEDS +}; + +/* Virtual definition for multicolor */ + +#define MT6370_REG_FLEDEN 0x17E +#define MT6370_REG_STRBTO 0x173 +#define MT6370_REG_CHGSTAT2 0x1D1 +#define MT6370_REG_FLEDSTAT1 0x1D9 +#define MT6370_REG_FLEDISTRB(_id) (0x174 + 4 * (_id)) +#define MT6370_REG_FLEDITOR(_id) (0x175 + 4 * (_id)) +#define MT6370_ITORCH_MASK GENMASK(4, 0) +#define MT6370_ISTROBE_MASK GENMASK(6, 0) +#define MT6370_STRBTO_MASK GENMASK(6, 0) +#define MT6370_TORCHEN_MASK BIT(3) +#define MT6370_STROBEN_MASK BIT(2) +#define MT6370_FLCSEN_MASK(_id) BIT(MT6370_LED_FLASH2 - (_id)) +#define MT6370_FLCSEN_MASK_ALL GENMASK(1, 0) +#define MT6370_FLEDCHGVINOVP_MASK BIT(3) +#define MT6370_FLED1STRBTO_MASK BIT(11) +#define MT6370_FLED2STRBTO_MASK BIT(10) +#define MT6370_FLED1STRB_MASK BIT(9) +#define MT6370_FLED2STRB_MASK BIT(8) +#define MT6370_FLED1SHORT_MASK BIT(7) +#define MT6370_FLED2SHORT_MASK BIT(6) +#define MT6370_FLEDLVF_MASK BIT(3) + +#define MT6370_LED_JOINT 2 +#define MT6370_RANGE_FLED_REG 4 +#define MT6370_ITORCH_MIN_uA 25000 +#define MT6370_ITORCH_STEP_uA 12500 +#define MT6370_ITORCH_MAX_uA 400000 +#define MT6370_ITORCH_DOUBLE_MAX_uA 800000 +#define MT6370_ISTRB_MIN_uA 50000 +#define MT6370_ISTRB_STEP_uA 12500 +#define MT6370_ISTRB_MAX_uA 1500000 +#define MT6370_ISTRB_DOUBLE_MAX_uA 3000000 +#define MT6370_STRBTO_MIN_US 64000 +#define MT6370_STRBTO_STEP_US 32000 +#define MT6370_STRBTO_MAX_US 2432000 + +#define STATE_OFF 0 +#define STATE_KEEP 1 +#define STATE_ON 2 + +#define to_mt6370_led(ptr, member) container_of(ptr, struct mt6370_led, member) + +struct mt6370_led { + struct led_classdev_flash flash; + struct v4l2_flash *v4l2_flash; + struct mt6370_priv *priv; + u32 led_no; + u32 default_state; +}; + +struct mt6370_priv { + struct device *dev; + struct regmap *regmap; + struct mutex lock; + unsigned int fled_strobe_used; + unsigned int fled_torch_used; + unsigned int leds_active; + unsigned int leds_count; + struct mt6370_led leds[]; +}; + +static int mt6370_torch_brightness_set(struct led_classdev *lcdev, + enum led_brightness level) +{ + struct mt6370_led *led = to_mt6370_led(lcdev, flash.led_cdev); + struct mt6370_priv *priv = led->priv; + u32 led_enable_mask = (led->led_no == MT6370_LED_JOINT) ? + MT6370_FLCSEN_MASK_ALL : + MT6370_FLCSEN_MASK(led->led_no); + u32 enable_mask = MT6370_TORCHEN_MASK | led_enable_mask; + u32 val = level ? led_enable_mask : 0; + u32 curr; + int ret, i; + + mutex_lock(&priv->lock); + + /* + * Only one set of flash control logic, + * use the flag to avoid strobe is currently used. + */ + if (priv->fled_strobe_used) { + dev_warn(lcdev->dev, "Please disable strobe first [%d]\n", + priv->fled_strobe_used); + ret = -EBUSY; + goto unlock; + } + + if (level) + curr = priv->fled_torch_used | BIT(led->led_no); + else + curr = priv->fled_torch_used & ~BIT(led->led_no); + + if (curr) + val |= MT6370_TORCHEN_MASK; + + if (level) { + level -= 1; + if (led->led_no == MT6370_LED_JOINT) { + int flevel[MT6370_MAX_LEDS]; + + flevel[0] = level / 2; + flevel[1] = level - flevel[0]; + for (i = 0; i < MT6370_MAX_LEDS; i++) { + ret = regmap_update_bits(priv->regmap, + MT6370_REG_FLEDITOR(i), + MT6370_ITORCH_MASK, flevel[i]); + if (ret) + goto unlock; + } + } else { + ret = regmap_update_bits(priv->regmap, + MT6370_REG_FLEDITOR(led->led_no), + MT6370_ITORCH_MASK, level); + if (ret) + goto unlock; + } + } + + ret = regmap_update_bits(priv->regmap, MT6370_REG_FLEDEN, + enable_mask, val); + if (ret) + goto unlock; + + priv->fled_torch_used = curr; + +unlock: + mutex_unlock(&priv->lock); + return ret; +} + +static int mt6370_flash_brightness_set(struct led_classdev_flash *fl_cdev, + u32 brightness) +{ + /* + * Due to the current spike when turning on flash, + * let brightness be kept by the framework. + * This empty function is used to + * prevent led_classdev_flash register ops check failure. + */ + return 0; +} + +static int _mt6370_flash_brightness_set(struct led_classdev_flash *fl_cdev, + u32 brightness) +{ + struct mt6370_led *led = to_mt6370_led(fl_cdev, flash); + struct mt6370_priv *priv = led->priv; + struct led_flash_setting *s = &fl_cdev->brightness; + u32 val = (brightness - s->min) / s->step; + int ret, i; + + if (led->led_no == MT6370_LED_JOINT) { + int flevel[MT6370_MAX_LEDS]; + + flevel[0] = val / 2; + flevel[1] = val - flevel[0]; + for (i = 0; i < MT6370_MAX_LEDS; i++) { + ret = regmap_update_bits(priv->regmap, + MT6370_REG_FLEDISTRB(i), + MT6370_ISTROBE_MASK, flevel[i]); + if (ret) + return ret; + } + } else { + return regmap_update_bits(priv->regmap, + MT6370_REG_FLEDISTRB(led->led_no), + MT6370_ISTROBE_MASK, val); + } + + return 0; +} + +static int mt6370_strobe_set(struct led_classdev_flash *fl_cdev, bool state) +{ + struct mt6370_led *led = to_mt6370_led(fl_cdev, flash); + struct mt6370_priv *priv = led->priv; + struct led_classdev *lcdev = &fl_cdev->led_cdev; + struct led_flash_setting *s = &fl_cdev->brightness; + u32 led_enable_mask = (led->led_no == MT6370_LED_JOINT) ? + MT6370_FLCSEN_MASK_ALL : + MT6370_FLCSEN_MASK(led->led_no); + u32 enable_mask = MT6370_STROBEN_MASK | led_enable_mask; + u32 val = state ? led_enable_mask : 0; + u32 curr; + int ret; + + mutex_lock(&priv->lock); + + /* + * Only one set of flash control logic, + * use the flag to avoid torch is currently used + */ + if (priv->fled_torch_used) { + dev_warn(lcdev->dev, "Please disable torch first [0x%x]\n", + priv->fled_torch_used); + ret = -EBUSY; + goto unlock; + } + + if (state) + curr = priv->fled_strobe_used | BIT(led->led_no); + else + curr = priv->fled_strobe_used & ~BIT(led->led_no); + + if (curr) + val |= MT6370_STROBEN_MASK; + + ret = regmap_update_bits(priv->regmap, MT6370_REG_FLEDEN, enable_mask, + val); + if (ret) { + dev_err(lcdev->dev, "[%d] control current source %d fail\n", + led->led_no, state); + goto unlock; + } + + /* + * If the flash needs to be on, + * config the flash current ramping up to the setting value. + * Else, always recover back to the minimum one. + */ + ret = _mt6370_flash_brightness_set(fl_cdev, state ? s->val : s->min); + if (ret) + goto unlock; + + /* + * For the flash to turn on/off, we need to wait HW ramping up/down time + * 5ms/500us to prevent the unexpected problem. + */ + if (!priv->fled_strobe_used && curr) + usleep_range(5000, 6000); + else if (priv->fled_strobe_used && !curr) + usleep_range(500, 600); + + priv->fled_strobe_used = curr; + +unlock: + mutex_unlock(&priv->lock); + return ret; +} + +static int mt6370_strobe_get(struct led_classdev_flash *fl_cdev, bool *state) +{ + struct mt6370_led *led = to_mt6370_led(fl_cdev, flash); + struct mt6370_priv *priv = led->priv; + + mutex_lock(&priv->lock); + *state = !!(priv->fled_strobe_used & BIT(led->led_no)); + mutex_unlock(&priv->lock); + + return 0; +} + +static int mt6370_timeout_set(struct led_classdev_flash *fl_cdev, u32 timeout) +{ + struct mt6370_led *led = to_mt6370_led(fl_cdev, flash); + struct mt6370_priv *priv = led->priv; + struct led_flash_setting *s = &fl_cdev->timeout; + u32 val = (timeout - s->min) / s->step; + int ret; + + mutex_lock(&priv->lock); + ret = regmap_update_bits(priv->regmap, MT6370_REG_STRBTO, + MT6370_STRBTO_MASK, val); + mutex_unlock(&priv->lock); + + return ret; +} + +static int mt6370_fault_get(struct led_classdev_flash *fl_cdev, u32 *fault) +{ + struct mt6370_led *led = to_mt6370_led(fl_cdev, flash); + struct mt6370_priv *priv = led->priv; + u16 fled_stat; + unsigned int chg_stat, strobe_timeout_mask, fled_short_mask; + u32 rfault = 0; + int ret; + + mutex_lock(&priv->lock); + ret = regmap_read(priv->regmap, MT6370_REG_CHGSTAT2, &chg_stat); + if (ret) + goto unlock; + + ret = regmap_raw_read(priv->regmap, MT6370_REG_FLEDSTAT1, &fled_stat, + sizeof(fled_stat)); + if (ret) + goto unlock; + + switch (led->led_no) { + case MT6370_LED_FLASH1: + strobe_timeout_mask = MT6370_FLED1STRBTO_MASK; + fled_short_mask = MT6370_FLED1SHORT_MASK; + break; + + case MT6370_LED_FLASH2: + strobe_timeout_mask = MT6370_FLED2STRBTO_MASK; + fled_short_mask = MT6370_FLED2SHORT_MASK; + break; + + case MT6370_LED_JOINT: + strobe_timeout_mask = MT6370_FLED1STRBTO_MASK | + MT6370_FLED2STRBTO_MASK; + fled_short_mask = MT6370_FLED1SHORT_MASK | + MT6370_FLED2SHORT_MASK; + } + + if (chg_stat & MT6370_FLEDCHGVINOVP_MASK) + rfault |= LED_FAULT_INPUT_VOLTAGE; + + if (fled_stat & strobe_timeout_mask) + rfault |= LED_FAULT_TIMEOUT; + + if (fled_stat & fled_short_mask) + rfault |= LED_FAULT_SHORT_CIRCUIT; + + if (fled_stat & MT6370_FLEDLVF_MASK) + rfault |= LED_FAULT_UNDER_VOLTAGE; + + *fault = rfault; +unlock: + mutex_unlock(&priv->lock); + return ret; +} + +static const struct led_flash_ops mt6370_flash_ops = { + .flash_brightness_set = mt6370_flash_brightness_set, + .strobe_set = mt6370_strobe_set, + .strobe_get = mt6370_strobe_get, + .timeout_set = mt6370_timeout_set, + .fault_get = mt6370_fault_get, +}; + +#if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS) +static int mt6370_flash_external_strobe_set(struct v4l2_flash *v4l2_flash, + bool enable) +{ + struct led_classdev_flash *flash = v4l2_flash->fled_cdev; + struct mt6370_led *led = to_mt6370_led(flash, flash); + struct mt6370_priv *priv = led->priv; + u32 mask = (led->led_no == MT6370_LED_JOINT) ? MT6370_FLCSEN_MASK_ALL : + MT6370_FLCSEN_MASK(led->led_no); + u32 val = enable ? mask : 0; + int ret; + + mutex_lock(&priv->lock); + ret = regmap_update_bits(priv->regmap, MT6370_REG_FLEDEN, mask, val); + if (ret) + goto unlock; + + if (enable) + priv->fled_strobe_used |= BIT(led->led_no); + else + priv->fled_strobe_used &= ~BIT(led->led_no); + +unlock: + mutex_unlock(&priv->lock); + return ret; +} + +static const struct v4l2_flash_ops v4l2_flash_ops = { + .external_strobe_set = mt6370_flash_external_strobe_set, +}; + +static void mt6370_init_v4l2_flash_config(struct mt6370_led *led, + struct v4l2_flash_config *config) +{ + struct led_classdev *lcdev; + struct led_flash_setting *s = &config->intensity; + + lcdev = &led->flash.led_cdev; + + s->min = MT6370_ITORCH_MIN_uA; + s->step = MT6370_ITORCH_STEP_uA; + s->val = s->max = s->min + (lcdev->max_brightness - 1) * s->step; + + config->has_external_strobe = 1; + strscpy(config->dev_name, lcdev->dev->kobj.name, + sizeof(config->dev_name)); + + config->flash_faults = LED_FAULT_SHORT_CIRCUIT | LED_FAULT_TIMEOUT | + LED_FAULT_INPUT_VOLTAGE | + LED_FAULT_UNDER_VOLTAGE; +} +#else +static const struct v4l2_flash_ops v4l2_flash_ops; +static void mt6370_init_v4l2_flash_config(struct mt6370_led *led, + struct v4l2_flash_config *config) +{ +} +#endif + +static void mt6370_v4l2_flash_release(void *v4l2_flash) +{ + v4l2_flash_release(v4l2_flash); +} + +static int mt6370_led_register(struct device *parent, struct mt6370_led *led, + struct led_init_data *init_data) +{ + struct v4l2_flash_config v4l2_config = {}; + int ret; + + ret = devm_led_classdev_flash_register_ext(parent, &led->flash, + init_data); + if (ret) + return dev_err_probe(parent, ret, + "Couldn't register flash %d\n", led->led_no); + + mt6370_init_v4l2_flash_config(led, &v4l2_config); + led->v4l2_flash = v4l2_flash_init(parent, init_data->fwnode, + &led->flash, &v4l2_flash_ops, + &v4l2_config); + if (IS_ERR(led->v4l2_flash)) + return dev_err_probe(parent, PTR_ERR(led->v4l2_flash), + "Failed to register %d v4l2 sd\n", led->led_no); + + return devm_add_action_or_reset(parent, mt6370_v4l2_flash_release, + led->v4l2_flash); +} + +static u32 mt6370_clamp(u32 val, u32 min, u32 max, u32 step) +{ + u32 retval; + + retval = clamp_val(val, min, max); + if (step > 1) + retval = rounddown(retval - min, step) + min; + + return retval; +} + +static int mt6370_init_flash_properties(struct mt6370_led *led, + struct led_init_data *init_data) +{ + struct led_classdev_flash *flash = &led->flash; + struct led_classdev *lcdev = &flash->led_cdev; + struct mt6370_priv *priv = led->priv; + struct led_flash_setting *s; + u32 sources[MT6370_MAX_LEDS]; + u32 max_uA, val; + int i, ret, num; + + num = fwnode_property_count_u32(init_data->fwnode, "led-sources"); + if (num < 1 || num > MT6370_MAX_LEDS) + return dev_err_probe(priv->dev, -EINVAL, + "Not specified or wrong number of led-sources\n"); + + ret = fwnode_property_read_u32_array(init_data->fwnode, "led-sources", sources, num); + if (ret) + return ret; + + for (i = 0; i < num; i++) { + if (sources[i] >= MT6370_MAX_LEDS) + return -EINVAL; + if (priv->leds_active & BIT(sources[i])) + return -EINVAL; + priv->leds_active |= BIT(sources[i]); + + } + led->led_no = (num == MT6370_MAX_LEDS) ? MT6370_LED_JOINT : + sources[0]; + + max_uA = (num == 2) ? MT6370_ITORCH_DOUBLE_MAX_uA : MT6370_ITORCH_MAX_uA; + ret = fwnode_property_read_u32(init_data->fwnode, "led-max-microamp", &val); + if (ret) { + dev_info(priv->dev, + "Not specified led-max-microamp, config to the minimum\n"); + val = MT6370_ITORCH_MIN_uA; + } else { + val = mt6370_clamp(val, MT6370_ITORCH_MIN_uA, max_uA, + MT6370_ITORCH_STEP_uA); + } + + lcdev->max_brightness = (val - MT6370_ITORCH_MIN_uA) / + MT6370_ITORCH_STEP_uA + 1; + lcdev->brightness_set_blocking = mt6370_torch_brightness_set; + lcdev->flags |= LED_DEV_CAP_FLASH; + + max_uA = (num == 2) ? MT6370_ISTRB_DOUBLE_MAX_uA : MT6370_ISTRB_MAX_uA; + ret = fwnode_property_read_u32(init_data->fwnode, "flash-max-microamp", &val); + if (ret) { + dev_info(priv->dev, + "Not specified flash-max-microamp, config to the minimum\n"); + val = MT6370_ISTRB_MIN_uA; + } else { + val = mt6370_clamp(val, MT6370_ISTRB_MIN_uA, max_uA, + MT6370_ISTRB_STEP_uA); + } + + s = &flash->brightness; + s->min = MT6370_ISTRB_MIN_uA; + s->step = MT6370_ISTRB_STEP_uA; + s->val = s->max = val; + + /* + * Always configure as min level when off to + * prevent flash current spike + */ + ret = _mt6370_flash_brightness_set(flash, s->min); + if (ret) + return ret; + + ret = fwnode_property_read_u32(init_data->fwnode, + "flash-max-timeout-us", &val); + if (ret) { + dev_info(priv->dev, + "Not specified flash-max-timeout-us, config to the minimum\n"); + val = MT6370_STRBTO_MIN_US; + } else { + val = mt6370_clamp(val, MT6370_STRBTO_MIN_US, + MT6370_STRBTO_MAX_US, MT6370_STRBTO_STEP_US); + } + + s = &flash->timeout; + s->min = MT6370_STRBTO_MIN_US; + s->step = MT6370_STRBTO_STEP_US; + s->val = s->max = val; + + flash->ops = &mt6370_flash_ops; + + return 0; +} + +static int mt6370_init_common_properties(struct mt6370_led *led, + struct led_init_data *init_data) +{ + const char * const states[] = { "off", "keep", "on" }; + const char *str = states[STATE_OFF]; + int ret; + + fwnode_property_read_string(init_data->fwnode, "default-state", &str); + ret = match_string(states, ARRAY_SIZE(states), str); + if (ret >= 0) + led->default_state = ret; + + return 0; +} + +static int mt6370_led_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct mt6370_priv *priv; + struct fwnode_handle *child; + size_t count; + int i = 0, ret; + + count = device_get_child_node_count(dev); + if (!count || count > MT6370_MAX_LEDS) + return dev_err_probe(dev, -EINVAL, + "No child node or node count over max led number %zu\n", count); + + priv = devm_kzalloc(dev, struct_size(priv, leds, count), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->leds_count = count; + priv->dev = dev; + mutex_init(&priv->lock); + + priv->regmap = dev_get_regmap(dev->parent, NULL); + if (!priv->regmap) + return dev_err_probe(dev, -ENODEV, "Failed to get parent regmap\n"); + + device_for_each_child_node(dev, child) { + struct mt6370_led *led = priv->leds + i; + struct led_init_data init_data = { .fwnode = child, }; + + led->priv = priv; + ret = mt6370_init_common_properties(led, &init_data); + if (ret) + return ret; + + ret = mt6370_init_flash_properties(led, &init_data); + if (ret) + return ret; + + ret = mt6370_led_register(dev, led, &init_data); + if (ret) + return ret; + + i++; + } + + return 0; +} + +static const struct of_device_id mt6370_led_of_id[] = { + { .compatible = "mediatek,mt6370-flashlight" }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, mt6370_led_of_id); + +static struct platform_driver mt6370_led_driver = { + .driver = { + .name = "mt6370-flashlight", + .of_match_table = mt6370_led_of_id, + }, + .probe = mt6370_led_probe, +}; +module_platform_driver(mt6370_led_driver); + +MODULE_AUTHOR("Alice Chen "); +MODULE_DESCRIPTION("MT6370 FLASH LED Driver"); +MODULE_LICENSE("GPL v2"); From patchwork Fri Aug 5 07:06:10 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: ChiaEn Wu X-Patchwork-Id: 12936983 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 6A86BC00140 for ; Fri, 5 Aug 2022 07:19:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=YAxk3vL6GhIczbGpfuIOdQos3fVrmEMM0piPGUYBRuE=; b=W94ki6WdqenJzM9UcLfPb91zG4 g8JT2mkFyQJE1uKksCE/OobfKY4puMMhI6BxuaVMdiOdlQaT6T6SivCpp/ILmwCdybEs1mvcYB6k5 sWh4EhzI/IQHRuSR2EJojH8FSWoiJ7UnSwyQLepHt5i31PReU01F8FmhAXyNSyT6y7+Z6C5CpVKLR pGthwRjQ7kkQf92fnzeOKLMID6S/TNsV4niGOJqBNrY/adviBu6oWZ67s7a+AXOUFB3pn8yLI6CZj 5b/zhEKf2TRPO1Op2dautX15JltltQ4nueh4S7237q/QUvIGux92qpN10KcxpkQyioSKzIo48mYAr EWFwl0Vg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1oJrcF-00Cn3j-P7; Fri, 05 Aug 2022 07:19:27 +0000 Received: from mail-pl1-x629.google.com ([2607:f8b0:4864:20::629]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1oJrRD-00ChiX-Ob; Fri, 05 Aug 2022 07:08:08 +0000 Received: by mail-pl1-x629.google.com with SMTP id 17so1879868plj.10; Fri, 05 Aug 2022 00:08:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc; bh=YAxk3vL6GhIczbGpfuIOdQos3fVrmEMM0piPGUYBRuE=; b=f3HiBRo1T6HLpmHCMCMclFqR4rWqJdxfFnb9dccg/7SgesO/uwgcoWCvnb6WJ14sph CRBGMHqRZPe0Qa7M96E8Asm9dPDxTOsHxHnG7KV0rjJ8Wqz0yIhSNquH1x6TbpwNDXqB 8WXIaJTdxHpEsfJslZbdpTCI0r6WGP3GXOiu2m4+QLk3BDR96Kx+XLoxdL/7tvL8CI63 UMaVh52KUIRi7MNGoDDI6ScYDHQkD5fZIFDIp6hvVk0hZLhLs3b3QnchYlNggW8MBdha NxM/xWIBOptnHoZ8gO/2qH+ecxVHjKQ4zjr1MNbM/u9AMmcQ3Aj3q7Q+OAV9bWhFSgwM DU2Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc; bh=YAxk3vL6GhIczbGpfuIOdQos3fVrmEMM0piPGUYBRuE=; b=0MQBAPmxRoYxSbpqLQWqeLKkP0222ubgw5FHjz2OI/qXPfh0cx7nNBeCB88CyLoD5L E4+tj/tNnPdmAPyoSm1TNABRCAXbUW+hxci/mbbqkHh/sUP6/FQJ/k881Dh7WmFFWneM bEeHOxu0KSHdgVU8/2VdZx4l5VjX39yntpjPQEhZJ3oYxZ8dNtJD4MldS+nIGz7neO+M /zRuCXL0d9Kzi+KFzvjIMGAcPZibx47rrP3ACUpqroCXtg2Cah6meCfVRdrdD/mfCSSh DaYgC3LzYFwl94DFEAkxSPqFYpKfMFLdcgkynfkpYvd+AoNheOql1XIxsT59piUijMwk APzg== X-Gm-Message-State: ACgBeo0y1rzwtDP5CuVvh5/vsVgLXQ5TLcQGKMC1d5oNzkxpXLrRm9qa oXJZAC37S5tuZ8yoYpATopM= X-Google-Smtp-Source: AA6agR56i3Fk4n3QeMAgHOhxMv+xUpTa7UverxJGsNiNwDxGlivCt9PBfwYkI7x9fsX/I5UuVDmkkA== X-Received: by 2002:a17:90b:1b11:b0:1f2:2d70:70d7 with SMTP id nu17-20020a17090b1b1100b001f22d7070d7mr14630865pjb.59.1659683281010; Fri, 05 Aug 2022 00:08:01 -0700 (PDT) Received: from RD-3580-24288.rt.l (42-72-229-62.emome-ip.hinet.net. [42.72.229.62]) by smtp.gmail.com with ESMTPSA id i5-20020a056a00224500b00525343b5047sm2191616pfu.76.2022.08.05.00.07.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 05 Aug 2022 00:08:00 -0700 (PDT) From: ChiaEn Wu To: lee.jones@linaro.org, daniel.thompson@linaro.org, jingoohan1@gmail.com, pavel@ucw.cz, robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, matthias.bgg@gmail.com, sre@kernel.org, chunfeng.yun@mediatek.com, gregkh@linuxfoundation.org, jic23@kernel.org, lars@metafoo.de, lgirdwood@gmail.com, broonie@kernel.org, linux@roeck-us.net, heikki.krogerus@linux.intel.com, deller@gmx.de, andy.shevchenko@gmail.com Cc: chiaen_wu@richtek.com, alice_chen@richtek.com, cy_huang@richtek.com, dri-devel@lists.freedesktop.org, linux-leds@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, linux-usb@vger.kernel.org, linux-iio@vger.kernel.org, linux-fbdev@vger.kernel.org, szunichen@gmail.com Subject: [PATCH v7 13/13] video: backlight: mt6370: Add MediaTek MT6370 support Date: Fri, 5 Aug 2022 15:06:10 +0800 Message-Id: <20220805070610.3516-14-peterwu.pub@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220805070610.3516-1-peterwu.pub@gmail.com> References: <20220805070610.3516-1-peterwu.pub@gmail.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220805_000804_056338_0D3A627B X-CRM114-Status: GOOD ( 25.35 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org From: ChiaEn Wu MediaTek MT6370 is a SubPMIC consisting of a single cell battery charger with ADC monitoring, RGB LEDs, dual channel flashlight, WLED backlight driver, display bias voltage supply, one general purpose LDO, and the USB Type-C & PD controller complies with the latest USB Type-C and PD standards. Add a support for the MediaTek MT6370 backlight driver. It controls 4 channels of 8 series WLEDs in 2048 (only for MT6370/MT6371) / 16384 (only for MT6372) current steps (30 mA) in exponential or linear mapping curves. Signed-off-by: ChiaEn Wu --- v7 - Add support 'exponential mode' property parsing - Add 'return dev_err_probe()' after 'if (IS_ERR(priv->enable_gpio))' - Add 'mt6372' compatible string - Revise Kconfig help text - Revise update()/get() for supporting 16384 steps (MT6372) - Revise all shift usages form using 'ffs() and fls()' to defining the _SHIFT macros. - Revise 'brightness ? 1 : 0' to '!!brightness' in gpiod_set_value() --- drivers/video/backlight/Kconfig | 13 ++ drivers/video/backlight/Makefile | 1 + drivers/video/backlight/mt6370-backlight.c | 351 +++++++++++++++++++++++++++++ 3 files changed, 365 insertions(+) create mode 100644 drivers/video/backlight/mt6370-backlight.c diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index a003e02..936ba1e 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig @@ -268,6 +268,19 @@ config BACKLIGHT_MAX8925 If you have a LCD backlight connected to the WLED output of MAX8925 WLED output, say Y here to enable this driver. +config BACKLIGHT_MT6370 + tristate "MediaTek MT6370 Backlight Driver" + depends on MFD_MT6370 + help + This enables support for Mediatek MT6370 Backlight driver. + It's commonly used to drive the display WLED. There are 4 channels + inside, and each channel supports up to 30mA of current capability + with 2048 current steps (only for MT6370/MT6371) or 16384 current + steps (only for MT6372) in exponential or linear mapping curves. + + This driver can also be built as a module. If so, the module + will be called "mt6370-backlight". + config BACKLIGHT_APPLE tristate "Apple Backlight Driver" depends on X86 && ACPI diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile index cae2c83..e815f3f 100644 --- a/drivers/video/backlight/Makefile +++ b/drivers/video/backlight/Makefile @@ -44,6 +44,7 @@ obj-$(CONFIG_BACKLIGHT_LP855X) += lp855x_bl.o obj-$(CONFIG_BACKLIGHT_LP8788) += lp8788_bl.o obj-$(CONFIG_BACKLIGHT_LV5207LP) += lv5207lp.o obj-$(CONFIG_BACKLIGHT_MAX8925) += max8925_bl.o +obj-$(CONFIG_BACKLIGHT_MT6370) += mt6370-backlight.o obj-$(CONFIG_BACKLIGHT_OMAP1) += omap1_bl.o obj-$(CONFIG_BACKLIGHT_PANDORA) += pandora_bl.o obj-$(CONFIG_BACKLIGHT_PCF50633) += pcf50633-backlight.o diff --git a/drivers/video/backlight/mt6370-backlight.c b/drivers/video/backlight/mt6370-backlight.c new file mode 100644 index 0000000..4c889b4 --- /dev/null +++ b/drivers/video/backlight/mt6370-backlight.c @@ -0,0 +1,351 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2022 Richtek Technology Corp. + * + * Author: ChiaEn Wu + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MT6370_REG_DEV_INFO 0x100 +#define MT6370_REG_BL_EN 0x1A0 +#define MT6370_REG_BL_BSTCTRL 0x1A1 +#define MT6370_REG_BL_PWM 0x1A2 +#define MT6370_REG_BL_DIM2 0x1A4 + +#define MT6370_VENID_MASK GENMASK(7, 4) +#define MT6370_BL_EXT_EN_MASK BIT(7) +#define MT6370_BL_EN_MASK BIT(6) +#define MT6370_BL_CODE_MASK BIT(0) +#define MT6370_BL_CH_MASK GENMASK(5, 2) +#define MT6370_BL_CH_SHIFT 2 +#define MT6370_BL_DIM2_COMMON_MASK GENMASK(2, 0) +#define MT6370_BL_DIM2_COMMON_SHIFT 3 +#define MT6370_BL_DIM2_6372_MASK GENMASK(5, 0) +#define MT6370_BL_DIM2_6372_SHIFT 6 +#define MT6370_BL_PWM_EN_MASK BIT(7) +#define MT6370_BL_PWM_HYS_EN_MASK BIT(2) +#define MT6370_BL_PWM_HYS_SEL_MASK GENMASK(1, 0) +#define MT6370_BL_OVP_EN_MASK BIT(7) +#define MT6370_BL_OVP_SEL_MASK GENMASK(6, 5) +#define MT6370_BL_OVP_SEL_SHIFT 5 +#define MT6370_BL_OC_EN_MASK BIT(3) +#define MT6370_BL_OC_SEL_MASK GENMASK(2, 1) +#define MT6370_BL_OC_SEL_SHIFT 1 + +#define MT6370_BL_PWM_HYS_TH_MIN_STEP 1 +#define MT6370_BL_PWM_HYS_TH_MAX_STEP 64 +#define MT6370_BL_OVP_MIN_UV 17000000 +#define MT6370_BL_OVP_MAX_UV 29000000 +#define MT6370_BL_OVP_STEP_UV 4000000 +#define MT6370_BL_OCP_MIN_UA 900000 +#define MT6370_BL_OCP_MAX_UA 1800000 +#define MT6370_BL_OCP_STEP_UA 300000 +#define MT6370_BL_MAX_COMMON_BRIGHTNESS 2048 +#define MT6370_BL_MAX_6372_BRIGHTNESS 16384 +#define MT6370_BL_MAX_CH 15 + +enum { + MT6370_VID_COMMON = 1, + MT6370_VID_6372, +}; + +struct mt6370_priv { + u8 dim2_mask; + u8 dim2_shift; + int def_max_brightness; + struct backlight_device *bl; + struct device *dev; + struct gpio_desc *enable_gpio; + struct regmap *regmap; +}; + +static int mt6370_bl_update_status(struct backlight_device *bl_dev) +{ + struct mt6370_priv *priv = bl_get_data(bl_dev); + int brightness = backlight_get_brightness(bl_dev); + unsigned int enable_val; + u8 brightness_val[2]; + int ret; + + if (brightness) { + brightness_val[0] = (brightness - 1) & priv->dim2_mask; + brightness_val[1] = (brightness - 1) >> priv->dim2_shift; + + ret = regmap_raw_write(priv->regmap, MT6370_REG_BL_DIM2, + brightness_val, sizeof(brightness_val)); + if (ret) + return ret; + } + + gpiod_set_value(priv->enable_gpio, !!brightness); + + enable_val = brightness ? MT6370_BL_EN_MASK : 0; + return regmap_update_bits(priv->regmap, MT6370_REG_BL_EN, + MT6370_BL_EN_MASK, enable_val); +} + +static int mt6370_bl_get_brightness(struct backlight_device *bl_dev) +{ + struct mt6370_priv *priv = bl_get_data(bl_dev); + unsigned int enable; + u8 brightness_val[2]; + int brightness, ret; + + ret = regmap_read(priv->regmap, MT6370_REG_BL_EN, &enable); + if (ret) + return ret; + + if (!(enable & MT6370_BL_EN_MASK)) + return 0; + + ret = regmap_raw_read(priv->regmap, MT6370_REG_BL_DIM2, + brightness_val, sizeof(brightness_val)); + if (ret) + return ret; + + brightness = brightness_val[1] << priv->dim2_shift; + brightness += brightness_val[0] & priv->dim2_mask; + + return brightness + 1; +} + +static const struct backlight_ops mt6370_bl_ops = { + .options = BL_CORE_SUSPENDRESUME, + .update_status = mt6370_bl_update_status, + .get_brightness = mt6370_bl_get_brightness, +}; + +static int mt6370_init_backlight_properties(struct mt6370_priv *priv, + struct backlight_properties *props) +{ + struct device *dev = priv->dev; + u8 prop_val; + u32 brightness, ovp_uV, ocp_uA; + unsigned int mask, val; + int ret; + + /* Vendor optional properties */ + val = 0; + if (device_property_read_bool(dev, "mediatek,bled-pwm-enable")) + val |= MT6370_BL_PWM_EN_MASK; + + if (device_property_read_bool(dev, "mediatek,bled-pwm-hys-enable")) + val |= MT6370_BL_PWM_HYS_EN_MASK; + + ret = device_property_read_u8(dev, + "mediatek,bled-pwm-hys-input-th-steps", + &prop_val); + if (!ret) { + prop_val = clamp_val(prop_val, + MT6370_BL_PWM_HYS_TH_MIN_STEP, + MT6370_BL_PWM_HYS_TH_MAX_STEP); + prop_val = prop_val <= 1 ? 0 : + prop_val <= 4 ? 1 : + prop_val <= 16 ? 2 : 3; + val |= prop_val; + } + + ret = regmap_update_bits(priv->regmap, MT6370_REG_BL_PWM, + val, val); + if (ret) + return ret; + + val = 0; + if (device_property_read_bool(dev, "mediatek,bled-ovp-shutdown")) + val |= MT6370_BL_OVP_EN_MASK; + + ret = device_property_read_u32(dev, "mediatek,bled-ovp-microvolt", + &ovp_uV); + if (!ret) { + ovp_uV = clamp_val(ovp_uV, MT6370_BL_OVP_MIN_UV, + MT6370_BL_OVP_MAX_UV); + ovp_uV = DIV_ROUND_UP(ovp_uV - MT6370_BL_OVP_MIN_UV, + MT6370_BL_OVP_STEP_UV); + val |= ovp_uV << MT6370_BL_OVP_SEL_SHIFT; + } + + if (device_property_read_bool(dev, "mediatek,bled-ocp-shutdown")) + val |= MT6370_BL_OC_EN_MASK; + + ret = device_property_read_u32(dev, "mediatek,bled-ocp-microamp", + &ocp_uA); + if (!ret) { + ocp_uA = clamp_val(ocp_uA, MT6370_BL_OCP_MIN_UA, + MT6370_BL_OCP_MAX_UA); + ocp_uA = DIV_ROUND_UP(ocp_uA - MT6370_BL_OCP_MIN_UA, + MT6370_BL_OCP_STEP_UA); + val |= ocp_uA << MT6370_BL_OC_SEL_SHIFT; + } + + ret = regmap_update_bits(priv->regmap, MT6370_REG_BL_BSTCTRL, + val, val); + if (ret) + return ret; + + /* Common properties */ + ret = device_property_read_u32(dev, "max-brightness", &brightness); + if (ret) + brightness = priv->def_max_brightness; + + props->max_brightness = min_t(u32, brightness, priv->def_max_brightness); + + ret = device_property_read_u32(dev, "default-brightness", &brightness); + if (ret) + brightness = props->max_brightness; + + props->brightness = min_t(u32, brightness, props->max_brightness); + + val = 0; + if (device_property_read_bool(dev, "mediatek,bled-exponential-mode-enable")) { + val |= MT6370_BL_CODE_MASK; + props->scale = BACKLIGHT_SCALE_NON_LINEAR; + } else + props->scale = BACKLIGHT_SCALE_LINEAR; + + ret = device_property_read_u8(dev, "mediatek,bled-channel-use", + &prop_val); + if (ret) { + dev_err(dev, "mediatek,bled-channel-use DT property missing\n"); + return ret; + } + + if (!prop_val || prop_val > MT6370_BL_MAX_CH) { + dev_err(dev, + "No channel specified or over than upper bound (%d)\n", + prop_val); + return -EINVAL; + } + + mask = MT6370_BL_EXT_EN_MASK | MT6370_BL_CH_MASK; + val |= prop_val << MT6370_BL_CH_SHIFT; + + if (priv->enable_gpio) + val |= MT6370_BL_EXT_EN_MASK; + + return regmap_update_bits(priv->regmap, MT6370_REG_BL_EN, mask, val); +} + +static int mt6370_check_vendor_info(struct mt6370_priv *priv) +{ + /* + * MT6372 uses 14 bits to control the brightness but MT6370 and MT6371 + * use 11 bits. They are different so we have to use this function to + * check the vendor ID and use different mask, shift and default + * maxiimum brightness value. + */ + unsigned int dev_info, hw_vid, of_vid; + int ret; + + ret = regmap_read(priv->regmap, MT6370_REG_DEV_INFO, &dev_info); + if (ret) + return ret; + + of_vid = (uintptr_t)of_device_get_match_data(priv->dev); + hw_vid = FIELD_GET(MT6370_VENID_MASK, dev_info); + hw_vid = hw_vid == 0x9 || hw_vid == 0xb ? MT6370_VID_6372 : MT6370_VID_COMMON; + if (hw_vid != of_vid) { + dev_err(priv->dev, "Buggy DT, wrong compatible string\n"); + return -EINVAL; + } + + if (hw_vid == MT6370_VID_6372) { + priv->dim2_mask = MT6370_BL_DIM2_6372_MASK; + priv->dim2_shift = MT6370_BL_DIM2_6372_SHIFT; + priv->def_max_brightness = MT6370_BL_MAX_6372_BRIGHTNESS; + } else { + priv->dim2_mask = MT6370_BL_DIM2_COMMON_MASK; + priv->dim2_shift = MT6370_BL_DIM2_COMMON_SHIFT; + priv->def_max_brightness = MT6370_BL_MAX_COMMON_BRIGHTNESS; + } + + return 0; +} + +static int mt6370_bl_probe(struct platform_device *pdev) +{ + struct backlight_properties props = { + .type = BACKLIGHT_RAW, + }; + struct device *dev = &pdev->dev; + struct mt6370_priv *priv; + int ret; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->dev = dev; + + priv->regmap = dev_get_regmap(dev->parent, NULL); + if (!priv->regmap) + return dev_err_probe(dev, -ENODEV, "Failed to get regmap\n"); + + ret = mt6370_check_vendor_info(priv); + if (ret) + return dev_err_probe(dev, ret, "Failed to check vendor info\n"); + + priv->enable_gpio = devm_gpiod_get_optional(dev, "enable", + GPIOD_OUT_HIGH); + if (IS_ERR(priv->enable_gpio)) + return dev_err_probe(dev, PTR_ERR(priv->enable_gpio), + "Failed to get 'enable' gpio\n"); + + ret = mt6370_init_backlight_properties(priv, &props); + if (ret) + return dev_err_probe(dev, ret, + "Failed to init backlight properties\n"); + + priv->bl = devm_backlight_device_register(dev, pdev->name, dev, priv, + &mt6370_bl_ops, &props); + if (IS_ERR(priv->bl)) + return dev_err_probe(dev, PTR_ERR(priv->bl), + "Failed to register backlight\n"); + + backlight_update_status(priv->bl); + platform_set_drvdata(pdev, priv); + + return 0; +} + +static int mt6370_bl_remove(struct platform_device *pdev) +{ + struct mt6370_priv *priv = platform_get_drvdata(pdev); + struct backlight_device *bl_dev = priv->bl; + + bl_dev->props.brightness = 0; + backlight_update_status(priv->bl); + + return 0; +} + +static const struct of_device_id __maybe_unused mt6370_bl_of_match[] = { + { .compatible = "mediatek,mt6370-backlight", .data = (void *)MT6370_VID_COMMON }, + { .compatible = "mediatek,mt6372-backlight", .data = (void *)MT6370_VID_6372 }, + {} +}; +MODULE_DEVICE_TABLE(of, mt6370_bl_of_match); + +static struct platform_driver mt6370_bl_driver = { + .driver = { + .name = "mt6370-backlight", + .of_match_table = mt6370_bl_of_match, + }, + .probe = mt6370_bl_probe, + .remove = mt6370_bl_remove, +}; +module_platform_driver(mt6370_bl_driver); + +MODULE_AUTHOR("ChiaEn Wu "); +MODULE_DESCRIPTION("MediaTek MT6370 Backlight Driver"); +MODULE_LICENSE("GPL v2");