All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alexandre Bailon <abailon@baylibre.com>
To: rui.zhang@intel.com, daniel.lezcano@linaro.org, amitk@kernel.org
Cc: linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org,
	ben.tseng@mediatek.com, khilman@baylibre.com,
	Alexandre Bailon <abailon@baylibre.com>
Subject: [RFC PATCH 2/2] thermal: add a virtual sensor to aggregate temperatures
Date: Thu, 19 Aug 2021 14:32:15 +0200	[thread overview]
Message-ID: <20210819123215.591593-3-abailon@baylibre.com> (raw)
In-Reply-To: <20210819123215.591593-1-abailon@baylibre.com>

This adds a virtual thermal sensor that reads temperature from
hardware sensor and return an aggregated temperature.
Currently, this only return the max temperature.

Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
---
 drivers/thermal/Kconfig              |   8 ++
 drivers/thermal/Makefile             |   1 +
 drivers/thermal/thermal_aggregator.c | 134 +++++++++++++++++++++++++++
 3 files changed, 143 insertions(+)
 create mode 100644 drivers/thermal/thermal_aggregator.c

diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 7a4ba50ba97d0..f9c152cfb95bc 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -228,6 +228,14 @@ config THERMAL_MMIO
 	  register or shared memory, is a potential candidate to work with this
 	  driver.
 
+config THERMAL_AGGREGATOR
+	tristate "Generic thermal aggregator driver"
+	depends on TERMAL_OF || COMPILE_TEST
+	help
+	  This option enables the generic thermal sensor aggregator.
+	  This driver creates a thermal sensor that reads the hardware sensors
+	  and aggregate the temperature.
+
 config HISI_THERMAL
 	tristate "Hisilicon thermal driver"
 	depends on ARCH_HISI || COMPILE_TEST
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 9729a2b089919..5b20ef15aebbe 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -60,3 +60,4 @@ obj-$(CONFIG_UNIPHIER_THERMAL)	+= uniphier_thermal.o
 obj-$(CONFIG_AMLOGIC_THERMAL)     += amlogic_thermal.o
 obj-$(CONFIG_SPRD_THERMAL)	+= sprd_thermal.o
 obj-$(CONFIG_KHADAS_MCU_FAN_THERMAL)	+= khadas_mcu_fan.o
+obj-$(CONFIG_THERMAL_AGGREGATOR) += thermal_aggregator.o
diff --git a/drivers/thermal/thermal_aggregator.c b/drivers/thermal/thermal_aggregator.c
new file mode 100644
index 0000000000000..76f871dbfee9e
--- /dev/null
+++ b/drivers/thermal/thermal_aggregator.c
@@ -0,0 +1,134 @@
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/slab.h>
+#include <linux/thermal.h>
+#include <linux/types.h>
+#include <linux/string.h>
+
+const char *aggr_types[] = {
+	"min",
+	"max",
+	"avg",
+};
+
+struct thermal_aggr;
+
+typedef int (*aggregate_fn)(struct thermal_aggr *aggr);
+
+struct thermal_aggr_sensor {
+	struct thermal_sensor *sensor;
+
+	struct list_head node;
+};
+
+struct thermal_aggr {
+	struct list_head sensors;
+	aggregate_fn *aggregate;
+	//struct thermal_zone_device *tz;
+};
+
+static int thermal_aggr_read_temp(void *data, int *temperature)
+{
+	struct thermal_aggr *aggr = data;
+	struct thermal_aggr_sensor *sensor;
+	int max_temp = 0;
+	int temp;
+
+	list_for_each_entry(sensor, &aggr->sensors, node) {
+		if (!sensor->sensor) {
+			return -ENODEV;
+		}
+
+		sensor->sensor->ops->get_temp(sensor->sensor->sensor_data, &temp);
+		max_temp = max(max_temp, temp);
+	}
+
+	*temperature = max_temp;
+
+	return 0;
+}
+
+static const struct thermal_zone_of_device_ops thermal_aggr_max_ops = {
+	.get_temp = thermal_aggr_read_temp,
+};
+
+static int thermal_aggr_probe(struct platform_device *pdev)
+{
+	struct thermal_aggr *aggr;
+	struct device *dev = &pdev->dev;
+	struct of_phandle_args args;
+	int count;
+	int ret;
+	int i;
+
+	count = of_count_phandle_with_args(dev->of_node,
+					   "thermal-sensors",
+					   "#thermal-sensor-cells");
+	if (count <= 0)
+		return -EINVAL;
+
+	aggr = kzalloc(sizeof(*aggr), GFP_KERNEL);
+	INIT_LIST_HEAD(&aggr->sensors);
+
+	for (i = 0; i < count; i++) {
+		struct thermal_sensor *sensor;
+		struct thermal_aggr_sensor *aggr_sensor;
+		int id;
+
+		ret = of_parse_phandle_with_args(dev->of_node,
+						 "thermal-sensors",
+						 "#thermal-sensor-cells",
+						 i,
+						 &args);
+		if (ret) {
+			return ret;
+		}
+
+		id = args.args_count ? args.args[0] : 0;
+		sensor = thermal_of_get_sensor(args.np, id);
+		if (sensor == NULL) {
+			return -EPROBE_DEFER;
+		}
+
+		aggr_sensor = kzalloc(sizeof(*aggr_sensor), GFP_KERNEL);
+		aggr_sensor->np = args.np;
+		aggr_sensor->id = id;
+		aggr_sensor->sensor = sensor;
+		list_add(&aggr_sensor->node, &aggr->sensors);
+	}
+
+	/*tzdev = */devm_thermal_zone_of_sensor_register(dev, 0, aggr, &thermal_aggr_max_ops);
+
+	return 0;
+}
+
+static int thermal_aggr_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static const struct of_device_id thermal_aggr_of_match[] = {
+	{
+		.compatible = "generic,thermal-aggregator",
+	},
+	{
+	},
+};
+MODULE_DEVICE_TABLE(of, thermal_aggr_of_match);
+
+static struct platform_driver thermal_aggr = {
+	.probe = thermal_aggr_probe,
+	.remove = thermal_aggr_remove,
+	.driver = {
+		.name = "thermal-aggregator",
+		.of_match_table = thermal_aggr_of_match,
+	},
+};
+
+module_platform_driver(thermal_aggr);
+MODULE_AUTHOR("Alexandre Bailon <abailon@baylibre.com>");
+MODULE_DESCRIPTION("Thermal sensor aggregator");
+MODULE_LICENSE("GPL v2");
-- 
2.31.1


  parent reply	other threads:[~2021-08-19 12:31 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-08-19 12:32 [RFC PATCH 0/2] Add a generic virtual thermal sensor Alexandre Bailon
2021-08-19 12:32 ` [RFC PATCH 1/2] thermal: provide a way to get thermal sensor from a device tree node Alexandre Bailon
2021-08-19 12:32 ` Alexandre Bailon [this message]
2021-08-20 12:52   ` [RFC PATCH 2/2] thermal: add a virtual sensor to aggregate temperatures Daniel Lezcano
2021-08-23  7:54     ` Alexandre Bailon
2021-08-20 11:30 ` [RFC PATCH 0/2] Add a generic virtual thermal sensor Daniel Lezcano
2021-08-23  7:35   ` Alexandre Bailon
2021-08-23  8:40     ` Daniel Lezcano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210819123215.591593-3-abailon@baylibre.com \
    --to=abailon@baylibre.com \
    --cc=amitk@kernel.org \
    --cc=ben.tseng@mediatek.com \
    --cc=daniel.lezcano@linaro.org \
    --cc=khilman@baylibre.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pm@vger.kernel.org \
    --cc=rui.zhang@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.