[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20251118125148.95603-9-wenliang202407@163.com>
Date: Tue, 18 Nov 2025 07:51:48 -0500
From: Wenliang Yan <wenliang202407@....com>
To: linux@...ck-us.net,
Jean Delvare <jdelvare@...e.com>
Cc: Wenliang Yan <wenliang202407@....com>,
Rob Herring <robh@...nel.org>,
Krzysztof Kozlowski <krzk+dt@...nel.org>,
Conor Dooley <conor+dt@...nel.org>,
Jonathan Corbet <corbet@....net>,
linux-hwmon@...r.kernel.org,
linux-kernel@...r.kernel.org
Subject: [PATCH v2 8/8] hwmon: (ina3221) Modify write/read functions for 'in' and 'curr' attribute
Modified the relevant read/write functions for 'in' and 'curr' attributes,
adding support for crit, lcrit, crit_alarm, and lcrit_alarm features.
Signed-off-by: Wenliang Yan <wenliang202407@....com>
---
drivers/hwmon/ina3221.c | 96 +++++++++++++++++++++++++++++++++++++++--
1 file changed, 92 insertions(+), 4 deletions(-)
diff --git a/drivers/hwmon/ina3221.c b/drivers/hwmon/ina3221.c
index 197fc3a468e4..2f05ee6c72a9 100644
--- a/drivers/hwmon/ina3221.c
+++ b/drivers/hwmon/ina3221.c
@@ -373,6 +373,12 @@ static const u8 ina3221_in_reg[] = {
INA3221_SHUNT_SUM,
};
+static const u8 alert_flag[] = {
+ F_AFF1,
+ F_AFF2,
+ F_AFF3,
+};
+
static int ina3221_read_chip(struct device *dev, u32 attr, long *val)
{
struct ina3221_data *ina = dev_get_drvdata(dev);
@@ -435,6 +441,38 @@ static int ina3221_read_in(struct device *dev, u32 attr, int channel, long *val)
case hwmon_in_enable:
*val = ina3221_is_enabled(ina, channel);
return 0;
+ case hwmon_in_crit:
+ case hwmon_in_lcrit:
+ if (!ina3221_is_enabled(ina, channel))
+ return -ENODATA;
+
+ if (channel >= INA3221_NUM_CHANNELS)
+ return -EOPNOTSUPP;
+
+ reg = limit_regs[channel];
+ ret = ina3221_read_value(ina, reg, ®val);
+ if (ret)
+ return ret;
+ /*
+ * Scale of bus voltage (mV): LSB is 8mV
+ */
+ *val = regval * 8;
+ return 0;
+ case hwmon_in_crit_alarm:
+ case hwmon_in_lcrit_alarm:
+ /* No actual register read if channel is disabled */
+ if (!ina3221_is_enabled(ina, channel)) {
+ /* Return 0 for alert flags */
+ *val = 0;
+ return 0;
+ }
+
+ reg = alert_flag[channel];
+ ret = regmap_field_read(ina->fields[reg], ®val);
+ if (ret)
+ return ret;
+ *val = regval;
+ return 0;
default:
return -EOPNOTSUPP;
}
@@ -494,6 +532,25 @@ static int ina3221_read_curr(struct device *dev, u32 attr,
/* Return current in mA */
*val = DIV_ROUND_CLOSEST(voltage_nv, resistance_uo);
return 0;
+ case hwmon_curr_lcrit:
+ if (!resistance_uo)
+ return -ENODATA;
+
+ if (channel >= INA3221_NUM_CHANNELS)
+ return -EOPNOTSUPP;
+
+ reg = limit_regs[channel];
+ ret = ina3221_read_value(ina, reg, ®val);
+ if (ret)
+ return ret;
+
+ /* Return current in mA */
+ *val = DIV_ROUND_CLOSEST(regval * ina->current_lsb_uA, 1000);
+ return 0;
+ case hwmon_curr_lcrit_alarm:
+ reg = alert_flag[channel];
+
+ fallthrough;
case hwmon_curr_crit_alarm:
case hwmon_curr_max_alarm:
/* No actual register read if channel is disabled */
@@ -690,10 +747,9 @@ static int ina3221_write_chip(struct device *dev, u32 attr, long val)
}
}
-static int ina3221_write_curr(struct device *dev, u32 attr,
- int channel, long val)
+static int ina3221_write_curr_shunt(struct ina3221_data *ina, u32 attr,
+ int channel, long val)
{
- struct ina3221_data *ina = dev_get_drvdata(dev);
struct ina3221_input *input = ina->inputs;
u8 reg = ina3221_curr_reg[attr][channel];
int resistance_uo, current_ma, voltage_uv;
@@ -736,6 +792,22 @@ static int ina3221_write_curr(struct device *dev, u32 attr,
return regmap_write(ina->regmap, reg, regval);
}
+static int ina3221_write_curr(struct device *dev, u32 attr,
+ int channel, long val)
+{
+ struct ina3221_data *ina = dev_get_drvdata(dev);
+
+ switch (attr) {
+ case hwmon_curr_crit:
+ case hwmon_curr_max:
+ return ina3221_write_curr_shunt(ina, attr, channel, val);
+ case hwmon_curr_lcrit:
+ return sq52210_alert_limit_write(ina, attr, channel, val);
+ default:
+ return 0;
+ }
+}
+
static int ina3221_write_enable(struct device *dev, int channel, bool enable)
{
struct ina3221_data *ina = dev_get_drvdata(dev);
@@ -784,6 +856,22 @@ static int ina3221_write_enable(struct device *dev, int channel, bool enable)
return ret;
}
+static int ina3221_write_in(struct device *dev, u32 attr, int channel, long val)
+{
+ struct ina3221_data *ina = dev_get_drvdata(dev);
+
+ switch (attr) {
+ case hwmon_in_lcrit:
+ return sq52210_alert_limit_write(ina, attr, channel, val);
+ case hwmon_in_crit:
+ return sq52210_alert_limit_write(ina, attr, channel, val);
+ case hwmon_in_enable:
+ return ina3221_write_enable(dev, channel, val);
+ default:
+ return 0;
+ }
+}
+
static int ina3221_write_power(struct device *dev, u32 attr, int channel, long val)
{
struct ina3221_data *ina = dev_get_drvdata(dev);
@@ -833,7 +921,7 @@ static int ina3221_write(struct device *dev, enum hwmon_sensor_types type,
break;
case hwmon_in:
/* 0-align channel ID */
- ret = ina3221_write_enable(dev, channel - 1, val);
+ ret = ina3221_write_in(dev, attr, channel - 1, val);
break;
case hwmon_curr:
ret = ina3221_write_curr(dev, attr, channel, val);
--
2.17.1
Powered by blists - more mailing lists