From patchwork Sun Dec 5 23:15:53 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Lezcano X-Patchwork-Id: 520893 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id CDDE5C433F5 for ; Sun, 5 Dec 2021 23:16:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237314AbhLEXTx (ORCPT ); Sun, 5 Dec 2021 18:19:53 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37304 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236903AbhLEXTu (ORCPT ); Sun, 5 Dec 2021 18:19:50 -0500 Received: from mail-wm1-x32a.google.com (mail-wm1-x32a.google.com [IPv6:2a00:1450:4864:20::32a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8C5D0C061354 for ; Sun, 5 Dec 2021 15:16:22 -0800 (PST) Received: by mail-wm1-x32a.google.com with SMTP id p18so6786768wmq.5 for ; Sun, 05 Dec 2021 15:16:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=+c/CHs8+P5F4ROQuUBwTx+ZVLn3ISFq8kc+Oou9iGQ8=; b=dAGmoX48rPq8f8yClhp/9pEBKE0wneGWphnEqgy9lL9akQfNz1quxO3SJXvAPC8zg/ x2Q2plsEBr2kV7BHv1UEvnXXkBMGxSgMfVzkc3C0VmBaF5KMy90UdfvlKeOHPLE40z6V JnMUS2kBXX1WsANtZ9RL2L3Coxtr8ZYXnJW8ax5y0uIyshFKzOkKxgAQwVNl5BV492H1 rwWz3uNPyOPA4ImcMf70NOhDMrVVZRHLwBUGwLkfSnZbRzLyKtmCT/zsBeCpP+eMjl1q geYTAh/A5NKsNyyWAqO/zqdTiSba/3wI73QySpp8q1d3ikrFKdz0P59jkcL8ySwYQ2s4 uDcQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=+c/CHs8+P5F4ROQuUBwTx+ZVLn3ISFq8kc+Oou9iGQ8=; b=E+tMwKhVYJ/agVvTUofPmL4VrmLsr1hFQckyN5nJF3787hwEf2CTusTCuh1WbEWZpf /SlD8s311h0/9Khk/58A67tPnxWHiQ7OrWRHrYQCWjBG+BFo1edZP31ZhSGLpLK7hx29 ligGjIrzALC+xhyI1gWqa7qo/9tKPFWSgf1BxZ8XH4vkIjFdEispJt8XLU8NwryjNlVH fthiQapKcV3/daTPIAIo4BDtYjiiv/1A/2/k+8fmmtj7RXshTWEGz+etN11b0BA7oJfj zab4NwYXxsjN28QrjghxWKfCbmMYzpYQ7Dht4ZCYcCRdwR9g9lLJpKfrSp0Rr2TAmqaA mfIg== X-Gm-Message-State: AOAM532tDtk+qg/pH9oNh2icl0WIsANq/2r6mhzHe5nNmaojxeovRZXa 9O3sLUd8K2BaJLQ0qLnhWlDZ027qsjO7Ow== X-Google-Smtp-Source: ABdhPJwljnwNzc2F5v5ySS4bugsbhLnbG29KOvP4c+1SZcp8/mX3i1Lh4VIFKqoqSuN1Kwhy4cWsRA== X-Received: by 2002:a1c:ed0a:: with SMTP id l10mr33951514wmh.140.1638746180791; Sun, 05 Dec 2021 15:16:20 -0800 (PST) Received: from localhost.localdomain ([2a01:e34:ed2f:f020:1cec:4235:bb04:b944]) by smtp.gmail.com with ESMTPSA id c10sm10715312wrb.81.2021.12.05.15.16.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 05 Dec 2021 15:16:18 -0800 (PST) From: Daniel Lezcano To: daniel.lezcano@linaro.org, robh@kernel.org Cc: arnd@linaro.org, heiko@sntech.de, ulf.hansson@linaro.org, rjw@rjwysocki.net, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, lukasz.luba@arm.com, Arnd Bergmann , Rob Herring Subject: [PATCH v4 1/5] dt-bindings: Powerzone new bindings Date: Mon, 6 Dec 2021 00:15:53 +0100 Message-Id: <20211205231558.779698-1-daniel.lezcano@linaro.org> X-Mailer: git-send-email 2.25.1 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org The proposed bindings are describing a set of powerzones. A power zone is the logical name for a component which is capable of power capping and where we can measure the power consumption. A power zone can aggregate several power zones in terms of power measurement and power limitations. That allows to apply power constraint to a group of components and let the system balance the allocated power in order to comply with the constraint. The ARM System Control and Management Interface (SCMI) can provide a power zone description. The powerzone semantic is also found on the Intel platform with the RAPL register. The Linux kernel powercap framework deals with the powerzones: https://www.kernel.org/doc/html/latest/power/powercap/powercap.html The powerzone can also represent a group of children powerzones, hence the description can result on a hierarchy. Such hierarchy already exists with the hardware or can be represented and computed from the kernel. The hierarchical description was initially proposed but not desired given there are other descriptions like the power domain proposing almost the same description. https://lore.kernel.org/all/CAL_JsqLuLcHj7525tTUmh7pLqe7T2j6UcznyhV7joS8ipyb_VQ@mail.gmail.com/ The description gives the power constraint dependencies to apply on a specific group of logically or physically aggregated devices. They do not represent the physical location or the power domains of the SoC even if the description could be similar. Cc: Arnd Bergmann Cc: Ulf Hansson Cc: Rob Herring Reviewed-by: Ulf Hansson Signed-off-by: Daniel Lezcano --- V3: - Removed required property 'compatible' - Removed powerzone-cells from the topmost node - Removed powerzone-cells from cpus 'consumers' in example - Set additionnal property to false V2: - Added pattern properties and stick to powerzone-* - Added required property compatible and powerzone-cells - Added additionnal property - Added compatible - Renamed to 'powerzones' - Added missing powerzone-cells to the topmost node - Fixed errors reported by 'make DT_CHECKER_FLAGS=-m dt_binding_check' V1: Initial post --- .../devicetree/bindings/power/powerzones.yaml | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 Documentation/devicetree/bindings/power/powerzones.yaml diff --git a/Documentation/devicetree/bindings/power/powerzones.yaml b/Documentation/devicetree/bindings/power/powerzones.yaml new file mode 100644 index 000000000000..ddb790acfea6 --- /dev/null +++ b/Documentation/devicetree/bindings/power/powerzones.yaml @@ -0,0 +1,97 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/power/powerzones.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Power zones description + +maintainers: + - Daniel Lezcano + +description: |+ + + A System on Chip contains a multitude of active components and each + of them is a source of heat. Even if a temperature sensor is not + present, a source of heat can be controlled by acting on the + consumed power via different techniques. + + A powerzone describes a component or a group of components where we + can control the maximum power consumption. For instance, a group of + CPUs via the performance domain, a LCD screen via the brightness, + etc ... + + Different components when they are used together can significantly + increase the overall temperature, so the description needs to + reflect this dependency in order to assign a power budget for a + group of powerzones. + + This description is done via a hierarchy and the DT reflects it. It + does not represent the physical location or a topology, eg. on a + big.Little system, the little CPUs may not be represented as they do + not contribute significantly to the heat, however the GPU can be + tied with the big CPUs as they usually have a connection for + multimedia or game workloads. + +properties: + $nodename: + const: powerzones + +patternProperties: + "^(powerzone)([@-].*)?$": + type: object + description: + A node representing a powerzone acting as an aggregator for all + its children powerzones. + + properties: + "#powerzone-cells": + description: + Number of cells in powerzone specifier. Typically 0 for nodes + representing but it can be any number in the future to + describe parameters of the powerzone. + + powerzones: + description: + A phandle to a parent powerzone. If no powerzone attribute is + set, the described powerzone is the topmost in the hierarchy. + + required: + - "#powerzone-cells" + +additionalProperties: false + +examples: + - | + powerzones { + + SOC_PZ: powerzone-soc { + #powerzone-cells = <0>; + }; + + PKG_PZ: powerzone-pkg { + #powerzone-cells = <0>; + powerzones = <&SOC_PZ>; + }; + + GPU_PZ: powerzone-gpu { + #powerzone-cells = <0>; + powerzones = <&PKG_PZ>; + }; + }; + + - | + A57_0: big@0 { + compatible = "arm,cortex-a57"; + reg = <0x0 0x0>; + device_type = "cpu"; + powerzones = <&PKG_PZ>; + }; + + A57_1: big@1 { + compatible = "arm,cortex-a57"; + reg = <0x0 0x0>; + device_type = "cpu"; + powerzones = <&PKG_PZ>; + }; +... From patchwork Sun Dec 5 23:15:54 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Lezcano X-Patchwork-Id: 521186 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 874EBC433F5 for ; Sun, 5 Dec 2021 23:16:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240845AbhLEXTz (ORCPT ); Sun, 5 Dec 2021 18:19:55 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37320 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238644AbhLEXTy (ORCPT ); Sun, 5 Dec 2021 18:19:54 -0500 Received: from mail-wr1-x42a.google.com (mail-wr1-x42a.google.com [IPv6:2a00:1450:4864:20::42a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 44A6FC061751 for ; Sun, 5 Dec 2021 15:16:26 -0800 (PST) Received: by mail-wr1-x42a.google.com with SMTP id o13so18565214wrs.12 for ; Sun, 05 Dec 2021 15:16:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=8SDUVe0WxBDs+x5sc5VSRWK56FrB6jL4WHqSjP3zaxg=; b=cFxn+LobBn91bijKgZt4wvkEUlRGNJXoHSktLeYNUXT4t9jx/rtJPZNldDLus0razj tZgAOLiS+Z5Tb8DdLRtm16Oz2mcI2Y/yoswW+T++FTm57zRXmJieHSGSiW5oh5DZ8YMu +qTRIz6a8AjbHVWxcSGm4v6kFwEa+lr3puIuIXphGqYMFCTF7IWmDiRAfutGki64qmMI S2/rdQnomZlWQtbApsZPoXSqqwGVF8sY2qdGmGqoSj7XMOr2DicKQzX81Hw2/moENz8A LTvkuPKpql4ZWJDbPHXk1kdMSY1SIxO74p20I7TSse6l5pZt2PvJ+IU21Dqapj6GXNuP B+Kw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=8SDUVe0WxBDs+x5sc5VSRWK56FrB6jL4WHqSjP3zaxg=; b=v1e6j6mN0aEWe9HFWDBap6LLH2XuyYrcacPGfYSpRAPsB5BHYyUghnu0BQkzhAPhyN cI/YS9cAY4f4yfjonwbYGv1dhyWFNyr/IwT4Xn2az4LInzbtarKkuYRpq3YDoK0oX8BP +k7c7QNXMv0hyWm0Im3eW8AC4wB/TrZuYp8wr+vNi5+Fhasl4y/WQ7KTFoKPl7OcoYs4 NwvDGS801bwKUhrtOLXyqkreHI0ou3gzAYOVC8ULVxzVWcgmo0nok/TJJA4GRO9NHydo IoKwtlLyu8xSM2BgHBnF03b7i9NanrBvt58uCcKXybzx7V4PqWQ6wzWgbXIX53Q1ifLp l+oQ== X-Gm-Message-State: AOAM533kf8TFqgYpVNr1pFEzL4fVt511RuAMMVB4SFDdAiQkLL5dZ9S7 jdxf74AQ6FeoGGgmpl4QuzmO0g== X-Google-Smtp-Source: ABdhPJwW/WzVl4850fY0QcNuzEze9AMto83BQfOb4lnMqjG4ZtCnCG4vkv9DnLBn5gb4pwj4Nr/HUg== X-Received: by 2002:adf:fe8e:: with SMTP id l14mr39797739wrr.177.1638746184732; Sun, 05 Dec 2021 15:16:24 -0800 (PST) Received: from localhost.localdomain ([2a01:e34:ed2f:f020:1cec:4235:bb04:b944]) by smtp.gmail.com with ESMTPSA id c10sm10715312wrb.81.2021.12.05.15.16.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 05 Dec 2021 15:16:24 -0800 (PST) From: Daniel Lezcano To: daniel.lezcano@linaro.org, robh@kernel.org Cc: arnd@linaro.org, heiko@sntech.de, ulf.hansson@linaro.org, rjw@rjwysocki.net, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, lukasz.luba@arm.com, Robin Murphy , Rob Herring , Johan Jonker , Helen Koike , Brian Norris , Elaine Zhang , linux-arm-kernel@lists.infradead.org (moderated list:ARM/Rockchip SoC support), linux-rockchip@lists.infradead.org (open list:ARM/Rockchip SoC support) Subject: [PATCH v4 2/5] arm64: dts: rockchip: Add powerzones definition for rock960 Date: Mon, 6 Dec 2021 00:15:54 +0100 Message-Id: <20211205231558.779698-2-daniel.lezcano@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20211205231558.779698-1-daniel.lezcano@linaro.org> References: <20211205231558.779698-1-daniel.lezcano@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org Add the powerzones description. This first step introduces the big, the little as powerzone places. Cc: Robin Murphy Reviewed-by: Ulf Hansson Signed-off-by: Daniel Lezcano --- V4: - Added missing powerzone-cells - Changed powerzone name to comply with the pattern property V3: - Remove GPU section as no power is available (yet) - Remove '#powerzone-cells' conforming to the bindings change V2: - Move description in the SoC dtsi specific file V1: Initial post --- arch/arm64/boot/dts/rockchip/rk3399.dtsi | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi index d3cdf6f42a30..901515898b5e 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi @@ -76,6 +76,7 @@ cpu_l0: cpu@0 { #cooling-cells = <2>; /* min followed by max */ dynamic-power-coefficient = <100>; cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; + powerzone = <&PKG_PZ>; }; cpu_l1: cpu@1 { @@ -88,6 +89,7 @@ cpu_l1: cpu@1 { #cooling-cells = <2>; /* min followed by max */ dynamic-power-coefficient = <100>; cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; + powerzone = <&PKG_PZ>; }; cpu_l2: cpu@2 { @@ -100,6 +102,7 @@ cpu_l2: cpu@2 { #cooling-cells = <2>; /* min followed by max */ dynamic-power-coefficient = <100>; cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; + powerzone = <&PKG_PZ>; }; cpu_l3: cpu@3 { @@ -112,6 +115,7 @@ cpu_l3: cpu@3 { #cooling-cells = <2>; /* min followed by max */ dynamic-power-coefficient = <100>; cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; + powerzone = <&PKG_PZ>; }; cpu_b0: cpu@100 { @@ -124,6 +128,7 @@ cpu_b0: cpu@100 { #cooling-cells = <2>; /* min followed by max */ dynamic-power-coefficient = <436>; cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; + powerzone = <&PKG_PZ>; thermal-idle { #cooling-cells = <2>; @@ -142,6 +147,7 @@ cpu_b1: cpu@101 { #cooling-cells = <2>; /* min followed by max */ dynamic-power-coefficient = <436>; cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>; + powerzone = <&PKG_PZ>; thermal-idle { #cooling-cells = <2>; @@ -791,6 +797,18 @@ spi5: spi@ff200000 { status = "disabled"; }; + powerzones { + + PKG_PZ: powerzone-pkg { + #powerzone-cells = <0>; + powerzone = <&SOC_PZ>; + }; + + SOC_PZ: powerzone-soc { + #powerzone-cells = <0>; + }; + }; + thermal_zones: thermal-zones { cpu_thermal: cpu-thermal { polling-delay-passive = <100>; From patchwork Sun Dec 5 23:15:55 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Lezcano X-Patchwork-Id: 520892 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B36FCC433EF for ; Sun, 5 Dec 2021 23:16:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240926AbhLEXUG (ORCPT ); Sun, 5 Dec 2021 18:20:06 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37338 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240989AbhLEXT4 (ORCPT ); Sun, 5 Dec 2021 18:19:56 -0500 Received: from mail-wr1-x434.google.com (mail-wr1-x434.google.com [IPv6:2a00:1450:4864:20::434]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 56AFDC061359 for ; Sun, 5 Dec 2021 15:16:28 -0800 (PST) Received: by mail-wr1-x434.google.com with SMTP id a9so18602589wrr.8 for ; Sun, 05 Dec 2021 15:16:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=ghUVEhvOdMPM8hnbGXgb0N6UgUT3EWuYvvMN4JA07EA=; b=DCQrHoCJ9TOuszjB9M/3oMVXxA1Mfn+E0yoLDXk6jj3cG4Opl8PiuEeQPVShb32X1w RIjmXv8kzISlX1RuJ5UbcUMFQkFtP5YhwBQ8v7FwiAvXETrO7yG7p6RTdi9g607m6whd xrZ8sqYRQqLtNhwIl2BmXlKq2rpn9XwZTnuFOnUkc00x1zIUA4fQZDvJhmpJnYm0OF1u 56JC+hvvfPUxV/IZ2+l+UgXRyzJMFbU+23bA9BOy++hrnFgCQ14pzcdNGliOuLzNEa/q bBPeb07AeA/HdDzs1yRGEh9RsSSHehfVayj6LGCGwWzVNhmF2grqtQDYJ1PJwtfqGpL2 cg7A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=ghUVEhvOdMPM8hnbGXgb0N6UgUT3EWuYvvMN4JA07EA=; b=Gir8c0fEicRZz+RtEmBahCev94ESqVTmjzcbeBxqcT9a2FG1NuimqrbKX2NbeaCov4 Z5r3B44pisZYSJHMgtq3toltYi41rucIDl4Uw4jHQyG1xZ0+pp7cksKl8RKqwnhTr2nh 0kphhR8L7Oo1H37GelnA2mPr1lEqGWL17Oufh9kVrY7lNL2BeTrg3gx6LpSlLpvQMy5/ R3WW7zeo+6UuYv79VDYSjP7IY3MESllb4grD0Galb4Y6+HIKM8Eb0Sy1ZtRr8ewj5QVL 7tJ9B6j0qluuWT3Hxy2o1Il1g0Up7LefiOrc7YnSBtZy0VpzBt+bL7ppiwBm/xUsCs9e tlsQ== X-Gm-Message-State: AOAM533tcMdBS/warClf44KM7qFXU9MK1pT4EqMAoku1s+ajIoS/SGLV /t4IiiUGPCj9t9hQgr7foAjhgA== X-Google-Smtp-Source: ABdhPJyUIZD1LyBcHJEIJNUtTe2QYDx2Vtg5MfN16R8uMODHQ06tvA7qJrZUbusucimzY/qInt/dUA== X-Received: by 2002:a05:6000:1842:: with SMTP id c2mr38379268wri.301.1638746186851; Sun, 05 Dec 2021 15:16:26 -0800 (PST) Received: from localhost.localdomain ([2a01:e34:ed2f:f020:1cec:4235:bb04:b944]) by smtp.gmail.com with ESMTPSA id c10sm10715312wrb.81.2021.12.05.15.16.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 05 Dec 2021 15:16:26 -0800 (PST) From: Daniel Lezcano To: daniel.lezcano@linaro.org, robh@kernel.org Cc: arnd@linaro.org, heiko@sntech.de, ulf.hansson@linaro.org, rjw@rjwysocki.net, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, lukasz.luba@arm.com, "Rafael J. Wysocki" , Daniel Lezcano Subject: [PATCH v4 3/5] powercap/drivers/dtpm: Add DT initialization support Date: Mon, 6 Dec 2021 00:15:55 +0100 Message-Id: <20211205231558.779698-3-daniel.lezcano@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20211205231558.779698-1-daniel.lezcano@linaro.org> References: <20211205231558.779698-1-daniel.lezcano@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org The DTPM framework is available but without a way to configure it. These changes add DT support to initialize the powercap hierarchy via the powerzones description. It acts in two steps. First it reads the powerzone dependencies and build the DTPM hierarchy. Second, it search for all devices which belongs to a powerzone and attach them to the hierarchy. This approach makes the initialization self-encapsulated for the DTPM components. In order to ensure a nice self-encapsulation, the DTPM table descriptors contains a couple of initialization functions, one to setup the DTPM backend and one to initialize it up. With this approach, the DTPM framework has a very few functions to export. Signed-off-by: Daniel Lezcano --- drivers/powercap/Kconfig | 1 + drivers/powercap/dtpm.c | 95 +++++++++++++++++++++++++++++++++++-- drivers/powercap/dtpm_cpu.c | 2 +- include/linux/dtpm.h | 19 +++++++- 4 files changed, 110 insertions(+), 7 deletions(-) diff --git a/drivers/powercap/Kconfig b/drivers/powercap/Kconfig index 8242e8c5ed77..b1ca339957e3 100644 --- a/drivers/powercap/Kconfig +++ b/drivers/powercap/Kconfig @@ -46,6 +46,7 @@ config IDLE_INJECT config DTPM bool "Power capping for Dynamic Thermal Power Management (EXPERIMENTAL)" + depends on OF help This enables support for the power capping for the dynamic thermal power management userspace engine. diff --git a/drivers/powercap/dtpm.c b/drivers/powercap/dtpm.c index 0fe70687c198..ebf08c0f489c 100644 --- a/drivers/powercap/dtpm.c +++ b/drivers/powercap/dtpm.c @@ -23,6 +23,7 @@ #include #include #include +#include #define DTPM_POWER_LIMIT_FLAG 0 @@ -461,9 +462,69 @@ int dtpm_register(const char *name, struct dtpm *dtpm, struct dtpm *parent) return 0; } -static int __init init_dtpm(void) +static int dtpm_for_each_child_of(struct device_node *root, + struct device_node *np, struct dtpm *parent) { + struct device_node *child; + struct device_node *pz; + struct dtpm *dtpm; + int ret; + + for_each_child_of_node(root, child) { + + pz = of_parse_phandle(child, "powerzone", 0); + if (pz != np) + continue; + + dtpm = kzalloc(sizeof(*dtpm), GFP_KERNEL); + if (!dtpm) + return -ENOMEM; + + dtpm_init(dtpm, NULL); + + ret = dtpm_register(child->name, dtpm, parent); + if (ret) { + pr_err("Failed to register dtpm node '%s'\n", child->name); + return ret; + } + + dtpm_set_data(dtpm, child); + + dtpm_for_each_child_of(root, child, dtpm); + } + + return 0; +} + +static int for_each_pz_dtpm(struct dtpm *dtpm, struct device_node *pz, + struct device_node *np, dtpm_setup_t setup) +{ + struct dtpm *child; + int ret = 0; + + if (dtpm_get_data(dtpm) == pz && setup) { + ret = setup(dtpm, np); + if (ret) + return ret; + } + + list_for_each_entry(child, &dtpm->children, sibling) + ret |= for_each_pz_dtpm(child, pz, np, setup); + + return ret; +} + +static int dtpm_probe(void) +{ + struct device_node *np; + struct device_node *pz; + struct dtpm_descr *dtpm_descr; + int ret; + + np = of_find_node_by_name(NULL, "powerzones"); + if (!np) + return 0; pct = powercap_register_control_type(NULL, "dtpm", NULL); if (IS_ERR(pct)) { @@ -471,9 +532,35 @@ static int __init init_dtpm(void) return PTR_ERR(pct); } - for_each_dtpm_table(dtpm_descr) - dtpm_descr->init(); + ret = dtpm_for_each_child_of(np, NULL, NULL); + if (ret) { + pr_err("Failed to read powerzones hierarchy: %d\n", ret); + goto out_release; + } + for_each_node_with_property(np, "powerzone") { + + pz = of_parse_phandle(np, "powerzone", 0); + + of_node_put(np); + if (!pz) + continue; + + for_each_dtpm_table(dtpm_descr) + for_each_pz_dtpm(root, pz, np, dtpm_descr->setup); + + of_node_put(pz); + } + + for_each_dtpm_table(dtpm_descr) + if (dtpm_descr->init) + dtpm_descr->init(); + return 0; + +out_release: + powercap_unregister_control_type(pct); + + return ret; } -late_initcall(init_dtpm); +late_initcall(dtpm_probe); diff --git a/drivers/powercap/dtpm_cpu.c b/drivers/powercap/dtpm_cpu.c index b740866b228d..6bffb44c75aa 100644 --- a/drivers/powercap/dtpm_cpu.c +++ b/drivers/powercap/dtpm_cpu.c @@ -269,4 +269,4 @@ static int __init dtpm_cpu_init(void) return 0; } -DTPM_DECLARE(dtpm_cpu, dtpm_cpu_init); +DTPM_DECLARE(dtpm_cpu, dtpm_cpu_init, NULL); diff --git a/include/linux/dtpm.h b/include/linux/dtpm.h index d37e5d06a357..7328682f24c9 100644 --- a/include/linux/dtpm.h +++ b/include/linux/dtpm.h @@ -32,23 +32,28 @@ struct dtpm_ops { void (*release)(struct dtpm *); }; +struct device_node; + typedef int (*dtpm_init_t)(void); +typedef int (*dtpm_setup_t)(struct dtpm *, struct device_node *); struct dtpm_descr { dtpm_init_t init; + dtpm_setup_t setup; }; /* Init section thermal table */ extern struct dtpm_descr __dtpm_table[]; extern struct dtpm_descr __dtpm_table_end[]; -#define DTPM_TABLE_ENTRY(name, __init) \ +#define DTPM_TABLE_ENTRY(name, __init, __setup) \ static struct dtpm_descr __dtpm_table_entry_##name \ __used __section("__dtpm_table") = { \ .init = __init, \ + .setup = __setup, \ } -#define DTPM_DECLARE(name, init) DTPM_TABLE_ENTRY(name, init) +#define DTPM_DECLARE(name, init, setup) DTPM_TABLE_ENTRY(name, init, setup) #define for_each_dtpm_table(__dtpm) \ for (__dtpm = __dtpm_table; \ @@ -60,6 +65,16 @@ static inline struct dtpm *to_dtpm(struct powercap_zone *zone) return container_of(zone, struct dtpm, zone); } +static inline void dtpm_set_data(struct dtpm *dtpm, void *data) +{ + powercap_set_zone_data(&dtpm->zone, data); +} + +static inline void *dtpm_get_data(struct dtpm *dtpm) +{ + return powercap_get_zone_data(&dtpm->zone); +} + int dtpm_update_power(struct dtpm *dtpm); int dtpm_release_zone(struct powercap_zone *pcz); From patchwork Sun Dec 5 23:15:56 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Lezcano X-Patchwork-Id: 521185 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 643AEC4332F for ; Sun, 5 Dec 2021 23:16:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241076AbhLEXUH (ORCPT ); Sun, 5 Dec 2021 18:20:07 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37354 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241080AbhLEXT6 (ORCPT ); Sun, 5 Dec 2021 18:19:58 -0500 Received: from mail-wr1-x42e.google.com (mail-wr1-x42e.google.com [IPv6:2a00:1450:4864:20::42e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0A028C061A83 for ; Sun, 5 Dec 2021 15:16:30 -0800 (PST) Received: by mail-wr1-x42e.google.com with SMTP id o13so18565378wrs.12 for ; Sun, 05 Dec 2021 15:16:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=JXIYabK6ZewRD4vP7R+kD9rZl3/XxOM5JXs9rSVNxs0=; b=BZ4TwD3SxJxsGh/FbEWbY/LJSI4250dSPguJNiIK4bcmeJxGvLC1J9w9IouTGYbE9n R+PvOndM1fHZGB3QIkRQXWXpQA2/vJ9TaXbuHYF3vLNb2gDVFCiLmJc9xM1eQPUH6bS4 5hPH3/MjatRpEHY/FDflFSx3apdrPdBuK+KsmhGV1cm1AzL2MONv73LF5jp+ObiiVUHD /BZS/MZN68qMshOjNZQL4EsNNHdSTIHeGkJqGyM3xaKuI/gkI0hLKDVAA+0w/yhZzak1 IY5REFVgNmv9ri6RhdAX+0kfwDvUhe39smhQI1ifJWOt76RgrpRkVNtWeElpa5BNXVRx tOCw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=JXIYabK6ZewRD4vP7R+kD9rZl3/XxOM5JXs9rSVNxs0=; b=4ERITKjsjpuSjr+taneMXgCfhwXT0VRi6Y408GqdeR4o3nNpqEMJpVD37Zz4SQHEtd LZDiDGTZVr/7WEOr2eTAhGZ2aPR1H5bD98tAs7gNZoRWYkeB7v3jFPHDl76/CzE//BPP +9LZVOA8WqxLs7vcQ2LFa4pM0MxBUWUOa+Rh60BMHxfhVpQKj+bC3EBRDIfKaTdrCgQw UNKF6xX3H2f9I/S/59vGgS9rH+DIS1bWgcg/rFkkUR6wRYUNUJogRpp+KnLTGK5i99fe jtynikQkoQ/SjYxne8xvdylYSXNIlPQCVCHiXFJls60cHNKVmromJ5Cpti9Wq2aFEPzD xgOQ== X-Gm-Message-State: AOAM531H3nQM4l+nYHNMmIStk6eT48gud4xQRpYLnyd1bIiU7iIIK9Rh WVfJhcJVlCcgeWlP/gKdNi9gPg== X-Google-Smtp-Source: ABdhPJzh6F/xXYdvKwGvpNmMucAAjEo9HmPzyZaEcasoGHS4tUxnfI5U5yON3hmWWFfY6xiA0kfI0Q== X-Received: by 2002:a05:6000:181:: with SMTP id p1mr39407367wrx.292.1638746188571; Sun, 05 Dec 2021 15:16:28 -0800 (PST) Received: from localhost.localdomain ([2a01:e34:ed2f:f020:1cec:4235:bb04:b944]) by smtp.gmail.com with ESMTPSA id c10sm10715312wrb.81.2021.12.05.15.16.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 05 Dec 2021 15:16:28 -0800 (PST) From: Daniel Lezcano To: daniel.lezcano@linaro.org, robh@kernel.org Cc: arnd@linaro.org, heiko@sntech.de, ulf.hansson@linaro.org, rjw@rjwysocki.net, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, lukasz.luba@arm.com, Daniel Lezcano , "Rafael J. Wysocki" Subject: [PATCH v4 4/5] powercap/drivers/dtpm: Add CPU DT initialization support Date: Mon, 6 Dec 2021 00:15:56 +0100 Message-Id: <20211205231558.779698-4-daniel.lezcano@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20211205231558.779698-1-daniel.lezcano@linaro.org> References: <20211205231558.779698-1-daniel.lezcano@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org Based on the previous DT changes in the core code, use the 'setup' callback to initialize the CPU DTPM backend. Code is reorganized to stick to the DTPM table description. No functional changes. Signed-off-by: Daniel Lezcano --- drivers/powercap/dtpm_cpu.c | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/drivers/powercap/dtpm_cpu.c b/drivers/powercap/dtpm_cpu.c index 6bffb44c75aa..64cec0770803 100644 --- a/drivers/powercap/dtpm_cpu.c +++ b/drivers/powercap/dtpm_cpu.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -176,6 +177,17 @@ static int cpuhp_dtpm_cpu_offline(unsigned int cpu) } static int cpuhp_dtpm_cpu_online(unsigned int cpu) +{ + struct dtpm_cpu *dtpm_cpu; + + dtpm_cpu = per_cpu(dtpm_per_cpu, cpu); + if (dtpm_cpu) + return dtpm_update_power(&dtpm_cpu->dtpm); + + return 0; +} + +static int __dtpm_cpu_setup(int cpu, struct dtpm *parent) { struct dtpm_cpu *dtpm_cpu; struct cpufreq_policy *policy; @@ -183,6 +195,10 @@ static int cpuhp_dtpm_cpu_online(unsigned int cpu) char name[CPUFREQ_NAME_LEN]; int ret = -ENOMEM; + dtpm_cpu = per_cpu(dtpm_per_cpu, cpu); + if (dtpm_cpu) + return 0; + policy = cpufreq_cpu_get(cpu); if (!policy) return 0; @@ -191,10 +207,6 @@ static int cpuhp_dtpm_cpu_online(unsigned int cpu) if (!pd) return -EINVAL; - dtpm_cpu = per_cpu(dtpm_per_cpu, cpu); - if (dtpm_cpu) - return dtpm_update_power(&dtpm_cpu->dtpm); - dtpm_cpu = kzalloc(sizeof(*dtpm_cpu), GFP_KERNEL); if (!dtpm_cpu) return -ENOMEM; @@ -207,7 +219,7 @@ static int cpuhp_dtpm_cpu_online(unsigned int cpu) snprintf(name, sizeof(name), "cpu%d-cpufreq", dtpm_cpu->cpu); - ret = dtpm_register(name, &dtpm_cpu->dtpm, NULL); + ret = dtpm_register(name, &dtpm_cpu->dtpm, parent); if (ret) goto out_kfree_dtpm_cpu; @@ -231,6 +243,17 @@ static int cpuhp_dtpm_cpu_online(unsigned int cpu) return ret; } +static int __init dtpm_cpu_setup(struct dtpm *dtpm, struct device_node *np) +{ + int cpu; + + cpu = of_cpu_node_to_id(np); + if (cpu < 0) + return 0; + + return __dtpm_cpu_setup(cpu, dtpm); +} + static int __init dtpm_cpu_init(void) { int ret; @@ -269,4 +292,4 @@ static int __init dtpm_cpu_init(void) return 0; } -DTPM_DECLARE(dtpm_cpu, dtpm_cpu_init, NULL); +DTPM_DECLARE(dtpm_cpu, dtpm_cpu_init, dtpm_cpu_setup); From patchwork Sun Dec 5 23:15:57 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Lezcano X-Patchwork-Id: 520891 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3EA99C433FE for ; Sun, 5 Dec 2021 23:17:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236804AbhLEXU6 (ORCPT ); Sun, 5 Dec 2021 18:20:58 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37384 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241138AbhLEXUB (ORCPT ); Sun, 5 Dec 2021 18:20:01 -0500 Received: from mail-wr1-x42f.google.com (mail-wr1-x42f.google.com [IPv6:2a00:1450:4864:20::42f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 53047C061D60 for ; Sun, 5 Dec 2021 15:16:32 -0800 (PST) Received: by mail-wr1-x42f.google.com with SMTP id t9so18616776wrx.7 for ; Sun, 05 Dec 2021 15:16:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=fWuS4fsoE295izAUB6ZNtsBDKP7xWapSH98WYNQuHlc=; b=mKH01d/1LEslm2VcVdUh0Uf1LmXkfi8RgV20iu7I3e80lrOkFzG6jhWGyyIRdkoVXX IOffNKXZCbrb6P0aazQ5H8Kv5L9suLhKhYIEPDqjYRGI8EBAAv3xXYn3k3RaIsv33hGv 0JP4dQR7GfdJIhCVL5Ix7FSwKeKIn3fxsN1/FW+iZrxAhyj/16RzRwz17htTBD3uzptr NvrIar9wN7i4UVz2jvXJTrdEm04jh7M3oBMMjNKFnh/UWTXLrn0+g4c2nRTw9uHz8Lkt OrsmIDcQr3WRM1Ade58I04m+d5eZFrcdRqFMzs9s07rIxC4WO31t5t8NV9W6jtVyyBYK s8Pg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=fWuS4fsoE295izAUB6ZNtsBDKP7xWapSH98WYNQuHlc=; b=nR7X63QKX9Xc8rYq6fAw18JdQD/aCz/2eiD5XGfMDwfkUrnYY/k77U9aeSSNO5nKj7 FwdJj+jC/dLlcKqgJi2HWALHIPmtZPkB2kzW5v7osy4WTqJ9hpc6TeI5iislcE2a8xqn gOGfFqG51xyJtDoVUmJKKiwJQ+J+CKmkYCD7DTcBAL4AFd191w9lxvRxKat7I2bKyR5w AS3Qc3C7S6KUsDLmCVMpn5BOkk5PGMxUX69/sNF4TVHL47IJDQDCufeEpgdrcVDAKbty IMbN9IC2Dj2jN1GpqXlsbRuh6EA8Q386a9kIHEcnlqK9SGyqCYtO+CvmD+bhfbBueUKJ kkpg== X-Gm-Message-State: AOAM530QHkG/349uFEJSxRpKJyw8Wi9oiMzwDfoCq4whow9ppz+Qo2U6 MlkqBpDPbeIrGqusZcR5J3Ed8Q== X-Google-Smtp-Source: ABdhPJzG8iSh53R4eaNFgzlwXBsReAOb4tRo1rNoBX3qOaJR4toiC2oDHs3yF4TC/PYnKNmKJDrZQA== X-Received: by 2002:adf:d1e2:: with SMTP id g2mr39594535wrd.179.1638746190796; Sun, 05 Dec 2021 15:16:30 -0800 (PST) Received: from localhost.localdomain ([2a01:e34:ed2f:f020:1cec:4235:bb04:b944]) by smtp.gmail.com with ESMTPSA id c10sm10715312wrb.81.2021.12.05.15.16.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 05 Dec 2021 15:16:30 -0800 (PST) From: Daniel Lezcano To: daniel.lezcano@linaro.org, robh@kernel.org Cc: arnd@linaro.org, heiko@sntech.de, ulf.hansson@linaro.org, rjw@rjwysocki.net, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, lukasz.luba@arm.com, Chanwoo Choi , Kyungmin Park , MyungJoo Ham , "Rafael J. Wysocki" , Daniel Lezcano Subject: [PATCH v4 5/5] powercap/drivers/dtpm: Add dtpm devfreq with energy model support Date: Mon, 6 Dec 2021 00:15:57 +0100 Message-Id: <20211205231558.779698-5-daniel.lezcano@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20211205231558.779698-1-daniel.lezcano@linaro.org> References: <20211205231558.779698-1-daniel.lezcano@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org Currently the dtpm supports the CPUs via cpufreq and the energy model. This change provides the same for the device which supports devfreq. Each device supporting devfreq and having an energy model will be added to the hierarchy if the corresponding powerzone is described in the DT. The concept is the same as the cpufreq DTPM support: the QoS is used to aggregate the requests and the energy model gives the value of the instantaneous power consumption ponderated by the load of the device. Cc: Chanwoo Choi Cc: Lukasz Luba Cc: Kyungmin Park Cc: MyungJoo Ham Signed-off-by: Daniel Lezcano --- V2: - Fixed missing prototype warning reported by lkp@ V1: Initial post --- drivers/powercap/Kconfig | 7 ++ drivers/powercap/Makefile | 1 + drivers/powercap/dtpm_devfreq.c | 201 ++++++++++++++++++++++++++++++++ 3 files changed, 209 insertions(+) create mode 100644 drivers/powercap/dtpm_devfreq.c diff --git a/drivers/powercap/Kconfig b/drivers/powercap/Kconfig index b1ca339957e3..515e3ceb3393 100644 --- a/drivers/powercap/Kconfig +++ b/drivers/powercap/Kconfig @@ -57,4 +57,11 @@ config DTPM_CPU help This enables support for CPU power limitation based on energy model. + +config DTPM_DEVFREQ + bool "Add device power capping based on the energy model" + depends on DTPM && ENERGY_MODEL + help + This enables support for device power limitation based on + energy model. endif diff --git a/drivers/powercap/Makefile b/drivers/powercap/Makefile index fabcf388a8d3..494617cdad88 100644 --- a/drivers/powercap/Makefile +++ b/drivers/powercap/Makefile @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only obj-$(CONFIG_DTPM) += dtpm.o obj-$(CONFIG_DTPM_CPU) += dtpm_cpu.o +obj-$(CONFIG_DTPM_DEVFREQ) += dtpm_devfreq.o obj-$(CONFIG_POWERCAP) += powercap_sys.o obj-$(CONFIG_INTEL_RAPL_CORE) += intel_rapl_common.o obj-$(CONFIG_INTEL_RAPL) += intel_rapl_msr.o diff --git a/drivers/powercap/dtpm_devfreq.c b/drivers/powercap/dtpm_devfreq.c new file mode 100644 index 000000000000..a1273eb54e80 --- /dev/null +++ b/drivers/powercap/dtpm_devfreq.c @@ -0,0 +1,201 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright 2021 Linaro Limited + * + * Author: Daniel Lezcano + * + * The devfreq device combined with the energy model and the load can + * give an estimation of the power consumption as well as limiting the + * power. + * + */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include + +struct dtpm_devfreq { + struct dtpm dtpm; + struct dev_pm_qos_request qos_req; + struct devfreq *devfreq; +}; + +static struct dtpm_devfreq *to_dtpm_devfreq(struct dtpm *dtpm) +{ + return container_of(dtpm, struct dtpm_devfreq, dtpm); +} + +static int update_pd_power_uw(struct dtpm *dtpm) +{ + struct dtpm_devfreq *dtpm_devfreq = to_dtpm_devfreq(dtpm); + struct devfreq *devfreq = dtpm_devfreq->devfreq; + struct device *dev = devfreq->dev.parent; + struct em_perf_domain *pd = em_pd_get(dev); + + dtpm->power_min = pd->table[0].power; + dtpm->power_min *= MICROWATT_PER_MILLIWATT; + + dtpm->power_max = pd->table[pd->nr_perf_states - 1].power; + dtpm->power_max *= MICROWATT_PER_MILLIWATT; + + return 0; +} + +static u64 set_pd_power_limit(struct dtpm *dtpm, u64 power_limit) +{ + struct dtpm_devfreq *dtpm_devfreq = to_dtpm_devfreq(dtpm); + struct devfreq *devfreq = dtpm_devfreq->devfreq; + struct device *dev = devfreq->dev.parent; + struct em_perf_domain *pd = em_pd_get(dev); + unsigned long freq; + u64 power; + int i; + + for (i = 0; i < pd->nr_perf_states; i++) { + + power = pd->table[i].power * MICROWATT_PER_MILLIWATT; + if (power > power_limit) + break; + } + + freq = pd->table[i - 1].frequency; + + dev_pm_qos_update_request(&dtpm_devfreq->qos_req, freq); + + power_limit = pd->table[i - 1].power * MICROWATT_PER_MILLIWATT; + + return power_limit; +} + +static void _normalize_load(struct devfreq_dev_status *status) +{ + if (status->total_time > 0xfffff) { + status->total_time >>= 10; + status->busy_time >>= 10; + } + + status->busy_time <<= 10; + status->busy_time /= status->total_time ? : 1; + + status->busy_time = status->busy_time ? : 1; + status->total_time = 1024; +} + +static u64 get_pd_power_uw(struct dtpm *dtpm) +{ + struct dtpm_devfreq *dtpm_devfreq = to_dtpm_devfreq(dtpm); + struct devfreq *devfreq = dtpm_devfreq->devfreq; + struct device *dev = devfreq->dev.parent; + struct em_perf_domain *pd = em_pd_get(dev); + struct devfreq_dev_status status; + unsigned long freq; + u64 power; + int i; + + mutex_lock(&devfreq->lock); + status = devfreq->last_status; + mutex_unlock(&devfreq->lock); + + freq = DIV_ROUND_UP(status.current_frequency, HZ_PER_KHZ); + _normalize_load(&status); + + for (i = 0; i < pd->nr_perf_states; i++) { + + if (pd->table[i].frequency < freq) + continue; + + power = pd->table[i].power * MICROWATT_PER_MILLIWATT; + power *= status.busy_time; + power >>= 10; + + return power; + } + + return 0; +} + +static void pd_release(struct dtpm *dtpm) +{ + struct dtpm_devfreq *dtpm_devfreq = to_dtpm_devfreq(dtpm); + + if (dev_pm_qos_request_active(&dtpm_devfreq->qos_req)) + dev_pm_qos_remove_request(&dtpm_devfreq->qos_req); + + kfree(dtpm_devfreq); +} + +static struct dtpm_ops dtpm_ops = { + .set_power_uw = set_pd_power_limit, + .get_power_uw = get_pd_power_uw, + .update_power_uw = update_pd_power_uw, + .release = pd_release, +}; + +static int __dtpm_devfreq_setup(struct devfreq *devfreq, struct dtpm *parent) +{ + struct device *dev = devfreq->dev.parent; + struct dtpm_devfreq *dtpm_devfreq; + struct em_perf_domain *pd; + int ret = -ENOMEM; + + pd = em_pd_get(dev); + if (!pd) { + ret = dev_pm_opp_of_register_em(dev, NULL); + if (ret) { + pr_err("No energy model available for '%s'\n", dev_name(dev)); + return -EINVAL; + } + } + + dtpm_devfreq = kzalloc(sizeof(*dtpm_devfreq), GFP_KERNEL); + if (!dtpm_devfreq) + return -ENOMEM; + + dtpm_init(&dtpm_devfreq->dtpm, &dtpm_ops); + + dtpm_devfreq->devfreq = devfreq; + + ret = dtpm_register(dev_name(dev), &dtpm_devfreq->dtpm, parent); + if (ret) { + pr_err("Failed to register '%s': %d\n", dev_name(dev), ret); + goto out_dtpm_devfreq; + } + + ret = dev_pm_qos_add_request(dev, &dtpm_devfreq->qos_req, + DEV_PM_QOS_MAX_FREQUENCY, + PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE); + if (ret) { + pr_err("Failed to add QoS request: %d\n", ret); + goto out_dtpm_unregister; + } + + dtpm_update_power(&dtpm_devfreq->dtpm); + + return 0; + +out_dtpm_unregister: + dtpm_unregister(&dtpm_devfreq->dtpm); +out_dtpm_devfreq: + kfree(dtpm_devfreq); + + return ret; +} + +static int __init dtpm_devfreq_setup(struct dtpm *dtpm, struct device_node *np) +{ + struct devfreq *devfreq; + + devfreq = devfreq_get_devfreq_by_node(np); + if (IS_ERR(devfreq)) + return 0; + + return __dtpm_devfreq_setup(devfreq, dtpm); +} + +DTPM_DECLARE(dtpm_dev, NULL, dtpm_devfreq_setup);