mirror of
https://github.com/torvalds/linux.git
synced 2024-12-26 12:52:30 +00:00
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: Daniel Matyas <daniel.matyas@analog.com> Link: https://lore.kernel.org/r/20231031182158.124608-5-daniel.matyas@analog.com Signed-off-by: Guenter Roeck <linux@roeck-us.net>
This commit is contained in:
parent
64176bde46
commit
29a9ac6414
@ -90,11 +90,28 @@ the data sheet are:
|
||||
|
||||
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
|
||||
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
|
||||
requested, one-shot is triggered, the device waits for 140 (conversion time) ms,
|
||||
and only after that is the temperature value register read.
|
||||
the resolution.
|
||||
|
||||
The conversion time doubles with every bit of increased resolution. The
|
||||
available resolutions are:
|
||||
|
||||
- 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 temperatures are displayed in milli-degrees. This means, that some data is
|
||||
@ -117,4 +134,4 @@ corresponding status bits.
|
||||
Notes
|
||||
-----
|
||||
|
||||
PEC and resolution are not implemented.
|
||||
PEC is not implemented.
|
||||
|
@ -37,6 +37,9 @@
|
||||
#define MAX31827_FLT_Q_1 0x0
|
||||
#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_16_BIT_TO_M_DGR(x) (sign_extend32(x, 15) * 1000 / 16)
|
||||
@ -65,6 +68,27 @@ static const u16 max31827_conversions[] = {
|
||||
[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 {
|
||||
/*
|
||||
* Prevent simultaneous access to the i2c client.
|
||||
@ -72,6 +96,8 @@ struct max31827_state {
|
||||
struct mutex lock;
|
||||
struct regmap *regmap;
|
||||
bool enable;
|
||||
unsigned int resolution;
|
||||
unsigned int update_interval;
|
||||
};
|
||||
|
||||
static const struct regmap_config max31827_regmap = {
|
||||
@ -88,9 +114,9 @@ static int shutdown_write(struct max31827_state *st, unsigned int reg,
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Before the Temperature Threshold Alarm and Alarm Hysteresis Threshold
|
||||
* register values are changed over I2C, the part must be in shutdown
|
||||
* mode.
|
||||
* Before the Temperature Threshold Alarm, Alarm Hysteresis Threshold
|
||||
* and Resolution bits from Configuration register are changed over I2C,
|
||||
* the part must be in shutdown mode.
|
||||
*
|
||||
* Mutex is used to ensure, that some other process doesn't change the
|
||||
* configuration register.
|
||||
@ -208,9 +234,18 @@ static int max31827_read(struct device *dev, enum hwmon_sensor_types type,
|
||||
mutex_unlock(&st->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
msleep(MAX31827_12_BIT_CNV_TIME);
|
||||
msleep(max31827_conv_times[st->resolution]);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
||||
mutex_unlock(&st->lock);
|
||||
@ -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);
|
||||
|
||||
return regmap_update_bits(st->regmap,
|
||||
MAX31827_CONFIGURATION_REG,
|
||||
MAX31827_CONFIGURATION_CNV_RATE_MASK,
|
||||
res);
|
||||
ret = regmap_update_bits(st->regmap,
|
||||
MAX31827_CONFIGURATION_REG,
|
||||
MAX31827_CONFIGURATION_CNV_RATE_MASK,
|
||||
res);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
st->update_interval = val;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -378,9 +417,70 @@ static int max31827_write(struct device *dev, enum hwmon_sensor_types type,
|
||||
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[] = {
|
||||
{ "max31827", max31827 },
|
||||
{ "max31828", max31828 },
|
||||
@ -529,7 +629,7 @@ static int max31827_probe(struct i2c_client *client)
|
||||
|
||||
hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, st,
|
||||
&max31827_chip_info,
|
||||
NULL);
|
||||
max31827_groups);
|
||||
|
||||
return PTR_ERR_OR_ZERO(hwmon_dev);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user