Commit 88548710 authored by Daniel Matyas's avatar Daniel Matyas Committed by Guenter Roeck

hwmon: (max31827) Handle new properties from the devicetree

Used fwnode to retrieve data from the devicetree in the init_client
function.

If the uint32 properties are not present, the default values are used
for max31827 chip.
Signed-off-by: default avatarDaniel Matyas <daniel.matyas@analog.com>
Link: https://lore.kernel.org/r/20231031182158.124608-1-daniel.matyas@analog.comSigned-off-by: default avatarGuenter Roeck <linux@roeck-us.net>
parent b4498792
......@@ -52,13 +52,21 @@ MAX31827 has low and over temperature alarms with an effective value and a
hysteresis value: -40 and -30 degrees for under temperature alarm and +100 and
+90 degrees for over temperature alarm.
The alarm can be configured in comparator and interrupt mode. Currently only
comparator mode is implemented. In Comparator mode, the OT/UT status bits have a
value of 1 when the temperature rises above the TH value or falls below TL,
which is also subject to the Fault Queue selection. OT status returns to 0 when
the temperature drops below the TH_HYST value or when shutdown mode is entered.
Similarly, UT status returns to 0 when the temperature rises above TL_HYST value
or when shutdown mode is entered.
The alarm can be configured in comparator and interrupt mode from the
devicetree. In Comparator mode, the OT/UT status bits have a value of 1 when the
temperature rises above the TH value or falls below TL, which is also subject to
the Fault Queue selection. OT status returns to 0 when the temperature drops
below the TH_HYST value or when shutdown mode is entered. Similarly, UT status
returns to 0 when the temperature rises above TL_HYST value or when shutdown
mode is entered.
In interrupt mode exceeding TH also sets OT status to 1, which remains set until
a read operation is performed on the configuration/status register (max or min
attribute); at this point, it returns to 0. Once OT status is set to 1 from
exceeding TH and reset, it is set to 1 again only when the temperature drops
below TH_HYST. The output remains asserted until it is reset by a read. It is
set again if the temperature rises above TH, and so on. The same logic applies
to the operation of the UT status bit.
Putting the MAX31827 into shutdown mode also resets the OT/UT status bits. Note
that if the mode is changed while OT/UT status bits are set, an OT/UT status
......@@ -68,6 +76,18 @@ clear the status bits before changing the operating mode.
The conversions can be manual with the one-shot functionality and automatic with
a set frequency. When powered on, the chip measures temperatures with 1 conv/s.
The conversion rate can be modified with update_interval attribute of the chip.
Conversion/second = 1/update_interval. Thus, the available options according to
the data sheet are:
- 64000 (ms) = 1 conv/64 sec
- 32000 (ms) = 1 conv/32 sec
- 16000 (ms) = 1 conv/16 sec
- 4000 (ms) = 1 conv/4 sec
- 1000 (ms) = 1 conv/sec (default)
- 250 (ms) = 4 conv/sec
- 125 (ms) = 8 conv/sec
Enabling the device when it is already enabled has the side effect of setting
the conversion frequency to 1 conv/s. The conversion time varies depending on
the resolution. The conversion time doubles with every bit of increased
......@@ -83,8 +103,18 @@ in the writing of alarm values too. For positive numbers the user-input value
will always be rounded down to the nearest possible value, for negative numbers
the user-input will always be rounded up to the nearest possible value.
Bus timeout resets the I2C-compatible interface when SCL is low for more than
30ms (nominal).
Alarm polarity determines if the active state of the alarm is low or high. The
behavior for both settings is dependent on the Fault Queue setting. The ALARM
pin is an open-drain output and requires a pullup resistor to operate.
The Fault Queue bits select how many consecutive temperature faults must occur
before overtemperature or undertemperature faults are indicated in the
corresponding status bits.
Notes
-----
Currently fault queue, alarm polarity and resolution cannot be modified.
PEC is not implemented either.
PEC and resolution are not implemented.
......@@ -11,6 +11,7 @@
#include <linux/hwmon.h>
#include <linux/i2c.h>
#include <linux/mutex.h>
#include <linux/of_device.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
......@@ -23,9 +24,17 @@
#define MAX31827_CONFIGURATION_1SHOT_MASK BIT(0)
#define MAX31827_CONFIGURATION_CNV_RATE_MASK GENMASK(3, 1)
#define MAX31827_CONFIGURATION_TIMEOUT_MASK BIT(5)
#define MAX31827_CONFIGURATION_RESOLUTION_MASK GENMASK(7, 6)
#define MAX31827_CONFIGURATION_ALRM_POL_MASK BIT(8)
#define MAX31827_CONFIGURATION_COMP_INT_MASK BIT(9)
#define MAX31827_CONFIGURATION_FLT_Q_MASK GENMASK(11, 10)
#define MAX31827_CONFIGURATION_U_TEMP_STAT_MASK BIT(14)
#define MAX31827_CONFIGURATION_O_TEMP_STAT_MASK BIT(15)
#define MAX31827_ALRM_POL_LOW 0x0
#define MAX31827_FLT_Q_1 0x0
#define MAX31827_12_BIT_CNV_TIME 140
#define MAX31827_16_BIT_TO_M_DGR(x) (sign_extend32(x, 15) * 1000 / 16)
......@@ -362,14 +371,68 @@ static int max31827_write(struct device *dev, enum hwmon_sensor_types type,
return -EOPNOTSUPP;
}
static int max31827_init_client(struct max31827_state *st)
static int max31827_init_client(struct max31827_state *st,
struct device *dev)
{
struct fwnode_handle *fwnode;
unsigned int res = 0;
u32 data, lsb_idx;
bool prop;
int ret;
fwnode = dev_fwnode(dev);
st->enable = true;
res |= MAX31827_DEVICE_ENABLE(1);
return regmap_update_bits(st->regmap, MAX31827_CONFIGURATION_REG,
MAX31827_CONFIGURATION_1SHOT_MASK |
MAX31827_CONFIGURATION_CNV_RATE_MASK,
MAX31827_DEVICE_ENABLE(1));
res |= MAX31827_CONFIGURATION_RESOLUTION_MASK;
prop = fwnode_property_read_bool(fwnode, "adi,comp-int");
res |= FIELD_PREP(MAX31827_CONFIGURATION_COMP_INT_MASK, prop);
prop = fwnode_property_read_bool(fwnode, "adi,timeout-enable");
res |= FIELD_PREP(MAX31827_CONFIGURATION_TIMEOUT_MASK, !prop);
if (fwnode_property_present(fwnode, "adi,alarm-pol")) {
ret = fwnode_property_read_u32(fwnode, "adi,alarm-pol", &data);
if (ret)
return ret;
res |= FIELD_PREP(MAX31827_CONFIGURATION_ALRM_POL_MASK, !!data);
} else {
/*
* Set default value.
*/
res |= FIELD_PREP(MAX31827_CONFIGURATION_ALRM_POL_MASK,
MAX31827_ALRM_POL_LOW);
}
if (fwnode_property_present(fwnode, "adi,fault-q")) {
ret = fwnode_property_read_u32(fwnode, "adi,fault-q", &data);
if (ret)
return ret;
/*
* Convert the desired fault queue into register bits.
*/
if (data != 0)
lsb_idx = __ffs(data);
if (hweight32(data) != 1 || lsb_idx > 4) {
dev_err(dev, "Invalid data in adi,fault-q\n");
return -EINVAL;
}
res |= FIELD_PREP(MAX31827_CONFIGURATION_FLT_Q_MASK, lsb_idx);
} else {
/*
* Set default value.
*/
res |= FIELD_PREP(MAX31827_CONFIGURATION_FLT_Q_MASK,
MAX31827_FLT_Q_1);
}
return regmap_write(st->regmap, MAX31827_CONFIGURATION_REG, res);
}
static const struct hwmon_channel_info *max31827_info[] = {
......@@ -417,7 +480,7 @@ static int max31827_probe(struct i2c_client *client)
if (err)
return dev_err_probe(dev, err, "failed to enable regulator\n");
err = max31827_init_client(st);
err = max31827_init_client(st, dev);
if (err)
return err;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment