Commit 29a9ac64 authored by Daniel Matyas's avatar Daniel Matyas Committed by Guenter Roeck

hwmon: (max31827) Add custom attribute for resolution

Added custom channel-specific (temp1) attribute for resolution. The wait
time for a conversion in one-shot mode (enable = 0) depends on the
resolution.

When resolution is 12-bit, the conversion time is 140ms, but the minimum
update_interval is 125ms. Handled this problem by waiting an additional
15ms (125ms + 15ms = 140ms).

Added 'mask' parameter to the shutdown_write() function. Now it can
either write or update bits, depending on the value of mask. This is
needed, because for alarms a write is necessary, but for resolution only
the resolution bits should be updated.
Signed-off-by: default avatarDaniel Matyas <daniel.matyas@analog.com>
Link: https://lore.kernel.org/r/20231031182158.124608-5-daniel.matyas@analog.comSigned-off-by: default avatarGuenter Roeck <linux@roeck-us.net>
parent 64176bde
...@@ -90,11 +90,28 @@ the data sheet are: ...@@ -90,11 +90,28 @@ the data sheet are:
Enabling the device when it is already enabled has the side effect of setting 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 conversion frequency to 1 conv/s. The conversion time varies depending on
the resolution. The conversion time doubles with every bit of increased the resolution.
resolution. For 10 bit resolution 35ms are needed, while for 12 bit resolution
(default) 140ms. When chip is in shutdown mode and a read operation is The conversion time doubles with every bit of increased resolution. The
requested, one-shot is triggered, the device waits for 140 (conversion time) ms, available resolutions are:
and only after that is the temperature value register read.
- 8 bit -> 8.75 ms conversion time
- 9 bit -> 17.5 ms conversion time
- 10 bit -> 35 ms conversion time
- 12 bit (default) -> 140 ms conversion time
There is a temp1_resolution attribute which indicates the unit change in the
input temperature in milli-degrees C.
- 1000 mC -> 8 bit
- 500 mC -> 9 bit
- 250 mC -> 10 bit
- 62 mC -> 12 bit (default) - actually this is 62.5, but the fil returns 62
When chip is in shutdown mode and a read operation is requested, one-shot is
triggered, the device waits for <conversion time> ms, and only after that is
the temperature value register read. Note that the conversion times are rounded
up to the nearest possible integer.
The LSB of the temperature values is 0.0625 degrees Celsius, but the values of The LSB of the temperature values is 0.0625 degrees Celsius, but the values of
the temperatures are displayed in milli-degrees. This means, that some data is the temperatures are displayed in milli-degrees. This means, that some data is
...@@ -117,4 +134,4 @@ corresponding status bits. ...@@ -117,4 +134,4 @@ corresponding status bits.
Notes Notes
----- -----
PEC and resolution are not implemented. PEC is not implemented.
...@@ -37,6 +37,9 @@ ...@@ -37,6 +37,9 @@
#define MAX31827_FLT_Q_1 0x0 #define MAX31827_FLT_Q_1 0x0
#define MAX31827_FLT_Q_4 0x2 #define MAX31827_FLT_Q_4 0x2
#define MAX31827_8_BIT_CNV_TIME 9
#define MAX31827_9_BIT_CNV_TIME 18
#define MAX31827_10_BIT_CNV_TIME 35
#define MAX31827_12_BIT_CNV_TIME 140 #define MAX31827_12_BIT_CNV_TIME 140
#define MAX31827_16_BIT_TO_M_DGR(x) (sign_extend32(x, 15) * 1000 / 16) #define MAX31827_16_BIT_TO_M_DGR(x) (sign_extend32(x, 15) * 1000 / 16)
...@@ -65,6 +68,27 @@ static const u16 max31827_conversions[] = { ...@@ -65,6 +68,27 @@ static const u16 max31827_conversions[] = {
[MAX31827_CNV_8_HZ] = 125, [MAX31827_CNV_8_HZ] = 125,
}; };
enum max31827_resolution {
MAX31827_RES_8_BIT = 0,
MAX31827_RES_9_BIT,
MAX31827_RES_10_BIT,
MAX31827_RES_12_BIT,
};
static const u16 max31827_resolutions[] = {
[MAX31827_RES_8_BIT] = 1000,
[MAX31827_RES_9_BIT] = 500,
[MAX31827_RES_10_BIT] = 250,
[MAX31827_RES_12_BIT] = 62,
};
static const u16 max31827_conv_times[] = {
[MAX31827_RES_8_BIT] = MAX31827_8_BIT_CNV_TIME,
[MAX31827_RES_9_BIT] = MAX31827_9_BIT_CNV_TIME,
[MAX31827_RES_10_BIT] = MAX31827_10_BIT_CNV_TIME,
[MAX31827_RES_12_BIT] = MAX31827_12_BIT_CNV_TIME,
};
struct max31827_state { struct max31827_state {
/* /*
* Prevent simultaneous access to the i2c client. * Prevent simultaneous access to the i2c client.
...@@ -72,6 +96,8 @@ struct max31827_state { ...@@ -72,6 +96,8 @@ struct max31827_state {
struct mutex lock; struct mutex lock;
struct regmap *regmap; struct regmap *regmap;
bool enable; bool enable;
unsigned int resolution;
unsigned int update_interval;
}; };
static const struct regmap_config max31827_regmap = { static const struct regmap_config max31827_regmap = {
...@@ -88,9 +114,9 @@ static int shutdown_write(struct max31827_state *st, unsigned int reg, ...@@ -88,9 +114,9 @@ static int shutdown_write(struct max31827_state *st, unsigned int reg,
int ret; int ret;
/* /*
* Before the Temperature Threshold Alarm and Alarm Hysteresis Threshold * Before the Temperature Threshold Alarm, Alarm Hysteresis Threshold
* register values are changed over I2C, the part must be in shutdown * and Resolution bits from Configuration register are changed over I2C,
* mode. * the part must be in shutdown mode.
* *
* Mutex is used to ensure, that some other process doesn't change the * Mutex is used to ensure, that some other process doesn't change the
* configuration register. * configuration register.
...@@ -208,9 +234,18 @@ static int max31827_read(struct device *dev, enum hwmon_sensor_types type, ...@@ -208,9 +234,18 @@ static int max31827_read(struct device *dev, enum hwmon_sensor_types type,
mutex_unlock(&st->lock); mutex_unlock(&st->lock);
return ret; return ret;
} }
msleep(max31827_conv_times[st->resolution]);
msleep(MAX31827_12_BIT_CNV_TIME);
} }
/*
* For 12-bit resolution the conversion time is 140 ms,
* thus an additional 15 ms is needed to complete the
* conversion: 125 ms + 15 ms = 140 ms
*/
if (max31827_resolutions[st->resolution] == 12 &&
st->update_interval == 125)
usleep_range(15000, 20000);
ret = regmap_read(st->regmap, MAX31827_T_REG, &uval); ret = regmap_read(st->regmap, MAX31827_T_REG, &uval);
mutex_unlock(&st->lock); mutex_unlock(&st->lock);
...@@ -367,10 +402,14 @@ static int max31827_write(struct device *dev, enum hwmon_sensor_types type, ...@@ -367,10 +402,14 @@ static int max31827_write(struct device *dev, enum hwmon_sensor_types type,
res = FIELD_PREP(MAX31827_CONFIGURATION_CNV_RATE_MASK, res = FIELD_PREP(MAX31827_CONFIGURATION_CNV_RATE_MASK,
res); res);
return regmap_update_bits(st->regmap, ret = regmap_update_bits(st->regmap,
MAX31827_CONFIGURATION_REG, MAX31827_CONFIGURATION_REG,
MAX31827_CONFIGURATION_CNV_RATE_MASK, MAX31827_CONFIGURATION_CNV_RATE_MASK,
res); res);
if (ret)
return ret;
st->update_interval = val;
} }
break; break;
...@@ -378,9 +417,70 @@ static int max31827_write(struct device *dev, enum hwmon_sensor_types type, ...@@ -378,9 +417,70 @@ static int max31827_write(struct device *dev, enum hwmon_sensor_types type,
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
return -EOPNOTSUPP; return 0;
}
static ssize_t temp1_resolution_show(struct device *dev,
struct device_attribute *devattr,
char *buf)
{
struct max31827_state *st = dev_get_drvdata(dev);
unsigned int val;
int ret;
ret = regmap_read(st->regmap, MAX31827_CONFIGURATION_REG, &val);
if (ret)
return ret;
val = FIELD_GET(MAX31827_CONFIGURATION_RESOLUTION_MASK, val);
return scnprintf(buf, PAGE_SIZE, "%u\n", max31827_resolutions[val]);
}
static ssize_t temp1_resolution_store(struct device *dev,
struct device_attribute *devattr,
const char *buf, size_t count)
{
struct max31827_state *st = dev_get_drvdata(dev);
unsigned int idx = 0;
unsigned int val;
int ret;
ret = kstrtouint(buf, 10, &val);
if (ret)
return ret;
/*
* Convert the desired resolution into register
* bits. idx is already initialized with 0.
*
* This was inspired by lm73 driver.
*/
while (idx < ARRAY_SIZE(max31827_resolutions) &&
val < max31827_resolutions[idx])
idx++;
if (idx == ARRAY_SIZE(max31827_resolutions))
idx = ARRAY_SIZE(max31827_resolutions) - 1;
st->resolution = idx;
ret = shutdown_write(st, MAX31827_CONFIGURATION_REG,
MAX31827_CONFIGURATION_RESOLUTION_MASK,
FIELD_PREP(MAX31827_CONFIGURATION_RESOLUTION_MASK,
idx));
return ret ? ret : count;
} }
static DEVICE_ATTR_RW(temp1_resolution);
static struct attribute *max31827_attrs[] = {
&dev_attr_temp1_resolution.attr,
NULL
};
ATTRIBUTE_GROUPS(max31827);
static const struct i2c_device_id max31827_i2c_ids[] = { static const struct i2c_device_id max31827_i2c_ids[] = {
{ "max31827", max31827 }, { "max31827", max31827 },
{ "max31828", max31828 }, { "max31828", max31828 },
...@@ -529,7 +629,7 @@ static int max31827_probe(struct i2c_client *client) ...@@ -529,7 +629,7 @@ static int max31827_probe(struct i2c_client *client)
hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, st, hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, st,
&max31827_chip_info, &max31827_chip_info,
NULL); max31827_groups);
return PTR_ERR_OR_ZERO(hwmon_dev); return PTR_ERR_OR_ZERO(hwmon_dev);
} }
......
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