summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Lezcano <daniel.lezcano@linaro.org>2021-06-24 09:39:42 +0200
committerDaniel Lezcano <daniel.lezcano@linaro.org>2021-06-29 00:06:39 +0200
commit70e1deb642a939d14dd9b0391d8219cf21a03253 (patch)
treef1ef2b1e21c777c8d29529529d3417528d07b260
parent2182a9a72de2187b74549490945a31bcea923a62 (diff)
downloadlinux-70e1deb642a939d14dd9b0391d8219cf21a03253.tar.gz
arm64: soc: rockchip: Add SoC specific DTPM definitions
The SoC code is in charge of creating the dtpm hierarchy. The rk3399 SoC has an energy model defined and two performance domains. Create a DTPM SoC hierarchy based on these device where we can limit the power and read the power consumption. Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
-rw-r--r--drivers/soc/rockchip/Kconfig8
-rw-r--r--drivers/soc/rockchip/Makefile1
-rw-r--r--drivers/soc/rockchip/dtpm.c97
3 files changed, 106 insertions, 0 deletions
diff --git a/drivers/soc/rockchip/Kconfig b/drivers/soc/rockchip/Kconfig
index 2c13bf4dd5db..fcdecea9169d 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 "Dynamic thermal power management support"
+ depends on DTPM_CPU && DTPM_DEVFREQ && DRM_PANFROST
+ help
+ Say y here to enable the dynamic thermal power management
+ for Rockchip. It will allow to do power capping on the
+ devices which are capable of that.
+
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..3137b523c1ea
--- /dev/null
+++ b/drivers/soc/rockchip/dtpm.c
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright 2021 Linaro Limited
+ *
+ * Author: Daniel Lezcano <daniel.lezcano@linaro.org>
+ *
+ * The powercap based Dynamic Thermal Power Management framework
+ * provides to the userspace a consistent API to set the power limit
+ * on some devices.
+ *
+ * DTPM defines the functions to create a tree of constraints. Each
+ * parent node is a virtual description of the aggregation of the
+ * children. It propagates the constraints set at its level to its
+ * children and collect the children power information. The leaves of
+ * the tree are the real devices which have the ability to get their
+ * current power consumption and set their power limit.
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/dtpm.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+
+/*
+ * Here we want to create the following hierarchy:
+ *
+ * soc
+ * |
+ * |--little (cpu-pd0)
+ * |
+ * `--big (cpu-pd1)
+ *
+ */
+static struct dtpm *soc;
+
+static __init int dtpm_rock_cb(struct device_node *node, const char *name,
+ struct dtpm *parent)
+{
+ struct dtpm *dtpm;
+ int ret;
+
+ dtpm = dtpm_of_find(node, 0);
+ if (!dtpm)
+ return -ENXIO;
+
+ ret = dtpm_register(name, dtpm, parent);
+ if (ret)
+ return ret;
+
+ /* End browsing the cpu list */
+ return 1;
+}
+
+static __init int dtpm_rock_init(void)
+{
+ const char *powerzones[] = {
+ "cpu-pd0", "cpu-pd1",
+ };
+
+ int i, ret;
+
+ ret = dtpm_probe();
+ if (ret)
+ return ret;
+
+ soc = kzalloc(sizeof(*soc), GFP_KERNEL);
+ if (!soc)
+ return -ENOMEM;
+
+ dtpm_init(soc, NULL);
+
+ ret = dtpm_register("soc", soc, NULL);
+ if (ret) {
+ pr_err("Failed to register 'soc': %d\n", ret);
+ return ret;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(powerzones); i++) {
+
+ ret = dtpm_of_for_each(powerzones[i], soc, dtpm_rock_cb);
+ if (ret && ret < 0)
+ pr_err("Failed to create '%s' dtpm entry: %d\n",
+ powerzones[i], ret);
+
+ }
+
+ return 0;
+}
+late_initcall_sync(dtpm_rock_init);
+
+static __exit void dtpm_rock_exit(void)
+{
+ dtpm_unregister(soc);
+}
+module_exit(dtpm_rock_exit);