From: Guenter Roeck <linux@roeck-us.net>
To: Hardware Monitoring <linux-hwmon@vger.kernel.org>
Cc: Tzung-Bi Shih <tzungbi@kernel.org>, Guenter Roeck <linux@roeck-us.net>
Subject: [PATCH v2 06/14] hwmon: (ina2xx) Re-initialize chip using regmap functions
Date: Thu, 29 Aug 2024 18:05:46 -0700 [thread overview]
Message-ID: <20240830010554.1462861-7-linux@roeck-us.net> (raw)
In-Reply-To: <20240830010554.1462861-1-linux@roeck-us.net>
If it is necessary to re-initialize the chip, for example because
it has been power cycled, use regmap functions to update register
contents. This ensures that all registers, including the configuration
register and alert registers, are updated to previously configured
values without having to locally cache everything.
For this to work, volatile registers have to be marked as volatile.
Also, the cache needs to be bypassed when reading the calibration
and mask_enable registers. While the calibration register is not
volatile, it will be reset to 0 if the chip has been power cycled.
Most of the bits in the mask_enable register are configuration bits,
except for bit 4 which reports if an alert has been observed.
Both registers need to be marked as non-volatile to be updated
after a power cycle, but it is necessary to bypass the cache when
reading them to detect if the chip has been power cycled and to
read the alert status.
The chip does not support register auto-increments. It is therefore
necessary to configure regmap to use single register read/write
operations. Otherwise regmap tries to write all registers in a single
operation when synchronizing register contents with the hardware,
and the synchronization fails.
Another necessary change is to declare ina226_alert_to_reg() as u16.
So far it returned an s16 which is sign extended to a large negative
value which is then sent to regmap as unsigned int, causing an -EINVAL
error return.
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
v2: Fixed typo in patch description (ben -> been)
Added .use_single_write = true and .use_single_read = true to
regmap configuration
drivers/hwmon/ina2xx.c | 50 ++++++++++++++++++++++++++++++++++--------
1 file changed, 41 insertions(+), 9 deletions(-)
diff --git a/drivers/hwmon/ina2xx.c b/drivers/hwmon/ina2xx.c
index ed8764a29d3f..db6432523e59 100644
--- a/drivers/hwmon/ina2xx.c
+++ b/drivers/hwmon/ina2xx.c
@@ -91,10 +91,41 @@
*/
#define INA226_TOTAL_CONV_TIME_DEFAULT 2200
+static bool ina2xx_writeable_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case INA2XX_CONFIG:
+ case INA2XX_CALIBRATION:
+ case INA226_MASK_ENABLE:
+ case INA226_ALERT_LIMIT:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool ina2xx_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case INA2XX_SHUNT_VOLTAGE:
+ case INA2XX_BUS_VOLTAGE:
+ case INA2XX_POWER:
+ case INA2XX_CURRENT:
+ return true;
+ default:
+ return false;
+ }
+}
+
static const struct regmap_config ina2xx_regmap_config = {
.reg_bits = 8,
.val_bits = 16,
+ .use_single_write = true,
+ .use_single_read = true,
.max_register = INA2XX_MAX_REGISTERS,
+ .cache_type = REGCACHE_MAPLE,
+ .volatile_reg = ina2xx_volatile_reg,
+ .writeable_reg = ina2xx_writeable_reg,
};
enum ina2xx_ids { ina219, ina226 };
@@ -229,16 +260,16 @@ static int ina2xx_read_reg(struct device *dev, int reg, unsigned int *regval)
if (*regval == 0) {
unsigned int cal;
- ret = regmap_read(regmap, INA2XX_CALIBRATION, &cal);
+ ret = regmap_read_bypassed(regmap, INA2XX_CALIBRATION, &cal);
if (ret < 0)
return ret;
if (cal == 0) {
dev_warn(dev, "chip not calibrated, reinitializing\n");
- ret = ina2xx_init(data);
- if (ret < 0)
- return ret;
+ regcache_mark_dirty(regmap);
+ regcache_sync(regmap);
+
/*
* Let's make sure the power and current
* registers have been updated before trying
@@ -340,7 +371,7 @@ static int ina226_reg_to_alert(struct ina2xx_data *data, u32 mask, u16 regval)
* Turns alert limit values into register values.
* Opposite of the formula in ina2xx_get_value().
*/
-static s16 ina226_alert_to_reg(struct ina2xx_data *data, u32 mask, int val)
+static u16 ina226_alert_to_reg(struct ina2xx_data *data, u32 mask, int val)
{
switch (mask) {
case INA226_SHUNT_OVER_VOLTAGE_MASK:
@@ -439,16 +470,17 @@ static ssize_t ina226_alarm_show(struct device *dev,
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct ina2xx_data *data = dev_get_drvdata(dev);
- int regval;
+ unsigned int mask;
int alarm = 0;
int ret;
- ret = regmap_read(data->regmap, INA226_MASK_ENABLE, ®val);
+ ret = regmap_read_bypassed(data->regmap, INA226_MASK_ENABLE, &mask);
if (ret)
return ret;
- alarm = (regval & attr->index) &&
- (regval & INA226_ALERT_FUNCTION_FLAG);
+ alarm = (mask & attr->index) &&
+ (mask & INA226_ALERT_FUNCTION_FLAG);
+
return sysfs_emit(buf, "%d\n", alarm);
}
--
2.45.2
next prev parent reply other threads:[~2024-08-30 1:06 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-08-30 1:05 [PATCH v2 00/14] hwmon: (ina2xx) Cleanup and convert to use with_info API Guenter Roeck
2024-08-30 1:05 ` [PATCH v2 01/14] hwmon: (ina2xx) Reorder include files to alphabetic order Guenter Roeck
2024-08-30 1:05 ` [PATCH v2 02/14] hwmon: (ina2xx) Replace platform data with device properties Guenter Roeck
2024-08-30 1:05 ` [PATCH v2 03/14] hwmon: (ina2xx) Use bit operations Guenter Roeck
2024-08-30 1:05 ` [PATCH v2 04/14] hwmon: (ina2xx) Mark regmap_config as const Guenter Roeck
2024-08-30 12:28 ` Tzung-Bi Shih
2024-08-30 1:05 ` [PATCH v2 05/14] hwmon: (ina2xx) Use local regmap pointer if used more than once Guenter Roeck
2024-08-30 1:05 ` Guenter Roeck [this message]
2024-08-30 12:29 ` [PATCH v2 06/14] hwmon: (ina2xx) Re-initialize chip using regmap functions Tzung-Bi Shih
2024-08-30 1:05 ` [PATCH v2 07/14] hwmon: (ina2xx) Fix various overflow issues Guenter Roeck
2024-08-30 1:05 ` [PATCH v2 08/14] hwmon: (ina2xx) Consolidate chip initialization code Guenter Roeck
2024-08-30 12:29 ` Tzung-Bi Shih
2024-08-30 1:05 ` [PATCH v2 09/14] hwmon: (ina2xx) Set alert latch Guenter Roeck
2024-08-30 12:29 ` Tzung-Bi Shih
2024-08-30 1:05 ` [PATCH v2 10/14] hwmon: (ina2xx) Move ina2xx_get_value() Guenter Roeck
2024-08-30 1:05 ` [PATCH v2 11/14] hwmon: (ina2xx) Convert to use with_info hwmon API Guenter Roeck
2024-08-30 12:30 ` Tzung-Bi Shih
2024-08-30 15:32 ` Guenter Roeck
2024-08-30 1:05 ` [PATCH v2 12/14] hwmon: (ina2xx) Pass register to alert limit write functions Guenter Roeck
2024-08-30 12:30 ` Tzung-Bi Shih
2024-08-30 1:05 ` [PATCH v2 13/14] hwmon: (ina2xx) Add support for current limits Guenter Roeck
2024-08-30 12:30 ` Tzung-Bi Shih
2024-08-30 1:05 ` [PATCH v2 14/14] hwmon: (ina2xx) Use shunt voltage to calculate current Guenter Roeck
2024-08-30 12:30 ` Tzung-Bi Shih
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=20240830010554.1462861-7-linux@roeck-us.net \
--to=linux@roeck-us.net \
--cc=linux-hwmon@vger.kernel.org \
--cc=tzungbi@kernel.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox