summaryrefslogtreecommitdiff
path: root/drivers/hwmon/ina209.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hwmon/ina209.c')
-rw-r--r--drivers/hwmon/ina209.c231
1 files changed, 100 insertions, 131 deletions
diff --git a/drivers/hwmon/ina209.c b/drivers/hwmon/ina209.c
index c6fdd5bd395e..bd7b3380d847 100644
--- a/drivers/hwmon/ina209.c
+++ b/drivers/hwmon/ina209.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Driver for the Texas Instruments / Burr Brown INA209
* Bidirectional Current/Power Monitor
@@ -12,12 +13,8 @@
* Copyright (C) 2012 Lothar Felten <l-felten@ti.com>
* Thanks to Jan Volkering
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
* Datasheet:
- * http://www.ti.com/lit/gpn/ina209
+ * https://www.ti.com/lit/gpn/ina209
*/
#include <linux/kernel.h>
@@ -63,7 +60,7 @@
#define INA209_SHUNT_DEFAULT 10000 /* uOhm */
struct ina209_data {
- struct device *hwmon_dev;
+ struct i2c_client *client;
struct mutex update_lock;
bool valid;
@@ -78,8 +75,8 @@ struct ina209_data {
static struct ina209_data *ina209_update_device(struct device *dev)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct ina209_data *data = i2c_get_clientdata(client);
+ struct ina209_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
struct ina209_data *ret = data;
s32 val;
int i;
@@ -117,7 +114,7 @@ static long ina209_from_reg(const u8 reg, const u16 val)
case INA209_SHUNT_VOLTAGE_POS_WARN:
case INA209_SHUNT_VOLTAGE_NEG_WARN:
/* LSB=10 uV. Convert to mV. */
- return DIV_ROUND_CLOSEST(val, 100);
+ return DIV_ROUND_CLOSEST((s16)val, 100);
case INA209_BUS_VOLTAGE:
case INA209_BUS_VOLTAGE_MAX_PEAK:
@@ -146,7 +143,7 @@ static long ina209_from_reg(const u8 reg, const u16 val)
case INA209_CURRENT:
/* LSB=1 mA (selected). Is in mA */
- return val;
+ return (s16)val;
}
/* programmer goofed */
@@ -230,11 +227,10 @@ static u16 ina209_reg_from_interval(u16 config, long interval)
return (config & 0xf807) | (adc << 3) | (adc << 7);
}
-static ssize_t ina209_set_interval(struct device *dev,
- struct device_attribute *da,
- const char *buf, size_t count)
+static ssize_t ina209_interval_store(struct device *dev,
+ struct device_attribute *da,
+ const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
struct ina209_data *data = ina209_update_device(dev);
long val;
u16 regval;
@@ -250,20 +246,20 @@ static ssize_t ina209_set_interval(struct device *dev,
mutex_lock(&data->update_lock);
regval = ina209_reg_from_interval(data->regs[INA209_CONFIGURATION],
val);
- i2c_smbus_write_word_swapped(client, INA209_CONFIGURATION, regval);
+ i2c_smbus_write_word_swapped(data->client, INA209_CONFIGURATION,
+ regval);
data->regs[INA209_CONFIGURATION] = regval;
data->update_interval = ina209_interval_from_reg(regval);
mutex_unlock(&data->update_lock);
return count;
}
-static ssize_t ina209_show_interval(struct device *dev,
+static ssize_t ina209_interval_show(struct device *dev,
struct device_attribute *da, char *buf)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct ina209_data *data = i2c_get_clientdata(client);
+ struct ina209_data *data = dev_get_drvdata(dev);
- return snprintf(buf, PAGE_SIZE, "%d\n", data->update_interval);
+ return sysfs_emit(buf, "%d\n", data->update_interval);
}
/*
@@ -280,14 +276,13 @@ static u16 ina209_reset_history_regs[] = {
INA209_POWER_PEAK
};
-static ssize_t ina209_reset_history(struct device *dev,
+static ssize_t ina209_history_store(struct device *dev,
struct device_attribute *da,
- const char *buf,
- size_t count)
+ const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct ina209_data *data = i2c_get_clientdata(client);
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct ina209_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
u32 mask = attr->index;
long val;
int i, ret;
@@ -307,12 +302,10 @@ static ssize_t ina209_reset_history(struct device *dev,
return count;
}
-static ssize_t ina209_set_value(struct device *dev,
- struct device_attribute *da,
- const char *buf,
- size_t count)
+static ssize_t ina209_value_store(struct device *dev,
+ struct device_attribute *da,
+ const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
struct ina209_data *data = ina209_update_device(dev);
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
int reg = attr->index;
@@ -332,16 +325,15 @@ static ssize_t ina209_set_value(struct device *dev,
count = ret;
goto abort;
}
- i2c_smbus_write_word_swapped(client, reg, ret);
+ i2c_smbus_write_word_swapped(data->client, reg, ret);
data->regs[reg] = ret;
abort:
mutex_unlock(&data->update_lock);
return count;
}
-static ssize_t ina209_show_value(struct device *dev,
- struct device_attribute *da,
- char *buf)
+static ssize_t ina209_value_show(struct device *dev,
+ struct device_attribute *da, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct ina209_data *data = ina209_update_device(dev);
@@ -351,12 +343,11 @@ static ssize_t ina209_show_value(struct device *dev,
return PTR_ERR(data);
val = ina209_from_reg(attr->index, data->regs[attr->index]);
- return snprintf(buf, PAGE_SIZE, "%ld\n", val);
+ return sysfs_emit(buf, "%ld\n", val);
}
-static ssize_t ina209_show_alarm(struct device *dev,
- struct device_attribute *da,
- char *buf)
+static ssize_t ina209_alarm_show(struct device *dev,
+ struct device_attribute *da, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct ina209_data *data = ina209_update_device(dev);
@@ -372,92 +363,75 @@ static ssize_t ina209_show_alarm(struct device *dev,
* All alarms are in the INA209_STATUS register. To avoid a long
* switch statement, the mask is passed in attr->index
*/
- return snprintf(buf, PAGE_SIZE, "%u\n", !!(status & mask));
+ return sysfs_emit(buf, "%u\n", !!(status & mask));
}
/* Shunt voltage, history, limits, alarms */
-static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, ina209_show_value, NULL,
- INA209_SHUNT_VOLTAGE);
-static SENSOR_DEVICE_ATTR(in0_input_highest, S_IRUGO, ina209_show_value, NULL,
- INA209_SHUNT_VOLTAGE_POS_PEAK);
-static SENSOR_DEVICE_ATTR(in0_input_lowest, S_IRUGO, ina209_show_value, NULL,
- INA209_SHUNT_VOLTAGE_NEG_PEAK);
-static SENSOR_DEVICE_ATTR(in0_reset_history, S_IWUSR, NULL,
- ina209_reset_history, (1 << 0) | (1 << 1));
-static SENSOR_DEVICE_ATTR(in0_max, S_IRUGO | S_IWUSR, ina209_show_value,
- ina209_set_value, INA209_SHUNT_VOLTAGE_POS_WARN);
-static SENSOR_DEVICE_ATTR(in0_min, S_IRUGO | S_IWUSR, ina209_show_value,
- ina209_set_value, INA209_SHUNT_VOLTAGE_NEG_WARN);
-static SENSOR_DEVICE_ATTR(in0_crit_max, S_IRUGO | S_IWUSR, ina209_show_value,
- ina209_set_value, INA209_CRITICAL_DAC_POS);
-static SENSOR_DEVICE_ATTR(in0_crit_min, S_IRUGO | S_IWUSR, ina209_show_value,
- ina209_set_value, INA209_CRITICAL_DAC_NEG);
-
-static SENSOR_DEVICE_ATTR(in0_min_alarm, S_IRUGO, ina209_show_alarm, NULL,
- 1 << 11);
-static SENSOR_DEVICE_ATTR(in0_max_alarm, S_IRUGO, ina209_show_alarm, NULL,
- 1 << 12);
-static SENSOR_DEVICE_ATTR(in0_crit_min_alarm, S_IRUGO, ina209_show_alarm, NULL,
- 1 << 6);
-static SENSOR_DEVICE_ATTR(in0_crit_max_alarm, S_IRUGO, ina209_show_alarm, NULL,
- 1 << 7);
+static SENSOR_DEVICE_ATTR_RO(in0_input, ina209_value, INA209_SHUNT_VOLTAGE);
+static SENSOR_DEVICE_ATTR_RO(in0_input_highest, ina209_value,
+ INA209_SHUNT_VOLTAGE_POS_PEAK);
+static SENSOR_DEVICE_ATTR_RO(in0_input_lowest, ina209_value,
+ INA209_SHUNT_VOLTAGE_NEG_PEAK);
+static SENSOR_DEVICE_ATTR_WO(in0_reset_history, ina209_history,
+ (1 << 0) | (1 << 1));
+static SENSOR_DEVICE_ATTR_RW(in0_max, ina209_value,
+ INA209_SHUNT_VOLTAGE_POS_WARN);
+static SENSOR_DEVICE_ATTR_RW(in0_min, ina209_value,
+ INA209_SHUNT_VOLTAGE_NEG_WARN);
+static SENSOR_DEVICE_ATTR_RW(in0_crit_max, ina209_value,
+ INA209_CRITICAL_DAC_POS);
+static SENSOR_DEVICE_ATTR_RW(in0_crit_min, ina209_value,
+ INA209_CRITICAL_DAC_NEG);
+
+static SENSOR_DEVICE_ATTR_RO(in0_min_alarm, ina209_alarm, 1 << 11);
+static SENSOR_DEVICE_ATTR_RO(in0_max_alarm, ina209_alarm, 1 << 12);
+static SENSOR_DEVICE_ATTR_RO(in0_crit_min_alarm, ina209_alarm, 1 << 6);
+static SENSOR_DEVICE_ATTR_RO(in0_crit_max_alarm, ina209_alarm, 1 << 7);
/* Bus voltage, history, limits, alarms */
-static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, ina209_show_value, NULL,
- INA209_BUS_VOLTAGE);
-static SENSOR_DEVICE_ATTR(in1_input_highest, S_IRUGO, ina209_show_value, NULL,
- INA209_BUS_VOLTAGE_MAX_PEAK);
-static SENSOR_DEVICE_ATTR(in1_input_lowest, S_IRUGO, ina209_show_value, NULL,
- INA209_BUS_VOLTAGE_MIN_PEAK);
-static SENSOR_DEVICE_ATTR(in1_reset_history, S_IWUSR, NULL,
- ina209_reset_history, (1 << 2) | (1 << 3));
-static SENSOR_DEVICE_ATTR(in1_max, S_IRUGO | S_IWUSR, ina209_show_value,
- ina209_set_value, INA209_BUS_VOLTAGE_OVER_WARN);
-static SENSOR_DEVICE_ATTR(in1_min, S_IRUGO | S_IWUSR, ina209_show_value,
- ina209_set_value, INA209_BUS_VOLTAGE_UNDER_WARN);
-static SENSOR_DEVICE_ATTR(in1_crit_max, S_IRUGO | S_IWUSR, ina209_show_value,
- ina209_set_value, INA209_BUS_VOLTAGE_OVER_LIMIT);
-static SENSOR_DEVICE_ATTR(in1_crit_min, S_IRUGO | S_IWUSR, ina209_show_value,
- ina209_set_value, INA209_BUS_VOLTAGE_UNDER_LIMIT);
-
-static SENSOR_DEVICE_ATTR(in1_min_alarm, S_IRUGO, ina209_show_alarm, NULL,
- 1 << 14);
-static SENSOR_DEVICE_ATTR(in1_max_alarm, S_IRUGO, ina209_show_alarm, NULL,
- 1 << 15);
-static SENSOR_DEVICE_ATTR(in1_crit_min_alarm, S_IRUGO, ina209_show_alarm, NULL,
- 1 << 9);
-static SENSOR_DEVICE_ATTR(in1_crit_max_alarm, S_IRUGO, ina209_show_alarm, NULL,
- 1 << 10);
+static SENSOR_DEVICE_ATTR_RO(in1_input, ina209_value, INA209_BUS_VOLTAGE);
+static SENSOR_DEVICE_ATTR_RO(in1_input_highest, ina209_value,
+ INA209_BUS_VOLTAGE_MAX_PEAK);
+static SENSOR_DEVICE_ATTR_RO(in1_input_lowest, ina209_value,
+ INA209_BUS_VOLTAGE_MIN_PEAK);
+static SENSOR_DEVICE_ATTR_WO(in1_reset_history, ina209_history,
+ (1 << 2) | (1 << 3));
+static SENSOR_DEVICE_ATTR_RW(in1_max, ina209_value,
+ INA209_BUS_VOLTAGE_OVER_WARN);
+static SENSOR_DEVICE_ATTR_RW(in1_min, ina209_value,
+ INA209_BUS_VOLTAGE_UNDER_WARN);
+static SENSOR_DEVICE_ATTR_RW(in1_crit_max, ina209_value,
+ INA209_BUS_VOLTAGE_OVER_LIMIT);
+static SENSOR_DEVICE_ATTR_RW(in1_crit_min, ina209_value,
+ INA209_BUS_VOLTAGE_UNDER_LIMIT);
+
+static SENSOR_DEVICE_ATTR_RO(in1_min_alarm, ina209_alarm, 1 << 14);
+static SENSOR_DEVICE_ATTR_RO(in1_max_alarm, ina209_alarm, 1 << 15);
+static SENSOR_DEVICE_ATTR_RO(in1_crit_min_alarm, ina209_alarm, 1 << 9);
+static SENSOR_DEVICE_ATTR_RO(in1_crit_max_alarm, ina209_alarm, 1 << 10);
/* Power */
-static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, ina209_show_value, NULL,
- INA209_POWER);
-static SENSOR_DEVICE_ATTR(power1_input_highest, S_IRUGO, ina209_show_value,
- NULL, INA209_POWER_PEAK);
-static SENSOR_DEVICE_ATTR(power1_reset_history, S_IWUSR, NULL,
- ina209_reset_history, 1 << 4);
-static SENSOR_DEVICE_ATTR(power1_max, S_IRUGO | S_IWUSR, ina209_show_value,
- ina209_set_value, INA209_POWER_WARN);
-static SENSOR_DEVICE_ATTR(power1_crit, S_IRUGO | S_IWUSR, ina209_show_value,
- ina209_set_value, INA209_POWER_OVER_LIMIT);
-
-static SENSOR_DEVICE_ATTR(power1_max_alarm, S_IRUGO, ina209_show_alarm, NULL,
- 1 << 13);
-static SENSOR_DEVICE_ATTR(power1_crit_alarm, S_IRUGO, ina209_show_alarm, NULL,
- 1 << 8);
+static SENSOR_DEVICE_ATTR_RO(power1_input, ina209_value, INA209_POWER);
+static SENSOR_DEVICE_ATTR_RO(power1_input_highest, ina209_value,
+ INA209_POWER_PEAK);
+static SENSOR_DEVICE_ATTR_WO(power1_reset_history, ina209_history, 1 << 4);
+static SENSOR_DEVICE_ATTR_RW(power1_max, ina209_value, INA209_POWER_WARN);
+static SENSOR_DEVICE_ATTR_RW(power1_crit, ina209_value,
+ INA209_POWER_OVER_LIMIT);
+
+static SENSOR_DEVICE_ATTR_RO(power1_max_alarm, ina209_alarm, 1 << 13);
+static SENSOR_DEVICE_ATTR_RO(power1_crit_alarm, ina209_alarm, 1 << 8);
/* Current */
-static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, ina209_show_value, NULL,
- INA209_CURRENT);
+static SENSOR_DEVICE_ATTR_RO(curr1_input, ina209_value, INA209_CURRENT);
-static SENSOR_DEVICE_ATTR(update_interval, S_IRUGO | S_IWUSR,
- ina209_show_interval, ina209_set_interval, 0);
+static SENSOR_DEVICE_ATTR_RW(update_interval, ina209_interval, 0);
/*
* Finally, construct an array of pointers to members of the above objects,
* as required for sysfs_create_group()
*/
-static struct attribute *ina209_attributes[] = {
+static struct attribute *ina209_attrs[] = {
&sensor_dev_attr_in0_input.dev_attr.attr,
&sensor_dev_attr_in0_input_highest.dev_attr.attr,
&sensor_dev_attr_in0_input_lowest.dev_attr.attr,
@@ -498,10 +472,7 @@ static struct attribute *ina209_attributes[] = {
NULL,
};
-
-static const struct attribute_group ina209_group = {
- .attrs = ina209_attributes,
-};
+ATTRIBUTE_GROUPS(ina209);
static void ina209_restore_conf(struct i2c_client *client,
struct ina209_data *data)
@@ -560,11 +531,11 @@ static int ina209_init_client(struct i2c_client *client,
return 0;
}
-static int ina209_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int ina209_probe(struct i2c_client *client)
{
struct i2c_adapter *adapter = client->adapter;
struct ina209_data *data;
+ struct device *hwmon_dev;
int ret;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA))
@@ -575,54 +546,52 @@ static int ina209_probe(struct i2c_client *client,
return -ENOMEM;
i2c_set_clientdata(client, data);
+ data->client = client;
mutex_init(&data->update_lock);
ret = ina209_init_client(client, data);
if (ret)
return ret;
- /* Register sysfs hooks */
- ret = sysfs_create_group(&client->dev.kobj, &ina209_group);
- if (ret)
+ hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev,
+ client->name,
+ data, ina209_groups);
+ if (IS_ERR(hwmon_dev)) {
+ ret = PTR_ERR(hwmon_dev);
goto out_restore_conf;
-
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- ret = PTR_ERR(data->hwmon_dev);
- goto out_hwmon_device_register;
}
return 0;
-out_hwmon_device_register:
- sysfs_remove_group(&client->dev.kobj, &ina209_group);
out_restore_conf:
ina209_restore_conf(client, data);
return ret;
}
-static int ina209_remove(struct i2c_client *client)
+static void ina209_remove(struct i2c_client *client)
{
struct ina209_data *data = i2c_get_clientdata(client);
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &ina209_group);
ina209_restore_conf(client, data);
-
- return 0;
}
static const struct i2c_device_id ina209_id[] = {
- { "ina209", 0 },
+ { "ina209" },
{ }
};
MODULE_DEVICE_TABLE(i2c, ina209_id);
+static const struct of_device_id __maybe_unused ina209_of_match[] = {
+ { .compatible = "ti,ina209" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, ina209_of_match);
+
/* This is the driver that will be inserted */
static struct i2c_driver ina209_driver = {
- .class = I2C_CLASS_HWMON,
.driver = {
.name = "ina209",
+ .of_match_table = of_match_ptr(ina209_of_match),
},
.probe = ina209_probe,
.remove = ina209_remove,