* [PATCH 1/2] dt-bindings: hwmon: ti,ina780a: Add INA780 device
@ 2025-08-06 0:51 Chris Packham
2025-08-06 0:51 ` [PATCH 2/2] hwmon: (ina780) Add driver for TI INA780 Chris Packham
2025-08-06 6:32 ` [PATCH 1/2] dt-bindings: hwmon: ti,ina780a: Add INA780 device Krzysztof Kozlowski
0 siblings, 2 replies; 9+ messages in thread
From: Chris Packham @ 2025-08-06 0:51 UTC (permalink / raw)
To: jdelvare, linux, robh, krzk+dt, conor+dt
Cc: linux-hwmon, devicetree, linux-kernel, Chris Packham
Add dtschema for TI INA780 Digital Power Monitor
Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz>
---
.../devicetree/bindings/hwmon/ti,ina780a.yaml | 47 +++++++++++++++++++
1 file changed, 47 insertions(+)
create mode 100644 Documentation/devicetree/bindings/hwmon/ti,ina780a.yaml
diff --git a/Documentation/devicetree/bindings/hwmon/ti,ina780a.yaml b/Documentation/devicetree/bindings/hwmon/ti,ina780a.yaml
new file mode 100644
index 000000000000..fa19d621b27b
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/ti,ina780a.yaml
@@ -0,0 +1,47 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/hwmon/ti,ina780a.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Texas Instruments INA780 Digital Power Monitor
+
+maintainers:
+ - Chris Packham <chris.packham@alliedtelesis.co.nz>
+
+description: |
+ The INA780x is a digital power monitor with an integrated current sensing
+ element.
+
+ Datasheets:
+ https://www.ti.com/lit/gpn/ina780a
+
+properties:
+ compatible:
+ enum:
+ - ti,ina780a
+ - ti,ina780b
+
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+
+allOf:
+ - $ref: hwmon-common.yaml#
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ hwmon@40 {
+ compatible = "ti,ina780a";
+ reg = <0x40>;
+ };
+ };
--
2.50.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 2/2] hwmon: (ina780) Add driver for TI INA780
2025-08-06 0:51 [PATCH 1/2] dt-bindings: hwmon: ti,ina780a: Add INA780 device Chris Packham
@ 2025-08-06 0:51 ` Chris Packham
2025-08-06 3:14 ` Guenter Roeck
2025-08-06 19:21 ` kernel test robot
2025-08-06 6:32 ` [PATCH 1/2] dt-bindings: hwmon: ti,ina780a: Add INA780 device Krzysztof Kozlowski
1 sibling, 2 replies; 9+ messages in thread
From: Chris Packham @ 2025-08-06 0:51 UTC (permalink / raw)
To: jdelvare, linux, robh, krzk+dt, conor+dt
Cc: linux-hwmon, devicetree, linux-kernel, Chris Packham
Add support for the TI INA780 Digital Power Monitor.
Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz>
---
drivers/hwmon/Kconfig | 11 +
drivers/hwmon/Makefile | 1 +
drivers/hwmon/ina780.c | 566 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 578 insertions(+)
create mode 100644 drivers/hwmon/ina780.c
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 079620dd4286..d11aebb6a1c1 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -2264,6 +2264,17 @@ config SENSORS_INA3221
This driver can also be built as a module. If so, the module
will be called ina3221.
+config SENSORS_INA780
+ tristate "Texas Instruments INA780 Power Monitor"
+ depends on I2C
+ select REGMAP_I2C
+ help
+ If you say yes here you get support for the TI INA780 Digital
+ Power Monitor.
+
+ This driver can also be built as a module. If so, the module
+ will be called ina780.
+
config SENSORS_SPD5118
tristate "SPD5118 Compliant Temperature Sensors"
depends on I2C
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 48e5866c0c9a..e4acef261f14 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -104,6 +104,7 @@ obj-$(CONFIG_SENSORS_INA209) += ina209.o
obj-$(CONFIG_SENSORS_INA2XX) += ina2xx.o
obj-$(CONFIG_SENSORS_INA238) += ina238.o
obj-$(CONFIG_SENSORS_INA3221) += ina3221.o
+obj-$(CONFIG_SENSORS_INA780) += ina780.o
obj-$(CONFIG_SENSORS_INTEL_M10_BMC_HWMON) += intel-m10-bmc-hwmon.o
obj-$(CONFIG_SENSORS_ISL28022) += isl28022.o
obj-$(CONFIG_SENSORS_IT87) += it87.o
diff --git a/drivers/hwmon/ina780.c b/drivers/hwmon/ina780.c
new file mode 100644
index 000000000000..b6a31fca400a
--- /dev/null
+++ b/drivers/hwmon/ina780.c
@@ -0,0 +1,566 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Driver for the Texas Instruments INA780 Digital Power Monitor
+ *
+ * Datasheet:
+ * https://www.ti.com/lit/gpn/ina780a
+ */
+
+#include <linux/bits.h>
+#include <linux/cleanup.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/hwmon.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/math64.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+
+#define INA780_CONFIG 0x0
+#define INA780_ADC_CONFIG 0x1
+#define INA780_VBUS 0x5
+#define INA780_DIETEMP 0x6
+#define INA780_CURRENT 0x7
+#define INA780_POWER 0x8
+#define INA780_ENERGY 0x9
+#define INA780_CHARGE 0xa
+#define INA780_DIAG_ALRT 0xb
+#define INA780_COL 0xc
+#define INA780_CUL 0xd
+#define INA780_BOVL 0xe
+#define INA780_BUVL 0xf
+#define INA780_TEMP_LIMIT 0x10
+#define INA780_PWR_LIMIT 0x11
+#define INA780_MANUFACTURER_ID 0x3e
+
+#define INA780_DIAG_ALRT_TMPOL BIT(7)
+#define INA780_DIAG_ALRT_CURRENTOL BIT(6)
+#define INA780_DIAG_ALRT_CURRENTUL BIT(5)
+#define INA780_DIAG_ALRT_BUSOL BIT(4)
+#define INA780_DIAG_ALRT_BUSUL BIT(3)
+#define INA780_DIAG_ALRT_POL BIT(2)
+
+#define INA780_BUS_VOLTAGE_LSB 3125 /* 3.125 mV/lsb */
+#define INA780_CURRENT_LSB 2400 /* 2.4 mA/lsb */
+#define INA780_TEMP_LSB 125000 /* 125 mC/lsb */
+#define INA780_ENERGY_LSB 7680 /* 7.68 mJ/lsb */
+#define INA780_POWER_LSB 480000 /* 480 uW/lsb */
+#define INA780_PWR_LIMIT_LSB (256 * INA780_POWER_LSB) /* 122.88 mW/lsb */
+
+#define INA780_ID 0x5449
+
+static const struct regmap_config ina780_regmap_config = {
+ .max_register = INA780_MANUFACTURER_ID,
+ .reg_bits = 8,
+ .val_bits = 16,
+};
+
+struct ina780_data {
+ struct mutex lock;
+ struct i2c_client *client;
+ struct regmap *regmap;
+};
+
+static int ina780_read_reg24(const struct i2c_client *client, u8 reg, u32 *val)
+{
+ u8 data[3];
+ int err;
+
+ err = i2c_smbus_read_i2c_block_data(client, reg, 3, data);
+ if (err < 0)
+ return err;
+ if (err != 3)
+ return -EIO;
+ *val = (data[0] << 16) | (data[1] << 8) | data[2];
+
+ return 0;
+}
+
+static int ina780_read_reg40(struct i2c_client *client, int reg, u64 *val)
+{
+ u8 data[5];
+ u32 low;
+ int err;
+
+ err = i2c_smbus_read_i2c_block_data(client, reg, 5, data);
+ if (err < 0)
+ return err;
+ if (err != 5)
+ return -EIO;
+
+ low = (data[1] << 24) | (data[2] << 16) | (data[3] << 8) | data[4];
+ *val = ((long long)data[0] << 32) | low;
+
+ return 0;
+}
+
+static int ina780_read_in(struct device *dev, u32 attr, long *val)
+{
+ struct ina780_data *data = dev_get_drvdata(dev);
+ unsigned int regval;
+ int reg, mask;
+ int err;
+
+ switch (attr) {
+ case hwmon_in_input:
+ reg = INA780_VBUS;
+ break;
+ case hwmon_in_max:
+ reg = INA780_BOVL;
+ break;
+ case hwmon_in_min:
+ reg = INA780_BUVL;
+ break;
+ case hwmon_in_max_alarm:
+ reg = INA780_DIAG_ALRT;
+ mask = INA780_DIAG_ALRT_BUSOL;
+ break;
+ case hwmon_in_min_alarm:
+ reg = INA780_DIAG_ALRT;
+ mask = INA780_DIAG_ALRT_BUSUL;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ switch (attr) {
+ case hwmon_in_input:
+ case hwmon_in_max:
+ case hwmon_in_min:
+ err = regmap_read(data->regmap, reg, ®val);
+ if (err)
+ return err;
+
+ *val = (regval * INA780_BUS_VOLTAGE_LSB) / 1000;
+ break;
+ case hwmon_in_max_alarm:
+ case hwmon_in_min_alarm:
+ err = regmap_read(data->regmap, reg, ®val);
+ if (err)
+ return err;
+ *val = !!(regval & mask);
+ break;
+ }
+
+ return 0;
+}
+
+static int ina780_write_in(struct device *dev, u32 attr, long val)
+{
+ struct ina780_data *data = dev_get_drvdata(dev);
+ unsigned int regval;
+ int reg;
+
+ switch (attr) {
+ case hwmon_in_max:
+ reg = INA780_BOVL;
+ break;
+ case hwmon_in_min:
+ reg = INA780_BUVL;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ val = clamp_val(val, 0, 102396);
+ regval = div_u64(val * 1000ULL, INA780_BUS_VOLTAGE_LSB);
+
+ return regmap_write(data->regmap, reg, regval);
+}
+
+static int ina780_read_curr(struct device *dev, u32 attr, long *val)
+{
+ struct ina780_data *data = dev_get_drvdata(dev);
+ unsigned int regval;
+ int reg, mask;
+ int err;
+
+ switch (attr) {
+ case hwmon_curr_input:
+ reg = INA780_CURRENT;
+ break;
+ case hwmon_curr_max:
+ reg = INA780_COL;
+ break;
+ case hwmon_curr_min:
+ reg = INA780_CUL;
+ break;
+ case hwmon_curr_max_alarm:
+ reg = INA780_DIAG_ALRT;
+ mask = INA780_DIAG_ALRT_CURRENTOL;
+ break;
+ case hwmon_curr_min_alarm:
+ reg = INA780_DIAG_ALRT;
+ mask = INA780_DIAG_ALRT_CURRENTUL;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ switch (attr) {
+ case hwmon_curr_input:
+ case hwmon_curr_max:
+ case hwmon_curr_min:
+ err = regmap_read(data->regmap, reg, ®val);
+ if (err)
+ return err;
+ *val = div_s64((s16)regval * INA780_CURRENT_LSB, 1000);
+ break;
+ case hwmon_curr_max_alarm:
+ case hwmon_curr_min_alarm:
+ err = regmap_read(data->regmap, reg, ®val);
+ if (err)
+ return err;
+ *val = !!(regval & mask);
+ break;
+ }
+
+ return 0;
+}
+
+static int ina780_write_curr(struct device *dev, u32 attr, long val)
+{
+ struct ina780_data *data = dev_get_drvdata(dev);
+ unsigned int regval;
+ int reg;
+
+ switch (attr) {
+ case hwmon_curr_max:
+ reg = INA780_COL;
+ break;
+ case hwmon_curr_min:
+ reg = INA780_CUL;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+ clamp_val(val, -78643, 78640);
+ regval = div_s64(val * 1000ULL, INA780_CURRENT_LSB);
+
+ return regmap_write(data->regmap, reg, regval);
+}
+
+static int ina780_read_power(struct device *dev, u32 attr, long *val)
+{
+ struct ina780_data *data = dev_get_drvdata(dev);
+ unsigned int regval;
+ int err;
+
+ switch (attr) {
+ case hwmon_power_input:
+ err = ina780_read_reg24(data->client, INA780_POWER, ®val);
+ if (err)
+ return err;
+ *val = div_u64((u64)regval * INA780_POWER_LSB, 1000);
+ break;
+ case hwmon_power_max:
+ err = regmap_read(data->regmap, INA780_PWR_LIMIT, ®val);
+ if (err)
+ return err;
+ *val = div_u64((u64)regval * INA780_PWR_LIMIT_LSB, 1000);
+ break;
+ case hwmon_power_max_alarm:
+ err = regmap_read(data->regmap, INA780_DIAG_ALRT, ®val);
+ if (err)
+ return err;
+ *val = !!(regval & INA780_DIAG_ALRT_POL);
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+static int ina780_write_power(struct device *dev, u32 attr, long val)
+{
+ struct ina780_data *data = dev_get_drvdata(dev);
+ int regval;
+
+ switch (attr) {
+ case hwmon_power_max:
+ val = clamp_val(val, 0, 8052940800);
+ regval = div_u64(val * 1000ULL, INA780_PWR_LIMIT_LSB);
+ return regmap_write(data->regmap, INA780_PWR_LIMIT, regval);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int ina780_read_temp(struct device *dev, u32 attr, long *val)
+{
+ struct ina780_data *data = dev_get_drvdata(dev);
+ int reg, mask;
+ int regval;
+ int err;
+
+ switch (attr) {
+ case hwmon_temp_input:
+ reg = INA780_DIETEMP;
+ break;
+ case hwmon_temp_max:
+ reg = INA780_TEMP_LIMIT;
+ break;
+ case hwmon_temp_max_alarm:
+ reg = INA780_DIAG_ALRT;
+ mask = INA780_DIAG_ALRT_TMPOL;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ switch (attr) {
+ case hwmon_temp_input:
+ case hwmon_temp_max:
+ err = regmap_read(data->regmap, reg, ®val);
+ if (err)
+ return err;
+ *val = div_s64(((s64)((s16)regval) >> 4) * INA780_TEMP_LSB, 1000);
+ break;
+ case hwmon_temp_max_alarm:
+ err = regmap_read(data->regmap, INA780_DIAG_ALRT, ®val);
+ *val = !!(regval & INA780_DIAG_ALRT_TMPOL);
+ break;
+ }
+
+ return 0;
+}
+
+static int ina780_write_temp(struct device *dev, u32 attr, long val)
+{
+ struct ina780_data *data = dev_get_drvdata(dev);
+ int regval;
+
+ if (attr != hwmon_temp_max)
+ return -EOPNOTSUPP;
+
+ val = clamp_val(val, -40000, 150000);
+ regval = div_s64(val * 1000, INA780_TEMP_LSB) << 4;
+
+ return regmap_write(data->regmap, INA780_TEMP_LIMIT, regval);
+}
+
+static int ina780_read_energy(struct device *dev, u32 attr, long *val)
+{
+ struct ina780_data *data = dev_get_drvdata(dev);
+ u64 regval;
+ int err;
+
+ if (attr != hwmon_energy_input)
+ return -EOPNOTSUPP;
+
+ err = ina780_read_reg40(data->client, INA780_ENERGY, ®val);
+ if (err)
+ return err;
+
+ *val = div_u64(regval * INA780_ENERGY_LSB, 1000);
+
+ return 0;
+}
+
+static int ina780_read(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long *val)
+{
+ struct ina780_data *data = dev_get_drvdata(dev);
+
+ guard(mutex)(&data->lock);
+
+ switch (type) {
+ case hwmon_in:
+ return ina780_read_in(dev, attr, val);
+ case hwmon_curr:
+ return ina780_read_curr(dev, attr, val);
+ case hwmon_power:
+ return ina780_read_power(dev, attr, val);
+ case hwmon_temp:
+ return ina780_read_temp(dev, attr, val);
+ case hwmon_energy:
+ return ina780_read_energy(dev, attr, val);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int ina780_write(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long val)
+{
+ struct ina780_data *data = dev_get_drvdata(dev);
+
+ guard(mutex)(&data->lock);
+
+ switch (type) {
+ case hwmon_in:
+ return ina780_write_in(dev, attr, val);
+ case hwmon_curr:
+ return ina780_write_curr(dev, attr, val);
+ case hwmon_power:
+ return ina780_write_power(dev, attr, val);
+ case hwmon_temp:
+ return ina780_write_temp(dev, attr, val);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static umode_t ina780_is_visible(const void *drvdata,
+ enum hwmon_sensor_types type,
+ u32 attr, int channel)
+{
+ switch (type) {
+ case hwmon_in:
+ switch (attr) {
+ case hwmon_in_input:
+ case hwmon_in_max_alarm:
+ case hwmon_in_min_alarm:
+ return 0444;
+ case hwmon_in_max:
+ case hwmon_in_min:
+ return 0644;
+ default:
+ return 0;
+ }
+ case hwmon_curr:
+ switch (attr) {
+ case hwmon_curr_input:
+ case hwmon_curr_max_alarm:
+ case hwmon_curr_min_alarm:
+ return 0444;
+ case hwmon_curr_max:
+ case hwmon_curr_min:
+ return 0644;
+ default:
+ return 0;
+ }
+ case hwmon_power:
+ switch (attr) {
+ case hwmon_power_input:
+ case hwmon_power_max_alarm:
+ return 0444;
+ case hwmon_power_max:
+ return 0644;
+ default:
+ return 0;
+ }
+ case hwmon_temp:
+ switch (attr) {
+ case hwmon_temp_input:
+ case hwmon_temp_max_alarm:
+ return 0444;
+ case hwmon_temp_max:
+ return 0644;
+ default:
+ return 0;
+ }
+ case hwmon_energy:
+ switch (attr) {
+ case hwmon_energy_input:
+ return 0444;
+ default:
+ return 0;
+ }
+ default:
+ return 0;
+ }
+}
+
+static const struct hwmon_channel_info * const ina238_info[] = {
+ HWMON_CHANNEL_INFO(in,
+ HWMON_I_INPUT |
+ HWMON_I_MAX | HWMON_I_MAX_ALARM |
+ HWMON_I_MIN | HWMON_I_MIN_ALARM),
+ HWMON_CHANNEL_INFO(curr,
+ HWMON_C_INPUT |
+ HWMON_C_MAX | HWMON_C_MAX_ALARM |
+ HWMON_C_MIN | HWMON_C_MIN_ALARM),
+ HWMON_CHANNEL_INFO(power,
+ HWMON_P_INPUT | HWMON_P_MAX | HWMON_P_MAX_ALARM),
+ HWMON_CHANNEL_INFO(temp,
+ HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MAX_ALARM),
+ HWMON_CHANNEL_INFO(energy,
+ HWMON_E_INPUT),
+ NULL
+};
+
+static const struct hwmon_ops ina780_hwmon_ops = {
+ .is_visible = ina780_is_visible,
+ .read = ina780_read,
+ .write = ina780_write,
+};
+
+static const struct hwmon_chip_info ina780_chip_info = {
+ .ops = &ina780_hwmon_ops,
+ .info = ina238_info,
+};
+
+static int ina780_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct ina780_data *data;
+ struct device *hwmon_dev;
+ unsigned int val;
+ int err;
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->client = client;
+ data->regmap = devm_regmap_init_i2c(client, &ina780_regmap_config);
+ if (IS_ERR(data->regmap)) {
+ dev_err(dev, "Failed to allocate register map\n");
+ return PTR_ERR(data->regmap);
+ }
+
+ err = regmap_read(data->regmap, INA780_MANUFACTURER_ID, &val);
+ if (err) {
+ dev_err(dev, "Error reading device ID\n");
+ return err;
+ }
+
+ if (val != INA780_ID)
+ dev_warn(dev, "Unexpected device ID %04x\n", val);
+
+ mutex_init(&data->lock);
+
+ hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, data,
+ &ina780_chip_info,
+ NULL);
+ if (IS_ERR(hwmon_dev))
+ return PTR_ERR(hwmon_dev);
+
+ /* Temp limit register can go to 255 C but actual max is 150 C*/
+ err = ina780_write_temp(hwmon_dev, hwmon_temp_max, 150000);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+static const struct i2c_device_id ina780_id[] = {
+ { "ina780a" },
+ { "ina780b" },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, ina780_id);
+
+static const struct of_device_id ina780_of_match[] = {
+ { .compatible = "ti,ina780a" },
+ { .compatible = "ti,ina780b" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ina780_of_match);
+
+static struct i2c_driver ina780_driver = {
+ .driver = {
+ .name = "ina780",
+ .of_match_table = ina780_of_match,
+ },
+ .probe = ina780_probe,
+ .id_table = ina780_id,
+};
+
+module_i2c_driver(ina780_driver);
+
+MODULE_AUTHOR("Chris Packham <chris.packham@alliedtelesis.co.nz>");
+MODULE_DESCRIPTION("INA780 driver");
+MODULE_LICENSE("GPL");
--
2.50.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] hwmon: (ina780) Add driver for TI INA780
2025-08-06 0:51 ` [PATCH 2/2] hwmon: (ina780) Add driver for TI INA780 Chris Packham
@ 2025-08-06 3:14 ` Guenter Roeck
2025-08-06 3:41 ` Chris Packham
2025-08-06 19:21 ` kernel test robot
1 sibling, 1 reply; 9+ messages in thread
From: Guenter Roeck @ 2025-08-06 3:14 UTC (permalink / raw)
To: Chris Packham, jdelvare, robh, krzk+dt, conor+dt
Cc: linux-hwmon, devicetree, linux-kernel
On 8/5/25 17:51, Chris Packham wrote:
> Add support for the TI INA780 Digital Power Monitor.
>
> Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz>
Looking at the registers, the chip seems to be almost identical to INA237/238.
Why a new driver ?
Guenter
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] hwmon: (ina780) Add driver for TI INA780
2025-08-06 3:14 ` Guenter Roeck
@ 2025-08-06 3:41 ` Chris Packham
2025-08-06 20:22 ` Guenter Roeck
0 siblings, 1 reply; 9+ messages in thread
From: Chris Packham @ 2025-08-06 3:41 UTC (permalink / raw)
To: Guenter Roeck, jdelvare@suse.com, robh@kernel.org,
krzk+dt@kernel.org, conor+dt@kernel.org
Cc: linux-hwmon@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org
Hi Guenter,
On 06/08/2025 15:14, Guenter Roeck wrote:
> On 8/5/25 17:51, Chris Packham wrote:
>> Add support for the TI INA780 Digital Power Monitor.
>>
>> Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz>
>
> Looking at the registers, the chip seems to be almost identical to
> INA237/238.
> Why a new driver ?
Yes I'd noticed the same thing as I went along. The INA780 has the
ezshunt thing (not sure if that's the same as the internal shunt on the
INA260) which means that a lot of the places where things are calculated
by the shunt resistor value aren't applicable and there's one less
voltage sensor. I did consider adding it to the ina2xx.c but it seemed
different enough to those chips to warrant a separate driver.
I think I can kind of squint and see how I might fold the ina780 support
into the ina238 driver although that may make things a bit messier. If
that's the direction you'd like to head I can give it a go.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] dt-bindings: hwmon: ti,ina780a: Add INA780 device
2025-08-06 0:51 [PATCH 1/2] dt-bindings: hwmon: ti,ina780a: Add INA780 device Chris Packham
2025-08-06 0:51 ` [PATCH 2/2] hwmon: (ina780) Add driver for TI INA780 Chris Packham
@ 2025-08-06 6:32 ` Krzysztof Kozlowski
2025-08-07 20:46 ` Chris Packham
1 sibling, 1 reply; 9+ messages in thread
From: Krzysztof Kozlowski @ 2025-08-06 6:32 UTC (permalink / raw)
To: Chris Packham, jdelvare, linux, robh, krzk+dt, conor+dt
Cc: linux-hwmon, devicetree, linux-kernel
On 06/08/2025 02:51, Chris Packham wrote:
> +
> +properties:
> + compatible:
> + enum:
> + - ti,ina780a
> + - ti,ina780b
> +
> + reg:
> + maxItems: 1
This looks a bit incomplete. Where is a supply? No shunt resistor
choice? No other properties from ina2xx apply?
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] hwmon: (ina780) Add driver for TI INA780
2025-08-06 0:51 ` [PATCH 2/2] hwmon: (ina780) Add driver for TI INA780 Chris Packham
2025-08-06 3:14 ` Guenter Roeck
@ 2025-08-06 19:21 ` kernel test robot
1 sibling, 0 replies; 9+ messages in thread
From: kernel test robot @ 2025-08-06 19:21 UTC (permalink / raw)
To: Chris Packham, jdelvare, linux, robh, krzk+dt, conor+dt
Cc: oe-kbuild-all, linux-hwmon, devicetree, linux-kernel,
Chris Packham
Hi Chris,
kernel test robot noticed the following build warnings:
[auto build test WARNING on groeck-staging/hwmon-next]
[also build test WARNING on linus/master v6.16 next-20250806]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Chris-Packham/hwmon-ina780-Add-driver-for-TI-INA780/20250806-115131
base: https://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git hwmon-next
patch link: https://lore.kernel.org/r/20250806005127.542298-2-chris.packham%40alliedtelesis.co.nz
patch subject: [PATCH 2/2] hwmon: (ina780) Add driver for TI INA780
config: x86_64-randconfig-072-20250807 (https://download.01.org/0day-ci/archive/20250807/202508070319.QMV6021c-lkp@intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14+deb12u1) 12.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250807/202508070319.QMV6021c-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202508070319.QMV6021c-lkp@intel.com/
All warnings (new ones prefixed by >>):
drivers/hwmon/ina780.c: In function 'ina780_read_temp':
>> drivers/hwmon/ina780.c:293:18: warning: variable 'mask' set but not used [-Wunused-but-set-variable]
293 | int reg, mask;
| ^~~~
vim +/mask +293 drivers/hwmon/ina780.c
289
290 static int ina780_read_temp(struct device *dev, u32 attr, long *val)
291 {
292 struct ina780_data *data = dev_get_drvdata(dev);
> 293 int reg, mask;
294 int regval;
295 int err;
296
297 switch (attr) {
298 case hwmon_temp_input:
299 reg = INA780_DIETEMP;
300 break;
301 case hwmon_temp_max:
302 reg = INA780_TEMP_LIMIT;
303 break;
304 case hwmon_temp_max_alarm:
305 reg = INA780_DIAG_ALRT;
306 mask = INA780_DIAG_ALRT_TMPOL;
307 break;
308 default:
309 return -EOPNOTSUPP;
310 }
311
312 switch (attr) {
313 case hwmon_temp_input:
314 case hwmon_temp_max:
315 err = regmap_read(data->regmap, reg, ®val);
316 if (err)
317 return err;
318 *val = div_s64(((s64)((s16)regval) >> 4) * INA780_TEMP_LSB, 1000);
319 break;
320 case hwmon_temp_max_alarm:
321 err = regmap_read(data->regmap, INA780_DIAG_ALRT, ®val);
322 *val = !!(regval & INA780_DIAG_ALRT_TMPOL);
323 break;
324 }
325
326 return 0;
327 }
328
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] hwmon: (ina780) Add driver for TI INA780
2025-08-06 3:41 ` Chris Packham
@ 2025-08-06 20:22 ` Guenter Roeck
0 siblings, 0 replies; 9+ messages in thread
From: Guenter Roeck @ 2025-08-06 20:22 UTC (permalink / raw)
To: Chris Packham, jdelvare@suse.com, robh@kernel.org,
krzk+dt@kernel.org, conor+dt@kernel.org
Cc: linux-hwmon@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org
On 8/5/25 20:41, Chris Packham wrote:
> Hi Guenter,
>
> On 06/08/2025 15:14, Guenter Roeck wrote:
>> On 8/5/25 17:51, Chris Packham wrote:
>>> Add support for the TI INA780 Digital Power Monitor.
>>>
>>> Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz>
>>
>> Looking at the registers, the chip seems to be almost identical to
>> INA237/238.
>> Why a new driver ?
>
> Yes I'd noticed the same thing as I went along. The INA780 has the
> ezshunt thing (not sure if that's the same as the internal shunt on the
> INA260) which means that a lot of the places where things are calculated
> by the shunt resistor value aren't applicable and there's one less
> voltage sensor. I did consider adding it to the ina2xx.c but it seemed
> different enough to those chips to warrant a separate driver.
>
> I think I can kind of squint and see how I might fold the ina780 support
> into the ina238 driver although that may make things a bit messier. If
> that's the direction you'd like to head I can give it a go.
Compare against INA280. The only difference I can see is that there is no
shunt resistor register, and current/power/energy LSBs are constant instead
of being configurable. That should be quite straightforward to figure out.
Guenter
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] dt-bindings: hwmon: ti,ina780a: Add INA780 device
2025-08-06 6:32 ` [PATCH 1/2] dt-bindings: hwmon: ti,ina780a: Add INA780 device Krzysztof Kozlowski
@ 2025-08-07 20:46 ` Chris Packham
2025-08-08 7:16 ` Krzysztof Kozlowski
0 siblings, 1 reply; 9+ messages in thread
From: Chris Packham @ 2025-08-07 20:46 UTC (permalink / raw)
To: Krzysztof Kozlowski, jdelvare@suse.com, linux@roeck-us.net,
robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org
Cc: linux-hwmon@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org
On 06/08/2025 18:32, Krzysztof Kozlowski wrote:
> On 06/08/2025 02:51, Chris Packham wrote:
>> +
>> +properties:
>> + compatible:
>> + enum:
>> + - ti,ina780a
>> + - ti,ina780b
>> +
>> + reg:
>> + maxItems: 1
>
> This looks a bit incomplete. Where is a supply? No shunt resistor
> choice? No other properties from ina2xx apply?
This chip doesn't need a shunt so pretty much all that is required is
compatible + reg. Guenter did mention rolling this into the existing
ina238 driver (and ina2xx binding) so I'm looking at that right now. I'm
also thinking about dropping the A vs B distinction. They are ordering
options that do impact the accuracy of the ADC but driver wise they
behave the same.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] dt-bindings: hwmon: ti,ina780a: Add INA780 device
2025-08-07 20:46 ` Chris Packham
@ 2025-08-08 7:16 ` Krzysztof Kozlowski
0 siblings, 0 replies; 9+ messages in thread
From: Krzysztof Kozlowski @ 2025-08-08 7:16 UTC (permalink / raw)
To: Chris Packham
Cc: jdelvare@suse.com, linux@roeck-us.net, robh@kernel.org,
krzk+dt@kernel.org, conor+dt@kernel.org,
linux-hwmon@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org
On Thu, Aug 07, 2025 at 08:46:46PM +0000, Chris Packham wrote:
>
> On 06/08/2025 18:32, Krzysztof Kozlowski wrote:
> > On 06/08/2025 02:51, Chris Packham wrote:
> >> +
> >> +properties:
> >> + compatible:
> >> + enum:
> >> + - ti,ina780a
> >> + - ti,ina780b
> >> +
> >> + reg:
> >> + maxItems: 1
> >
> > This looks a bit incomplete. Where is a supply? No shunt resistor
> > choice? No other properties from ina2xx apply?
> This chip doesn't need a shunt so pretty much all that is required is
> compatible + reg. Guenter did mention rolling this into the existing
> ina238 driver (and ina2xx binding) so I'm looking at that right now. I'm
> also thinking about dropping the A vs B distinction. They are ordering
> options that do impact the accuracy of the ADC but driver wise they
> behave the same.
Then I suggest to skip a/b. Usually we do not have compatibles for
packaging differences or even consumer/industrial thermal choices.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2025-08-08 7:16 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-06 0:51 [PATCH 1/2] dt-bindings: hwmon: ti,ina780a: Add INA780 device Chris Packham
2025-08-06 0:51 ` [PATCH 2/2] hwmon: (ina780) Add driver for TI INA780 Chris Packham
2025-08-06 3:14 ` Guenter Roeck
2025-08-06 3:41 ` Chris Packham
2025-08-06 20:22 ` Guenter Roeck
2025-08-06 19:21 ` kernel test robot
2025-08-06 6:32 ` [PATCH 1/2] dt-bindings: hwmon: ti,ina780a: Add INA780 device Krzysztof Kozlowski
2025-08-07 20:46 ` Chris Packham
2025-08-08 7:16 ` Krzysztof Kozlowski
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).