From patchwork Fri Jan 28 16:35:33 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Lezcano X-Patchwork-Id: 12728743 X-Patchwork-Delegate: daniel.lezcano@linaro.org 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 360BDC433FE for ; Fri, 28 Jan 2022 16:36:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1350135AbiA1QgJ (ORCPT ); Fri, 28 Jan 2022 11:36:09 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44468 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1350067AbiA1QgI (ORCPT ); Fri, 28 Jan 2022 11:36:08 -0500 Received: from mail-wr1-x42b.google.com (mail-wr1-x42b.google.com [IPv6:2a00:1450:4864:20::42b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AEBF6C061714 for ; Fri, 28 Jan 2022 08:36:07 -0800 (PST) Received: by mail-wr1-x42b.google.com with SMTP id a13so11920817wrh.9 for ; Fri, 28 Jan 2022 08:36:07 -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=qh9ZukSBrcmzrIqovMOzTJ9hbhpz7rlhT3FvWLuMjno=; b=iXbzw95Y1DQRW+hjAI8IYGj5KLHaChdb2BKM1Ql3yXLewljYBMWZEMQtbYK0W58h7X qLuRbE750QpId6mVndzHhbzGAxV8GoucgoEuctffCF1sbCc4qCBbIIZqHBNV7dJzIFgd wMnFHdzft2GDCyfO78zvXdK9CM+nZ40BQMc1hAs++jtetAYfYSjQ54ghtomCDKWWQYiO Vfbmvbvjj2kGTN269t5V19mvcKin4WIbnoqw+1b/BPz/GDYfT1IipPMJuEVLsFzrE2Ad gjFRdLapEWNnjoIm+Z81bfetOHDnaMqAankUSYpPN9nJGtx5hPcXAQjKkD9TPvYRQZKt 0n6g== 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=qh9ZukSBrcmzrIqovMOzTJ9hbhpz7rlhT3FvWLuMjno=; b=O8J9k8KHqNTI/joY/ZpXTaQ0SJIkXhwyFmRO6iagbMqVpYFZX5XZZx2xtdpvw3zCKn zU9IJsyOGvEzkYSMU7V6w+GgyCfFeFmCwctc58LcflpO3iAHQp+c8LuGKXHn410j/P8H t0xJQJ9AcOpRrR5o0VEKpSe3FovBYxjpM22y0r9GJAZVCjoO3HAj0yRqvm8cGs5nYckN rUCgetQ5/XyRZtYvp01KpJGjHzoieKjujGwKwsb9zZnQRWjvgN6MDjLkgtKfnOiyil3+ 76a60JuTYrl1TeD09fiw1QNAjs55Qg+gTjNmJ7ayLdKilDtc2bRRchKSkONue7taqs4T jn2A== X-Gm-Message-State: AOAM5310dp6DBS4OcUOWE68MaDQMzwXoasPm0BgDegccI4oj47lfbuE5 SRhUOXusSRlnW78DOOnud6jeKA== X-Google-Smtp-Source: ABdhPJwMZoA7mdRtx2e6Wt/qHVleYsrCePnVZ4AsVaXByy1PPO0iDI0HZlWi4bC7mCGyE4SK2z8WsQ== X-Received: by 2002:a5d:48c5:: with SMTP id p5mr7778841wrs.566.1643387766198; Fri, 28 Jan 2022 08:36:06 -0800 (PST) Received: from localhost.localdomain ([2a01:e34:ed2f:f020:f39:b962:8b8e:9851]) by smtp.gmail.com with ESMTPSA id m6sm5734745wrw.54.2022.01.28.08.36.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 28 Jan 2022 08:36:05 -0800 (PST) From: Daniel Lezcano To: daniel.lezcano@linaro.org, rjw@rjwysocki.net Cc: heiko@sntech.de, robh@kernel.org, lukasz.luba@arm.com, arnd@linaro.org, linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, Ulf Hansson , Daniel Lezcano , "Rafael J. Wysocki" , Arnd Bergmann , linux-arch@vger.kernel.org (open list:GENERIC INCLUDE/ASM HEADER FILES) Subject: [PATCH v8 1/5] powercap/drivers/dtpm: Convert the init table section to a simple array Date: Fri, 28 Jan 2022 17:35:33 +0100 Message-Id: <20220128163537.212248-2-daniel.lezcano@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220128163537.212248-1-daniel.lezcano@linaro.org> References: <20220128163537.212248-1-daniel.lezcano@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org The init table section is freed after the system booted. However the next changes will make per module the DTPM description, so the table won't be accessible when the module is loaded. In order to fix that, we should move the table to the data section where there are very few entries and that makes strange to add it there. The main goal of the table was to keep self-encapsulated code and we can keep it almost as it by using an array instead. Suggested-by: Ulf Hansson Reviewed-by: Ulf Hansson Signed-off-by: Daniel Lezcano --- drivers/powercap/dtpm.c | 2 ++ drivers/powercap/dtpm_cpu.c | 5 ++++- drivers/powercap/dtpm_subsys.h | 18 ++++++++++++++++++ include/asm-generic/vmlinux.lds.h | 11 ----------- include/linux/dtpm.h | 24 +++--------------------- 5 files changed, 27 insertions(+), 33 deletions(-) create mode 100644 drivers/powercap/dtpm_subsys.h diff --git a/drivers/powercap/dtpm.c b/drivers/powercap/dtpm.c index 8cb45f2d3d78..0e5c93443c70 100644 --- a/drivers/powercap/dtpm.c +++ b/drivers/powercap/dtpm.c @@ -24,6 +24,8 @@ #include #include +#include "dtpm_subsys.h" + #define DTPM_POWER_LIMIT_FLAG 0 static const char *constraint_name[] = { diff --git a/drivers/powercap/dtpm_cpu.c b/drivers/powercap/dtpm_cpu.c index b740866b228d..5763e0ce2af5 100644 --- a/drivers/powercap/dtpm_cpu.c +++ b/drivers/powercap/dtpm_cpu.c @@ -269,4 +269,7 @@ static int __init dtpm_cpu_init(void) return 0; } -DTPM_DECLARE(dtpm_cpu, dtpm_cpu_init); +struct dtpm_subsys_ops dtpm_cpu_ops = { + .name = KBUILD_MODNAME, + .init = dtpm_cpu_init, +}; diff --git a/drivers/powercap/dtpm_subsys.h b/drivers/powercap/dtpm_subsys.h new file mode 100644 index 000000000000..2a3a2055f60e --- /dev/null +++ b/drivers/powercap/dtpm_subsys.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2022 Linaro Ltd + * + * Author: Daniel Lezcano + */ +#ifndef ___DTPM_SUBSYS_H__ +#define ___DTPM_SUBSYS_H__ + +extern struct dtpm_subsys_ops dtpm_cpu_ops; + +struct dtpm_subsys_ops *dtpm_subsys[] = { +#ifdef CONFIG_DTPM_CPU + &dtpm_cpu_ops, +#endif +}; + +#endif diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 42f3866bca69..2a10db2f0bc5 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -321,16 +321,6 @@ #define THERMAL_TABLE(name) #endif -#ifdef CONFIG_DTPM -#define DTPM_TABLE() \ - . = ALIGN(8); \ - __dtpm_table = .; \ - KEEP(*(__dtpm_table)) \ - __dtpm_table_end = .; -#else -#define DTPM_TABLE() -#endif - #define KERNEL_DTB() \ STRUCT_ALIGN(); \ __dtb_start = .; \ @@ -723,7 +713,6 @@ ACPI_PROBE_TABLE(irqchip) \ ACPI_PROBE_TABLE(timer) \ THERMAL_TABLE(governor) \ - DTPM_TABLE() \ EARLYCON_TABLE() \ LSM_TABLE() \ EARLY_LSM_TABLE() \ diff --git a/include/linux/dtpm.h b/include/linux/dtpm.h index d37e5d06a357..506048158a50 100644 --- a/include/linux/dtpm.h +++ b/include/linux/dtpm.h @@ -32,29 +32,11 @@ struct dtpm_ops { void (*release)(struct dtpm *); }; -typedef int (*dtpm_init_t)(void); - -struct dtpm_descr { - dtpm_init_t init; +struct dtpm_subsys_ops { + const char *name; + int (*init)(void); }; -/* Init section thermal table */ -extern struct dtpm_descr __dtpm_table[]; -extern struct dtpm_descr __dtpm_table_end[]; - -#define DTPM_TABLE_ENTRY(name, __init) \ - static struct dtpm_descr __dtpm_table_entry_##name \ - __used __section("__dtpm_table") = { \ - .init = __init, \ - } - -#define DTPM_DECLARE(name, init) DTPM_TABLE_ENTRY(name, init) - -#define for_each_dtpm_table(__dtpm) \ - for (__dtpm = __dtpm_table; \ - __dtpm < __dtpm_table_end; \ - __dtpm++) - static inline struct dtpm *to_dtpm(struct powercap_zone *zone) { return container_of(zone, struct dtpm, zone); From patchwork Fri Jan 28 16:35:34 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Lezcano X-Patchwork-Id: 12728744 X-Patchwork-Delegate: daniel.lezcano@linaro.org 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 E671FC433EF for ; Fri, 28 Jan 2022 16:36:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1350163AbiA1QgP (ORCPT ); Fri, 28 Jan 2022 11:36:15 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44492 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1350160AbiA1QgM (ORCPT ); Fri, 28 Jan 2022 11:36:12 -0500 Received: from mail-wm1-x336.google.com (mail-wm1-x336.google.com [IPv6:2a00:1450:4864:20::336]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 525F0C061747 for ; Fri, 28 Jan 2022 08:36:11 -0800 (PST) Received: by mail-wm1-x336.google.com with SMTP id i187-20020a1c3bc4000000b0034d2ed1be2aso8593294wma.1 for ; Fri, 28 Jan 2022 08:36:11 -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=mWsbf9R4m7vHX1+nD6A4itXJcqFKk8EHnq/mwBf0uV8=; b=uPgkGPde5xM3eQ1Nz2vjiUjx6WBVdUeXdeMp2b22vCSdRvwszUd4fp3ojbuZxKxAsi xS02sR2sEvIfsNZ4jkkzAkNwPl07EwGtWKNZ78pw0MqMhQSG3N1+ovhDWmEM8ASurAdi dabg8XryV+J8fmWmqAORe1KkPHfNFppn/WHaG8dpGPt+TFe6b1aJqAntQbFGmJazlXih Wv/JCaWsHfEueIRzfqrP6CmLOxfZM8WV7ps92x8oA4B1oJUhIUdnP+N8r7t5bpB82gXX YpkNtMAd6uImPqg9cwOXHt5M0KIvOtbZYVG2nCunbaFtbUn772g8NkWkmDeNNq+2PVv3 e4YQ== 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=mWsbf9R4m7vHX1+nD6A4itXJcqFKk8EHnq/mwBf0uV8=; b=5npZnWyQIeqPyaDYEpK6ZvpsA/07mHzDRqOsBEatZ4gz8FSmF29N+KeO6M71XhT/c7 ToN3m3EYzC7TxpWgMedI0iDbgaUGFqXbTLZkUioGdWbCKKfRl3u2/7Dj90nXOgc0sxjS yX7blDwHIc/UcUrrraSJFjw+bwBfEdPpL11xAVm8GYDNakU7DhzyFSwQDyvbSBS0nzqx ZXC+5IgIS+0sBQdqLiKg8CCgnSE0YHk3fbPnzk5vYXF1wv8QkQUprCanfzcZnSlCEvfJ Ll3la8d7naUKxD83qKMT09SXG8DD5tcFL7MTLKlqnDz3rAvcNgq93BNPfGDvqNcvoEzq Fegg== X-Gm-Message-State: AOAM532USYTv93QEmJp+V3FPucHAKH6bsbMijReu7srnJTC5lSl36RBz 8cKUhOLe6R5zv1tJT3L/quYVb7vnJQUfWA== X-Google-Smtp-Source: ABdhPJwg5xG2AC8YJbbY5WIk7qBGTRv2ClU2sepL6lMExfayb1RqcGEq3gIF/j2kGBVaD4e/KvHeUA== X-Received: by 2002:a1c:4645:: with SMTP id t66mr16050250wma.39.1643387769744; Fri, 28 Jan 2022 08:36:09 -0800 (PST) Received: from localhost.localdomain ([2a01:e34:ed2f:f020:f39:b962:8b8e:9851]) by smtp.gmail.com with ESMTPSA id m6sm5734745wrw.54.2022.01.28.08.36.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 28 Jan 2022 08:36:07 -0800 (PST) From: Daniel Lezcano To: daniel.lezcano@linaro.org, rjw@rjwysocki.net Cc: heiko@sntech.de, robh@kernel.org, lukasz.luba@arm.com, arnd@linaro.org, linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, Ulf Hansson , "Rafael J. Wysocki" , Daniel Lezcano Subject: [PATCH v8 2/5] powercap/drivers/dtpm: Add hierarchy creation Date: Fri, 28 Jan 2022 17:35:34 +0100 Message-Id: <20220128163537.212248-3-daniel.lezcano@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220128163537.212248-1-daniel.lezcano@linaro.org> References: <20220128163537.212248-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. This change provides a way to create a hierarchy of DTPM node where the power consumption reflects the sum of the children's power consumption. It is up to the platform to specify an array of dtpm nodes where each element has a pointer to its parent, except the top most one. The type of the node gives the indication of which initialization callback to call. At this time, we can create a virtual node, where its purpose is to be a parent in the hierarchy, and a DT node where the name describes its path. In order to ensure a nice self-encapsulation, the DTPM subsys array 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 material to export. Signed-off-by: Daniel Lezcano Reviewed-by: Ulf Hansson --- drivers/powercap/Kconfig | 1 + drivers/powercap/dtpm.c | 190 ++++++++++++++++++++++++++++++++++++++- include/linux/dtpm.h | 15 ++++ 3 files changed, 203 insertions(+), 3 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 0e5c93443c70..414826a1509b 100644 --- a/drivers/powercap/dtpm.c +++ b/drivers/powercap/dtpm.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "dtpm_subsys.h" @@ -463,14 +464,197 @@ int dtpm_register(const char *name, struct dtpm *dtpm, struct dtpm *parent) return 0; } -static int __init init_dtpm(void) +static struct dtpm *dtpm_setup_virtual(const struct dtpm_node *hierarchy, + struct dtpm *parent) { + struct dtpm *dtpm; + int ret; + + dtpm = kzalloc(sizeof(*dtpm), GFP_KERNEL); + if (!dtpm) + return ERR_PTR(-ENOMEM); + dtpm_init(dtpm, NULL); + + ret = dtpm_register(hierarchy->name, dtpm, parent); + if (ret) { + pr_err("Failed to register dtpm node '%s': %d\n", + hierarchy->name, ret); + kfree(dtpm); + return ERR_PTR(ret); + } + + return dtpm; +} + +static struct dtpm *dtpm_setup_dt(const struct dtpm_node *hierarchy, + struct dtpm *parent) +{ + struct device_node *np; + int i, ret; + + np = of_find_node_by_path(hierarchy->name); + if (!np) { + pr_err("Failed to find '%s'\n", hierarchy->name); + return ERR_PTR(-ENXIO); + } + + for (i = 0; i < ARRAY_SIZE(dtpm_subsys); i++) { + + if (!dtpm_subsys[i]->setup) + continue; + + ret = dtpm_subsys[i]->setup(parent, np); + if (ret) { + pr_err("Failed to setup '%s': %d\n", dtpm_subsys[i]->name, ret); + of_node_put(np); + return ERR_PTR(ret); + } + } + + of_node_put(np); + + /* + * By returning a NULL pointer, we let know the caller there + * is no child for us as we are a leaf of the tree + */ + return NULL; +} + +typedef struct dtpm * (*dtpm_node_callback_t)(const struct dtpm_node *, struct dtpm *); + +dtpm_node_callback_t dtpm_node_callback[] = { + [DTPM_NODE_VIRTUAL] = dtpm_setup_virtual, + [DTPM_NODE_DT] = dtpm_setup_dt, +}; + +static int dtpm_for_each_child(const struct dtpm_node *hierarchy, + const struct dtpm_node *it, struct dtpm *parent) +{ + struct dtpm *dtpm; + int i, ret; + + for (i = 0; hierarchy[i].name; i++) { + + if (hierarchy[i].parent != it) + continue; + + dtpm = dtpm_node_callback[hierarchy[i].type](&hierarchy[i], parent); + + /* + * A NULL pointer means there is no children, hence we + * continue without going deeper in the recursivity. + */ + if (!dtpm) + continue; + + /* + * There are multiple reasons why the callback could + * fail. The generic glue is abstracting the backend + * and therefore it is not possible to report back or + * take a decision based on the error. In any case, + * if this call fails, it is not critical in the + * hierarchy creation, we can assume the underlying + * service is not found, so we continue without this + * branch in the tree but with a warning to log the + * information the node was not created. + */ + if (IS_ERR(dtpm)) { + pr_warn("Failed to create '%s' in the hierarchy\n", + hierarchy[i].name); + continue; + } + + ret = dtpm_for_each_child(hierarchy, &hierarchy[i], dtpm); + if (ret) + return ret; + } + + return 0; +} + +/** + * dtpm_create_hierarchy - Create the dtpm hierarchy + * @hierarchy: An array of struct dtpm_node describing the hierarchy + * + * The function is called by the platform specific code with the + * description of the different node in the hierarchy. It creates the + * tree in the sysfs filesystem under the powercap dtpm entry. + * + * The expected tree has the format: + * + * struct dtpm_node hierarchy[] = { + * [0] { .name = "topmost", type = DTPM_NODE_VIRTUAL }, + * [1] { .name = "package", .type = DTPM_NODE_VIRTUAL, .parent = &hierarchy[0] }, + * [2] { .name = "/cpus/cpu0", .type = DTPM_NODE_DT, .parent = &hierarchy[1] }, + * [3] { .name = "/cpus/cpu1", .type = DTPM_NODE_DT, .parent = &hierarchy[1] }, + * [4] { .name = "/cpus/cpu2", .type = DTPM_NODE_DT, .parent = &hierarchy[1] }, + * [5] { .name = "/cpus/cpu3", .type = DTPM_NODE_DT, .parent = &hierarchy[1] }, + * [6] { } + * }; + * + * The last element is always an empty one and marks the end of the + * array. + * + * Return: zero on success, a negative value in case of error. Errors + * are reported back from the underlying functions. + */ +int dtpm_create_hierarchy(struct of_device_id *dtpm_match_table) +{ + const struct of_device_id *match; + const struct dtpm_node *hierarchy; + struct device_node *np; + int i, ret; + + if (pct) + return -EBUSY; + pct = powercap_register_control_type(NULL, "dtpm", NULL); if (IS_ERR(pct)) { pr_err("Failed to register control type\n"); - return PTR_ERR(pct); + ret = PTR_ERR(pct); + goto out_pct; + } + + ret = -ENODEV; + np = of_find_node_by_path("/"); + if (!np) + goto out_err; + + match = of_match_node(dtpm_match_table, np); + + of_node_put(np); + + if (!match) + goto out_err; + + hierarchy = match->data; + if (!hierarchy) { + ret = -EFAULT; + goto out_err; + } + + ret = dtpm_for_each_child(hierarchy, NULL, NULL); + if (ret) + goto out_err; + + for (i = 0; i < ARRAY_SIZE(dtpm_subsys); i++) { + + if (!dtpm_subsys[i]->init) + continue; + + ret = dtpm_subsys[i]->init(); + if (ret) + pr_info("Failed to initialze '%s': %d", + dtpm_subsys[i]->name, ret); } return 0; + +out_err: + powercap_unregister_control_type(pct); +out_pct: + pct = NULL; + + return ret; } -late_initcall(init_dtpm); +EXPORT_SYMBOL_GPL(dtpm_create_hierarchy); diff --git a/include/linux/dtpm.h b/include/linux/dtpm.h index 506048158a50..f7a25c70dd4c 100644 --- a/include/linux/dtpm.h +++ b/include/linux/dtpm.h @@ -32,9 +32,23 @@ struct dtpm_ops { void (*release)(struct dtpm *); }; +struct device_node; + struct dtpm_subsys_ops { const char *name; int (*init)(void); + int (*setup)(struct dtpm *, struct device_node *); +}; + +enum DTPM_NODE_TYPE { + DTPM_NODE_VIRTUAL = 0, + DTPM_NODE_DT, +}; + +struct dtpm_node { + enum DTPM_NODE_TYPE type; + const char *name; + struct dtpm_node *parent; }; static inline struct dtpm *to_dtpm(struct powercap_zone *zone) @@ -52,4 +66,5 @@ void dtpm_unregister(struct dtpm *dtpm); int dtpm_register(const char *name, struct dtpm *dtpm, struct dtpm *parent); +int dtpm_create_hierarchy(struct of_device_id *dtpm_match_table); #endif From patchwork Fri Jan 28 16:35:35 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Lezcano X-Patchwork-Id: 12728746 X-Patchwork-Delegate: daniel.lezcano@linaro.org 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 9754FC433F5 for ; Fri, 28 Jan 2022 16:36:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1350146AbiA1QgU (ORCPT ); Fri, 28 Jan 2022 11:36:20 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44512 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1350184AbiA1QgO (ORCPT ); Fri, 28 Jan 2022 11:36:14 -0500 Received: from mail-wm1-x331.google.com (mail-wm1-x331.google.com [IPv6:2a00:1450:4864:20::331]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 051A5C06174E for ; Fri, 28 Jan 2022 08:36:13 -0800 (PST) Received: by mail-wm1-x331.google.com with SMTP id o30-20020a05600c511e00b0034f4c3186f4so8567595wms.3 for ; Fri, 28 Jan 2022 08:36:12 -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=oPK1edLyJrRFFEyWcyiec8UXIbfSrQa/ueeEQUG7KDE=; b=kGyi6U92aemfBrqx1MsrnIRNqE7tjyN/FjHGf3cWg0qVpija+ScUg7R0y4UcYPKTNp 951ssI+FVMlGXDMnic+lGaP3MkOzqgWaH/OpX51uT5hyuXMrOFYczWKdOpPzOI4NwYa0 a6Vbvd3iak8eWOy0K9bzJ1J+oWZ0QHPidFbtpH+T7qK8s5ELyAbyIzr1rz5m/QXOEdjw +KjCUeGMptQyuguDUmthx/oHvCuGNvTYpX1Hk7h5Z0q5JAZpD0OmeMSbfLMjov/Z9eor 6hkcjuPjk6i4eG9yVNPkWQ3ZeC2sAefj+8q/gpeiZDwuuFvz9jhJOMyaSb3RjDIt78Sb 5NkA== 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=oPK1edLyJrRFFEyWcyiec8UXIbfSrQa/ueeEQUG7KDE=; b=Dka8QGKv42IZhN8Fbz3viGLtszr/pZTb7g6+7wNt/f00BXlaV8IZFnQKCXOzcwFRhW MGrVECvWsIXQIwt6ViyPSzHG5NHAKWS5lez6Mi7MfD9LjZ6oJ4pm18l0reEcFneGWHmR 7rL+JYRfXCaCp7Mwee1NV9wEeUaboCHXBCh9LGSd3enLKk7I3U0ahZe8H8yahfLE1PLP KDcpghXDZ9aojvACeDbOm+61rvYNN6yRM8ZRn8TKRLiQPdNTvRkU/wfw3R/8FIo3wYwN AvH881eYQR3YgTG52eCNFu/lEAhMC5WcBY+vM2VwRDLQB1OWCOCmEC5l42QODIRHEunX Gu+Q== X-Gm-Message-State: AOAM530E6vwOx1qAVUNoj4HP5l9hT1qHOFC/CxSo2qBE33VEjudAOvYm bLsVXgtnlKgWw8mozkr83f999g== X-Google-Smtp-Source: ABdhPJwvHeyXNhi7RFJ2QaYYMJS7UntYm6hj8Gz+56fUrsZ0y8xZzXk0LaGrhKsbyFh5guhz8dFOIw== X-Received: by 2002:a7b:c0d0:: with SMTP id s16mr8205368wmh.169.1643387771424; Fri, 28 Jan 2022 08:36:11 -0800 (PST) Received: from localhost.localdomain ([2a01:e34:ed2f:f020:f39:b962:8b8e:9851]) by smtp.gmail.com with ESMTPSA id m6sm5734745wrw.54.2022.01.28.08.36.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 28 Jan 2022 08:36:10 -0800 (PST) From: Daniel Lezcano To: daniel.lezcano@linaro.org, rjw@rjwysocki.net Cc: heiko@sntech.de, robh@kernel.org, lukasz.luba@arm.com, arnd@linaro.org, linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, Ulf Hansson , Daniel Lezcano , "Rafael J. Wysocki" Subject: [PATCH v8 3/5] powercap/drivers/dtpm: Add CPU DT initialization support Date: Fri, 28 Jan 2022 17:35:35 +0100 Message-Id: <20220128163537.212248-4-daniel.lezcano@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220128163537.212248-1-daniel.lezcano@linaro.org> References: <20220128163537.212248-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 Reviewed-by: Ulf Hansson --- drivers/powercap/dtpm_cpu.c | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/drivers/powercap/dtpm_cpu.c b/drivers/powercap/dtpm_cpu.c index 5763e0ce2af5..eed5ad688d46 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,7 +243,18 @@ static int cpuhp_dtpm_cpu_online(unsigned int cpu) return ret; } -static int __init dtpm_cpu_init(void) +static int 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 dtpm_cpu_init(void) { int ret; @@ -272,4 +295,5 @@ static int __init dtpm_cpu_init(void) struct dtpm_subsys_ops dtpm_cpu_ops = { .name = KBUILD_MODNAME, .init = dtpm_cpu_init, + .setup = dtpm_cpu_setup, }; From patchwork Fri Jan 28 16:35:36 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Lezcano X-Patchwork-Id: 12728745 X-Patchwork-Delegate: daniel.lezcano@linaro.org 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 0B07CC4332F for ; Fri, 28 Jan 2022 16:36:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1350165AbiA1QgS (ORCPT ); Fri, 28 Jan 2022 11:36:18 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44524 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1350136AbiA1QgQ (ORCPT ); Fri, 28 Jan 2022 11:36:16 -0500 Received: from mail-wm1-x32d.google.com (mail-wm1-x32d.google.com [IPv6:2a00:1450:4864:20::32d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5807EC06173B for ; Fri, 28 Jan 2022 08:36:16 -0800 (PST) Received: by mail-wm1-x32d.google.com with SMTP id c2so4837038wml.1 for ; Fri, 28 Jan 2022 08:36:16 -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=+bYImjRjTWNep/cOZZmI5ERgtlrCtBnQFFuQ+RCujyw=; b=BuuXC5yxN4n9+z313nFuaVUDsjZ+K0x17XHumzXLAejfLBsb2uboSeHqFNldZgglb/ +kwzp7bR/kiamsPmS0DZIaqFvapuOO8eNQPrq0slPyji06ZV3hcMMICeoURU6wWn5YG4 SvsS4IwwjrEppYbHU8xY7Iv7ynd1TgZn9rskFwqvBd0rBDH9xNQB0Sv2wLkRQ1utKUZL E56Hrj+hTFRiI7c9yuegTBm5ZGCWGUV8lJNPTm+gbyUyc+WgQh9Aqy7VS6CeRUGMKTbe RrESoUDE0wD1HI49q2xBXUwrPnfWCuj+chl2Y0c7foWkYQ/XFEVdfadaZ3vosS0x9DWa Nugg== 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=+bYImjRjTWNep/cOZZmI5ERgtlrCtBnQFFuQ+RCujyw=; b=Bh0xNKjmly+lgAlOjOusRkYGeNrLUMNsdrXfMHNG1B8ab0L4Ccsl6OdayQc1U+URQm /h8L9Ifv07VaQahxOXQDh558t5NGwAgM3vWLaECpUCFQNesIwiTwKfJ6XYpnfQfaN/8S NG4KaEz6KVGjDEYkoXcsImJlcKN2xj26p7Qml407LZOqGeBxkYdbBkT6NXvWmkguUim0 wFsxrgscCCT7Jqyl2k6n5mxRQolriRBdsPC3zskn4aZWsC/S0kknv08UO7TSYimaPKc9 Qp4ej2hHi4i+DJCjXdKECUA7bDfo/0EOINKij5VzA43/PIbtVZU0G8NaTUjcqxsD9mwG DlkQ== X-Gm-Message-State: AOAM533BVtYZUFC2/O3CnI1GcflWC+8zdsIzvZDoRCxPuTrVmS2TdUyf 3cHwaexOF3ZATnKc7zVBEqrtqQ== X-Google-Smtp-Source: ABdhPJxT1AHWCo1tvuXmMkacT6nIIv/QTAiSIhMM5jhoGOXc8B+7GQkcxelVDpM7lBonUOGEdGzRqw== X-Received: by 2002:a1c:4386:: with SMTP id q128mr7996680wma.9.1643387774791; Fri, 28 Jan 2022 08:36:14 -0800 (PST) Received: from localhost.localdomain ([2a01:e34:ed2f:f020:f39:b962:8b8e:9851]) by smtp.gmail.com with ESMTPSA id m6sm5734745wrw.54.2022.01.28.08.36.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 28 Jan 2022 08:36:14 -0800 (PST) From: Daniel Lezcano To: daniel.lezcano@linaro.org, rjw@rjwysocki.net Cc: heiko@sntech.de, robh@kernel.org, lukasz.luba@arm.com, arnd@linaro.org, linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, Chanwoo Choi , Kyungmin Park , MyungJoo Ham , "Rafael J. Wysocki" , Daniel Lezcano Subject: [PATCH v8 4/5] powercap/drivers/dtpm: Add dtpm devfreq with energy model support Date: Fri, 28 Jan 2022 17:35:36 +0100 Message-Id: <20220128163537.212248-5-daniel.lezcano@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220128163537.212248-1-daniel.lezcano@linaro.org> References: <20220128163537.212248-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 can be added to the hierarchy. 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 --- drivers/powercap/Kconfig | 7 ++ drivers/powercap/Makefile | 1 + drivers/powercap/dtpm_devfreq.c | 203 ++++++++++++++++++++++++++++++++ drivers/powercap/dtpm_subsys.h | 4 + 4 files changed, 215 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..91276761a31d --- /dev/null +++ b/drivers/powercap/dtpm_devfreq.c @@ -0,0 +1,203 @@ +// 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); + kfree(dtpm_devfreq); + return ret; + } + + 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); + + return ret; +} + +static int 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); +} + +struct dtpm_subsys_ops dtpm_devfreq_ops = { + .name = KBUILD_MODNAME, + .setup = dtpm_devfreq_setup, +}; diff --git a/drivers/powercap/dtpm_subsys.h b/drivers/powercap/dtpm_subsys.h index 2a3a2055f60e..db1712938a96 100644 --- a/drivers/powercap/dtpm_subsys.h +++ b/drivers/powercap/dtpm_subsys.h @@ -8,11 +8,15 @@ #define ___DTPM_SUBSYS_H__ extern struct dtpm_subsys_ops dtpm_cpu_ops; +extern struct dtpm_subsys_ops dtpm_devfreq_ops; struct dtpm_subsys_ops *dtpm_subsys[] = { #ifdef CONFIG_DTPM_CPU &dtpm_cpu_ops, #endif +#ifdef CONFIG_DTPM_DEVFREQ + &dtpm_devfreq_ops, +#endif }; #endif From patchwork Fri Jan 28 16:35:37 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Lezcano X-Patchwork-Id: 12728747 X-Patchwork-Delegate: daniel.lezcano@linaro.org 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 4E41AC433F5 for ; Fri, 28 Jan 2022 16:36:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1350196AbiA1Qg2 (ORCPT ); Fri, 28 Jan 2022 11:36:28 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44556 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1350197AbiA1QgW (ORCPT ); Fri, 28 Jan 2022 11:36:22 -0500 Received: from mail-wr1-x42d.google.com (mail-wr1-x42d.google.com [IPv6:2a00:1450:4864:20::42d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6C4A7C061747 for ; Fri, 28 Jan 2022 08:36:22 -0800 (PST) Received: by mail-wr1-x42d.google.com with SMTP id m14so11690501wrg.12 for ; Fri, 28 Jan 2022 08:36: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:in-reply-to:references :mime-version:content-transfer-encoding; bh=99dERtWOZtbIzdgryv5Ia92S7CWD3+jik7G8TWPvHK4=; b=M56W1cYQkxO416lN+jHB1tezGrT0pfoCHG+V30MKezZeGa1pynMj+KMFaFb+TC3xtR QMogfQHJDufhRqxBR6KnAJ+xQF7iDAHcaL6BHjZb6W/t92XCBNdgp5zou1XR178MrL4z s5FbTVaCgtijqYCITJBmcuM2L2B5PwH9jDR/fAJrnrdt0vx//WVR71e2M8M8NCYLjDbW h+w/tXk883nHnYyi9FXF9ylMdrOSRfI7SARFZKXXO11REESQ44wxz971S/YF4HYsH792 W7EZTGUfv9qcua4OiCgY61fRq35io87LL5TW8Ovtjzq3anlJRGCuSS2YRqLemAlcSh1Q I5Kg== 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=99dERtWOZtbIzdgryv5Ia92S7CWD3+jik7G8TWPvHK4=; b=drLDgFU+wfgfac5FCjCu72oF+wqA3IYI2fnKv7lhjEic7X9+fHECv8jQX3+hbcnNzt an4jhDMSeWW13jxaecig/QO3Tn5L9G0Q/Awha56A7jR/GLK8BzvOEK5F2ebfUPwaL0Sf /GrcQVlqPtptFnDKvvF9mdGeJ6BmLL++zjYbEPOSFbZrSwcWo7VDOdpwZH81VV2+frg9 jj/DBAXg/i8YCJvB5bFzIvMBTgJeZ2x1vhyJDXSx+QTJeK8pFOCB9VgATg0HnzjtGkrb KqVBs1uJOz6IpdWfg1PlDKtN6zHVBBL4BUI7FMEcHCnNhZJWZe8DRY+I2rTV5hvKshIr 4TXA== X-Gm-Message-State: AOAM533NXG+kz/aKP5yqk9PTuwMb6IPgNjsFqfv+SfwBnztKez5QfyPd fsrTx0bnT77c61PjbUpf6KWo4Q== X-Google-Smtp-Source: ABdhPJwxf8JZPd4soZH8tiFA70PMwbDqUAwzX9iu+50eMktnT6hbnD1to8hEQRhEd71OIDQlFPrA1g== X-Received: by 2002:adf:f141:: with SMTP id y1mr7683089wro.104.1643387780869; Fri, 28 Jan 2022 08:36:20 -0800 (PST) Received: from localhost.localdomain ([2a01:e34:ed2f:f020:f39:b962:8b8e:9851]) by smtp.gmail.com with ESMTPSA id m6sm5734745wrw.54.2022.01.28.08.36.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 28 Jan 2022 08:36:20 -0800 (PST) From: Daniel Lezcano To: daniel.lezcano@linaro.org, rjw@rjwysocki.net Cc: heiko@sntech.de, robh@kernel.org, lukasz.luba@arm.com, arnd@linaro.org, linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, Geert Uytterhoeven , 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 v8 5/5] rockchip/soc/drivers: Add DTPM description for rk3399 Date: Fri, 28 Jan 2022 17:35:37 +0100 Message-Id: <20220128163537.212248-6-daniel.lezcano@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220128163537.212248-1-daniel.lezcano@linaro.org> References: <20220128163537.212248-1-daniel.lezcano@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org The DTPM framework does support now the hierarchy description. The platform specific code can call the hierarchy creation function with an array of struct dtpm_node pointing to their parent. This patch provides a description of the big / Little CPUs and the GPU and tie them together under a virtual 'package' name. Only rk3399 is described now. The description could be extended in the future with the memory controller with devfreq. The description is always a module and it describes the soft dependencies. The userspace has to load the softdeps module in the right order. Signed-off-by: Daniel Lezcano Reviewed-by; Heiko Stuebner --- Changelog: V8: - Add '/* sentinel */' in the last array entry - Remove Panfrost dependency in the dtpm rockchip module's Kconfig V7: - No changes V6: - Made rk3399 always as a module and added module softdeps V5: - Module creation --- drivers/soc/rockchip/Kconfig | 8 +++++ drivers/soc/rockchip/Makefile | 1 + drivers/soc/rockchip/dtpm.c | 59 +++++++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+) create mode 100644 drivers/soc/rockchip/dtpm.c diff --git a/drivers/soc/rockchip/Kconfig b/drivers/soc/rockchip/Kconfig index 25eb2c1e31bb..156ac0e0c8fe 100644 --- a/drivers/soc/rockchip/Kconfig +++ b/drivers/soc/rockchip/Kconfig @@ -34,4 +34,12 @@ config ROCKCHIP_PM_DOMAINS If unsure, say N. +config ROCKCHIP_DTPM + tristate "Rockchip DTPM hierarchy" + depends on DTPM && m + help + Describe the hierarchy for the Dynamic Thermal Power + Management tree on this platform. That will create all the + power capping capable devices. + endif diff --git a/drivers/soc/rockchip/Makefile b/drivers/soc/rockchip/Makefile index 875032f7344e..05f31a4e743c 100644 --- a/drivers/soc/rockchip/Makefile +++ b/drivers/soc/rockchip/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_ROCKCHIP_GRF) += grf.o obj-$(CONFIG_ROCKCHIP_IODOMAIN) += io-domain.o obj-$(CONFIG_ROCKCHIP_PM_DOMAINS) += pm_domains.o +obj-$(CONFIG_ROCKCHIP_DTPM) += dtpm.o diff --git a/drivers/soc/rockchip/dtpm.c b/drivers/soc/rockchip/dtpm.c new file mode 100644 index 000000000000..ebebb748488b --- /dev/null +++ b/drivers/soc/rockchip/dtpm.c @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright 2021 Linaro Limited + * + * Author: Daniel Lezcano + * + * DTPM hierarchy description + */ +#include +#include +#include +#include + +static struct dtpm_node __initdata rk3399_hierarchy[] = { + [0]{ .name = "rk3399", + .type = DTPM_NODE_VIRTUAL }, + [1]{ .name = "package", + .type = DTPM_NODE_VIRTUAL, + .parent = &rk3399_hierarchy[0] }, + [2]{ .name = "/cpus/cpu@0", + .type = DTPM_NODE_DT, + .parent = &rk3399_hierarchy[1] }, + [3]{ .name = "/cpus/cpu@1", + .type = DTPM_NODE_DT, + .parent = &rk3399_hierarchy[1] }, + [4]{ .name = "/cpus/cpu@2", + .type = DTPM_NODE_DT, + .parent = &rk3399_hierarchy[1] }, + [5]{ .name = "/cpus/cpu@3", + .type = DTPM_NODE_DT, + .parent = &rk3399_hierarchy[1] }, + [6]{ .name = "/cpus/cpu@100", + .type = DTPM_NODE_DT, + .parent = &rk3399_hierarchy[1] }, + [7]{ .name = "/cpus/cpu@101", + .type = DTPM_NODE_DT, + .parent = &rk3399_hierarchy[1] }, + [8]{ .name = "/gpu@ff9a0000", + .type = DTPM_NODE_DT, + .parent = &rk3399_hierarchy[1] }, + [9]{ /* sentinel */ } +}; + +static struct of_device_id __initdata rockchip_dtpm_match_table[] = { + { .compatible = "rockchip,rk3399", .data = rk3399_hierarchy }, + {}, +}; + +static int __init rockchip_dtpm_init(void) +{ + return dtpm_create_hierarchy(rockchip_dtpm_match_table); +} +module_init(rockchip_dtpm_init); + +MODULE_SOFTDEP("pre: panfrost cpufreq-dt"); +MODULE_DESCRIPTION("Rockchip DTPM driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:dtpm"); +MODULE_AUTHOR("Daniel Lezcano