diff options
Diffstat (limited to 'drivers/hwmon/ina209.c')
| -rw-r--r-- | drivers/hwmon/ina209.c | 231 |
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, |
