From: Thomas Marangoni <Thomas.Marangoni@becom-group.com>
To: linux-hwmon@vger.kernel.org
Cc: robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org,
linux@roeck-us.net, corbet@lwn.net, Jonathan.Cameron@huawei.com,
Frank.Li@nxp.com, michal.simek@amd.com,
rodrigo.gobbi.7@gmail.com, chou.cosmo@gmail.com,
wenswang@yeah.net, nuno.sa@analog.com, paweldembicki@gmail.com,
apokusinski01@gmail.com, eajames@linux.ibm.com,
vassilisamir@gmail.com, heiko@sntech.de,
neil.armstrong@linaro.org,
prabhakar.mahadev-lad.rj@bp.renesas.com,
kever.yang@rock-chips.com, mani@kernel.org, dev@kael-k.io,
devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-doc@vger.kernel.org,
Thomas Marangoni <Thomas.Marangoni@becom-group.com>
Subject: [PATCH 1/4] hwmon: Add driver for wsen tids-2521020222501
Date: Mon, 17 Nov 2025 13:38:03 +0100 [thread overview]
Message-ID: <20251117123809.47488-2-Thomas.Marangoni@becom-group.com> (raw)
In-Reply-To: <20251117123809.47488-1-Thomas.Marangoni@becom-group.com>
This commit adds support for the wsen tids-2521020222501. It is a
low cost and small-form-factor i2c temperature sensor.
It supports the following features:
- Continuous temperature reading in four intervals: 5 ms, 10 ms,
20 ms and 40 ms.
- Low temperature alarm
- High temperature alarm
The driver supports following hwmon features:
- hwmon_temp_input
- hwmon_temp_min_alarm
- hwmon_temp_max_alarm
- hwmon_temp_min_hyst
- hwmon_temp_max_hyst
- hwmon_chip_update_interval
Additional notes:
- The update interval only supports four fixed values.
- The alarm is reset on reading.
---
drivers/hwmon/Kconfig | 10 +
drivers/hwmon/Makefile | 1 +
drivers/hwmon/tids.c | 560 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 571 insertions(+)
create mode 100644 drivers/hwmon/tids.c
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 8c852bcac26f..5e578241001f 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -2647,6 +2647,16 @@ config SENSORS_WM8350
This driver can also be built as a module. If so, the module
will be called wm8350-hwmon.
+config SENSORS_TIDS
+ tristate "TIDS"
+ depends on I2C
+ help
+ If you say yes here you get support for the temperature
+ sensor WSEN TIDS from Würth Elektronik.
+
+ This driver can also be built as a module. If so, the module
+ will be called tids.
+
config SENSORS_ULTRA45
tristate "Sun Ultra45 PIC16F747"
depends on SPARC64
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index a8de5bc69f2a..def052b2bdfa 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -244,6 +244,7 @@ obj-$(CONFIG_SENSORS_W83L785TS) += w83l785ts.o
obj-$(CONFIG_SENSORS_W83L786NG) += w83l786ng.o
obj-$(CONFIG_SENSORS_WM831X) += wm831x-hwmon.o
obj-$(CONFIG_SENSORS_WM8350) += wm8350-hwmon.o
+obj-$(CONFIG_SENSORS_TIDS) += tids.o
obj-$(CONFIG_SENSORS_XGENE) += xgene-hwmon.o
obj-$(CONFIG_SENSORS_OCC) += occ/
diff --git a/drivers/hwmon/tids.c b/drivers/hwmon/tids.c
new file mode 100644
index 000000000000..0176a5e8b574
--- /dev/null
+++ b/drivers/hwmon/tids.c
@@ -0,0 +1,560 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/*
+ * Copyright (c) BECOM Electronics GmbH
+ *
+ * wsen_tids_2521020222501.c - Linux hwmon driver for WSEN-TIDS
+ * 2521020222501 Temperature sensor
+ *
+ * Author: Thomas Marangoni <thomas.marangoni@becom-group.com>
+ */
+
+#include <linux/bits.h>
+#include <linux/delay.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+/*
+ * TIDS registers
+ */
+#define TIDS_CMD_DEVICE_ID 0x01
+#define TIDS_CMD_T_H_LIMIT 0x02
+#define TIDS_CMD_T_L_LIMIT 0x03
+#define TIDS_CMD_CTRL 0x04
+#define TIDS_CMD_STATUS 0x05
+#define TIDS_CMD_DATA_T_L 0x06
+#define TIDS_CMD_DATA_T_H 0x07
+#define TIDS_CMD_SOFT_REST 0x0C
+
+/*
+ * TIDS device IDs
+ */
+#define TIDS_ID_2521020222501 0xa0
+
+enum tids_update_interval {
+ tids_update_interval_40ms = 0,
+ tids_update_interval_20ms = 1,
+ tids_update_interval_10ms = 2,
+ tids_update_interval_5ms = 3,
+};
+
+/* TIDS control register */
+static const struct reg_field tids_reg_field_ctrl_one_shot =
+ REG_FIELD(TIDS_CMD_CTRL, 0, 0);
+static const struct reg_field tids_reg_field_ctrl_freerun =
+ REG_FIELD(TIDS_CMD_CTRL, 2, 2);
+static const struct reg_field tids_reg_field_ctrl_if_add_inc =
+ REG_FIELD(TIDS_CMD_CTRL, 3, 3);
+static const struct reg_field tids_reg_field_ctrl_avg =
+ REG_FIELD(TIDS_CMD_CTRL, 4, 5);
+static const struct reg_field tids_reg_field_ctrl_bdu =
+ REG_FIELD(TIDS_CMD_CTRL, 6, 6);
+/* TIDS status register */
+static const struct reg_field tids_reg_field_status_busy =
+ REG_FIELD(TIDS_CMD_STATUS, 0, 0);
+static const struct reg_field tids_reg_field_status_over_thl =
+ REG_FIELD(TIDS_CMD_STATUS, 1, 1);
+static const struct reg_field tids_reg_field_status_under_tll =
+ REG_FIELD(TIDS_CMD_STATUS, 2, 2);
+/* TIDS reset register */
+static const struct reg_field tids_reg_field_soft_reset =
+ REG_FIELD(TIDS_CMD_SOFT_REST, 1, 1);
+
+struct tids_data {
+ struct i2c_client *client;
+
+ struct regmap *regmap;
+
+ /* regmap field for ctrl register */
+ struct regmap_field *reg_ctrl_one_shot;
+ struct regmap_field *reg_ctrl_freerun;
+ struct regmap_field *reg_ctrl_if_add_inc;
+ struct regmap_field *reg_ctrl_avg;
+ struct regmap_field *reg_ctrl_bdu;
+
+ /* regmap field for status register */
+ struct regmap_field *reg_status_busy;
+ struct regmap_field *reg_status_over_thl;
+ struct regmap_field *reg_status_under_tll;
+
+ /* regmap field for soft reset register*/
+ struct regmap_field *reg_soft_reset;
+
+ int irq;
+ int temperature;
+};
+
+static ssize_t tids_interval_read(struct device *dev, long *val)
+{
+ int ret = 0;
+ unsigned int avg_value = 0;
+ struct tids_data *data = dev_get_drvdata(dev);
+
+ ret = regmap_field_read(data->reg_ctrl_avg, &avg_value);
+ if (ret < 0)
+ return ret;
+
+ switch (avg_value) {
+ case tids_update_interval_40ms:
+ *val = 40;
+ break;
+ case tids_update_interval_20ms:
+ *val = 20;
+ break;
+ case tids_update_interval_10ms:
+ *val = 10;
+ break;
+ case tids_update_interval_5ms:
+ *val = 5;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static ssize_t tids_interval_write(struct device *dev, long val)
+{
+ unsigned int avg_value = 0;
+ struct tids_data *data = dev_get_drvdata(dev);
+
+ switch (val) {
+ case 40:
+ avg_value = tids_update_interval_40ms;
+ break;
+ case 20:
+ avg_value = tids_update_interval_20ms;
+ break;
+ case 10:
+ avg_value = tids_update_interval_10ms;
+ break;
+ case 5:
+ avg_value = tids_update_interval_5ms;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return regmap_field_write(data->reg_ctrl_avg, avg_value);
+}
+
+static int tids_temperature1_read(struct device *dev, long *val)
+{
+ int ret;
+ u8 buf[2] = { 0 };
+ struct tids_data *data = dev_get_drvdata(dev);
+
+ ret = regmap_bulk_read(data->regmap, TIDS_CMD_DATA_T_L, buf, 2);
+ if (ret < 0)
+ return ret;
+
+ // temperature in °mC
+ *val = (((s16)(buf[1] << 8) | buf[0])) * 10;
+
+ return 0;
+}
+
+static ssize_t tids_temperature_alarm_read(struct device *dev, u32 attr,
+ long *val)
+{
+ int ret = 0;
+ unsigned int reg_data = 0;
+ struct tids_data *data = dev_get_drvdata(dev);
+
+ if (attr == hwmon_temp_min_alarm)
+ ret = regmap_field_read(data->reg_status_under_tll, ®_data);
+ else if (attr == hwmon_temp_max_alarm)
+ ret = regmap_field_read(data->reg_status_over_thl, ®_data);
+ else
+ return -EOPNOTSUPP;
+
+ if (ret < 0)
+ return ret;
+
+ *val = reg_data;
+
+ return 0;
+}
+
+static int tids_temperature_hyst_read(struct device *dev, u32 attr, long *val)
+{
+ int ret;
+ struct tids_data *data = dev_get_drvdata(dev);
+ unsigned int reg_data = 0;
+
+ if (attr == hwmon_temp_min_hyst)
+ ret = regmap_read(data->regmap, TIDS_CMD_T_L_LIMIT, ®_data);
+ else if (attr == hwmon_temp_max_hyst)
+ ret = regmap_read(data->regmap, TIDS_CMD_T_H_LIMIT, ®_data);
+ else
+ return -EOPNOTSUPP;
+
+ if (ret < 0)
+ return ret;
+
+ // temperature from register conversion in °mC
+ *val = (((u8)reg_data - 63) * 640);
+
+ return 0;
+}
+
+static ssize_t tids_temperature_hyst_write(struct device *dev, u32 attr,
+ long val)
+{
+ u8 reg_data = 0;
+ struct tids_data *data = dev_get_drvdata(dev);
+
+ // temperature in °mC
+ if (val < -39680 || val > 122880)
+ return -EINVAL;
+
+ // temperature to register conversion in °mC
+ reg_data = (u8)((val / 640) + 63);
+
+ if (attr == hwmon_temp_min_hyst)
+ return regmap_write(data->regmap, TIDS_CMD_T_L_LIMIT, reg_data);
+ else if (attr == hwmon_temp_max_hyst)
+ return regmap_write(data->regmap, TIDS_CMD_T_H_LIMIT, reg_data);
+ else
+ return -EOPNOTSUPP;
+}
+
+static umode_t tids_hwmon_visible(const void *data,
+ enum hwmon_sensor_types type, u32 attr,
+ int channel)
+{
+ umode_t mode = 0;
+
+ switch (type) {
+ case hwmon_temp:
+ switch (attr) {
+ case hwmon_temp_input:
+ case hwmon_temp_min_alarm:
+ case hwmon_temp_max_alarm:
+ mode = 0444;
+ break;
+ case hwmon_temp_min_hyst:
+ case hwmon_temp_max_hyst:
+ mode = 0644;
+ break;
+ default:
+ break;
+ }
+ break;
+ case hwmon_chip:
+ switch (attr) {
+ case hwmon_chip_update_interval:
+ mode = 0644;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return mode;
+}
+
+static int tids_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long *val)
+{
+ switch (type) {
+ case hwmon_temp:
+ switch (attr) {
+ case hwmon_temp_input:
+ return tids_temperature1_read(dev, val);
+ case hwmon_temp_min_alarm:
+ case hwmon_temp_max_alarm:
+ return tids_temperature_alarm_read(dev, attr, val);
+ case hwmon_temp_min_hyst:
+ case hwmon_temp_max_hyst:
+ return tids_temperature_hyst_read(dev, attr, val);
+ default:
+ return -EOPNOTSUPP;
+ }
+ case hwmon_chip:
+ switch (attr) {
+ case hwmon_chip_update_interval:
+ return tids_interval_read(dev, val);
+ default:
+ return -EOPNOTSUPP;
+ }
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int tids_hwmon_write(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long val)
+{
+ switch (type) {
+ case hwmon_temp:
+ switch (attr) {
+ case hwmon_temp_min_hyst:
+ case hwmon_temp_max_hyst:
+ return tids_temperature_hyst_write(dev, attr, val);
+ default:
+ return -EOPNOTSUPP;
+ }
+ case hwmon_chip:
+ switch (attr) {
+ case hwmon_chip_update_interval:
+ return tids_interval_write(dev, val);
+ default:
+ return -EOPNOTSUPP;
+ }
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static const struct hwmon_channel_info *const tids_info[] = {
+ HWMON_CHANNEL_INFO(chip, HWMON_C_UPDATE_INTERVAL),
+ HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_MIN_ALARM |
+ HWMON_T_MAX_ALARM | HWMON_T_MIN_HYST |
+ HWMON_T_MAX_HYST),
+ NULL
+};
+
+static const struct hwmon_ops tids_ops = {
+ .is_visible = tids_hwmon_visible,
+ .read = tids_hwmon_read,
+ .write = tids_hwmon_write,
+};
+
+static const struct hwmon_chip_info tids_chip_info = {
+ .ops = &tids_ops,
+ .info = tids_info,
+};
+
+static bool tids_regmap_writeable_reg(struct device *dev, unsigned int reg)
+{
+ if (reg >= 0x02 && reg <= 0x04)
+ return true;
+
+ if (reg == 0x0c)
+ return true;
+
+ return false;
+}
+
+static bool tids_regmap_readable_reg(struct device *dev, unsigned int reg)
+{
+ if (reg >= 0x01 && reg <= 0x07)
+ return true;
+
+ if (reg == 0x0c)
+ return true;
+
+ return false;
+}
+
+static bool tids_regmap_volatile_reg(struct device *dev, unsigned int reg)
+{
+ if (reg >= 0x05 && reg <= 0x07)
+ return true;
+
+ if (reg == 0x0c)
+ return true;
+
+ return false;
+}
+
+static const struct regmap_config regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = TIDS_CMD_SOFT_REST,
+ .writeable_reg = tids_regmap_writeable_reg,
+ .readable_reg = tids_regmap_readable_reg,
+ .volatile_reg = tids_regmap_volatile_reg,
+ .use_single_read = 0,
+};
+
+static int tids_probe_regmap(struct tids_data *data)
+{
+ struct device *dev = &data->client->dev;
+
+ /* Init regmap */
+ data->regmap = devm_regmap_init_i2c(data->client, ®map_config);
+ if (IS_ERR(data->regmap))
+ return dev_err_probe(dev, PTR_ERR(data->regmap),
+ "regmap initialization failed\n");
+
+ /* Allocate regmap_field for ctrl register */
+ data->reg_ctrl_one_shot = devm_regmap_field_alloc(
+ dev, data->regmap, tids_reg_field_ctrl_one_shot);
+ if (IS_ERR(data->reg_ctrl_one_shot))
+ return dev_err_probe(
+ dev, PTR_ERR(data->reg_ctrl_one_shot),
+ "regmap_field reg_ctrl_one_shot initialization failed\n");
+
+ data->reg_ctrl_freerun = devm_regmap_field_alloc(
+ dev, data->regmap, tids_reg_field_ctrl_freerun);
+ if (IS_ERR(data->reg_ctrl_freerun))
+ return dev_err_probe(
+ dev, PTR_ERR(data->reg_ctrl_freerun),
+ "regmap_field reg_ctrl_freerun initialization failed\n");
+
+ data->reg_ctrl_if_add_inc = devm_regmap_field_alloc(
+ dev, data->regmap, tids_reg_field_ctrl_if_add_inc);
+ if (IS_ERR(data->reg_ctrl_if_add_inc))
+ return dev_err_probe(
+ dev, PTR_ERR(data->reg_ctrl_if_add_inc),
+ "regmap_field reg_ctrl_if_add_inc initialization failed\n");
+
+ data->reg_ctrl_avg = devm_regmap_field_alloc(dev, data->regmap,
+ tids_reg_field_ctrl_avg);
+ if (IS_ERR(data->reg_ctrl_avg))
+ return dev_err_probe(
+ dev, PTR_ERR(data->reg_ctrl_avg),
+ "regmap_field reg_ctrl_avg initialization failed\n");
+
+ data->reg_ctrl_bdu = devm_regmap_field_alloc(dev, data->regmap,
+ tids_reg_field_ctrl_bdu);
+ if (IS_ERR(data->reg_ctrl_bdu))
+ return dev_err_probe(
+ dev, PTR_ERR(data->reg_ctrl_bdu),
+ "regmap_field reg_ctrl_bdu initialization failed\n");
+
+ /* Allocate regmap_field for status register */
+ data->reg_status_busy = devm_regmap_field_alloc(
+ dev, data->regmap, tids_reg_field_status_busy);
+ if (IS_ERR(data->reg_status_busy))
+ return dev_err_probe(
+ dev, PTR_ERR(data->reg_status_busy),
+ "regmap_field reg_status_busy initialization failed\n");
+
+ data->reg_status_over_thl = devm_regmap_field_alloc(
+ dev, data->regmap, tids_reg_field_status_over_thl);
+ if (IS_ERR(data->reg_status_over_thl))
+ return dev_err_probe(
+ dev, PTR_ERR(data->reg_status_over_thl),
+ "regmap_field reg_status_over_thl initialization failed\n");
+
+ data->reg_status_under_tll = devm_regmap_field_alloc(
+ dev, data->regmap, tids_reg_field_status_under_tll);
+ if (IS_ERR(data->reg_status_under_tll))
+ return dev_err_probe(
+ dev, PTR_ERR(data->reg_status_under_tll),
+ "regmap_field reg_status_under_tll initialization failed\n");
+
+ /* Allocate regmap_field for software_reset */
+ data->reg_soft_reset = devm_regmap_field_alloc(
+ dev, data->regmap, tids_reg_field_soft_reset);
+ if (IS_ERR(data->reg_soft_reset))
+ return dev_err_probe(
+ dev, PTR_ERR(data->reg_soft_reset),
+ "regmap_field reg_soft_reset initialization failed\n");
+
+ return 0;
+}
+
+static int tids_probe(struct i2c_client *client)
+{
+ struct device *device = &client->dev;
+ struct device *hwmon_dev;
+ struct tids_data *data;
+ unsigned int value;
+ int ret = 0;
+
+ data = devm_kzalloc(device, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->client = client;
+
+ ret = tids_probe_regmap(data);
+ if (ret != 0)
+ return ret;
+
+ /* Read device id, to check if i2c is working */
+ ret = regmap_read(data->regmap, TIDS_CMD_DEVICE_ID, &value);
+ if (ret < 0)
+ return ret;
+
+ /* Triggering soft reset */
+ ret = regmap_field_write(data->reg_soft_reset, 1);
+ if (ret < 0)
+ return ret;
+
+ ret = regmap_field_write(data->reg_soft_reset, 0);
+ if (ret < 0)
+ return ret;
+
+ /* Allowing bulk read */
+ ret = regmap_field_write(data->reg_ctrl_if_add_inc, 1);
+ if (ret < 0)
+ return ret;
+
+ /* Set meassurement interval */
+ ret = regmap_field_write(data->reg_ctrl_avg, tids_update_interval_40ms);
+ if (ret < 0)
+ return ret;
+
+ /* Set device to free run mode */
+ ret = regmap_field_write(data->reg_ctrl_freerun, 1);
+ if (ret < 0)
+ return ret;
+
+ /* Don't update temperature register until high and low value are read */
+ ret = regmap_field_write(data->reg_ctrl_bdu, 1);
+ if (ret < 0)
+ return ret;
+
+ hwmon_dev = devm_hwmon_device_register_with_info(
+ device, device->driver->name, data, &tids_chip_info, NULL);
+
+ return PTR_ERR_OR_ZERO(hwmon_dev);
+}
+
+static int tids_suspend(struct device *dev)
+{
+ struct tids_data *data = dev_get_drvdata(dev);
+
+ return regmap_field_write(data->reg_ctrl_freerun, 0);
+}
+
+static int tids_resume(struct device *dev)
+{
+ struct tids_data *data = dev_get_drvdata(dev);
+
+ return regmap_field_write(data->reg_ctrl_freerun, 1);
+}
+
+static DEFINE_SIMPLE_DEV_PM_OPS(tids_dev_pm_ops, tids_resume, tids_suspend);
+
+static const struct i2c_device_id tids_id[] = {
+ { "tids", 0 },
+ {},
+};
+MODULE_DEVICE_TABLE(i2c, tids_id);
+
+static const struct of_device_id tids_of_match[] = {
+ { .compatible = "wsen,tids-2521020222501" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, tids_of_match);
+
+static struct i2c_driver tids_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "tids",
+ .pm = pm_sleep_ptr(&tids_dev_pm_ops),
+ .of_match_table = tids_of_match,
+ },
+ .probe = tids_probe,
+ .id_table = tids_id,
+};
+
+module_i2c_driver(tids_driver);
+
+MODULE_AUTHOR("Thomas Marangoni <Thomas.Marangoni@becom-group.com>");
+MODULE_DESCRIPTION("WSEN TIDS temperature sensor driver");
+MODULE_LICENSE("GPL");
--
2.51.1
next prev parent reply other threads:[~2025-11-17 12:40 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-11-17 12:38 [PATCH 0/4] hwmon: Add driver for wsen tids-2521020222501 Thomas Marangoni
2025-11-17 12:38 ` Thomas Marangoni [this message]
2025-11-17 16:24 ` [PATCH 1/4] " Guenter Roeck
2025-11-19 10:40 ` Thomas Marangoni
2025-11-17 12:38 ` [PATCH 2/4] hwmon: documentation: add tids Thomas Marangoni
2025-11-17 16:31 ` Guenter Roeck
2025-11-17 12:38 ` [PATCH 3/4] dt-bindings: Add tids in bindings and wsen as vendor Thomas Marangoni
2025-11-17 16:27 ` Guenter Roeck
2025-11-17 16:33 ` Krzysztof Kozlowski
2025-11-17 12:38 ` [PATCH 4/4] MAINTAINERS: Add tids driver as maintained Thomas Marangoni
2025-11-17 16:31 ` Krzysztof Kozlowski
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=20251117123809.47488-2-Thomas.Marangoni@becom-group.com \
--to=thomas.marangoni@becom-group.com \
--cc=Frank.Li@nxp.com \
--cc=Jonathan.Cameron@huawei.com \
--cc=apokusinski01@gmail.com \
--cc=chou.cosmo@gmail.com \
--cc=conor+dt@kernel.org \
--cc=corbet@lwn.net \
--cc=dev@kael-k.io \
--cc=devicetree@vger.kernel.org \
--cc=eajames@linux.ibm.com \
--cc=heiko@sntech.de \
--cc=kever.yang@rock-chips.com \
--cc=krzk+dt@kernel.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-hwmon@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux@roeck-us.net \
--cc=mani@kernel.org \
--cc=michal.simek@amd.com \
--cc=neil.armstrong@linaro.org \
--cc=nuno.sa@analog.com \
--cc=paweldembicki@gmail.com \
--cc=prabhakar.mahadev-lad.rj@bp.renesas.com \
--cc=robh@kernel.org \
--cc=rodrigo.gobbi.7@gmail.com \
--cc=vassilisamir@gmail.com \
--cc=wenswang@yeah.net \
/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.