From 8a5c5cc61748642a1276ef94611e21a60f0796ab Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sat, 4 May 2013 14:49:36 +0200 Subject: hwmon: (lm75) Per-chip configuration register initialization There is no standard for the configuration register bits of LM75-like chips. We shouldn't blindly clear bits setting the resolution as they are either unused or used for something else on some of the supported chips. So, switch to per-chip configuration initialization. This will allow for better tuning later, for example using more resolution bits when available. Signed-off-by: Jean Delvare Acked-by: Guenter Roeck --- drivers/hwmon/lm75.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c index 291edff..4670fbe 100644 --- a/drivers/hwmon/lm75.c +++ b/drivers/hwmon/lm75.c @@ -167,8 +167,28 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id) * Then tweak to be more precise when appropriate. */ set_mask = 0; - clr_mask = (1 << 0) /* continuous conversions */ - | (1 << 6) | (1 << 5); /* 9-bit mode */ + clr_mask = LM75_SHUTDOWN; /* continuous conversions */ + + switch (id->driver_data) { + case adt75: + clr_mask |= 1 << 5; /* not one-shot mode */ + break; + case ds1775: + case ds75: + case stds75: + clr_mask |= 3 << 5; /* 9-bit mode */ + break; + case mcp980x: + case tmp100: + case tmp101: + case tmp105: + case tmp175: + case tmp275: + case tmp75: + clr_mask |= 3 << 5; /* 9-bit mode */ + clr_mask |= 1 << 7; /* not one-shot mode */ + break; + } /* configure as specified */ status = lm75_read_value(client, LM75_REG_CONF); -- cgit v1.1 From 87d0621ae2bdf2e2c60aadbbcb8b6c680777c1bf Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sat, 4 May 2013 14:49:36 +0200 Subject: hwmon: (lm75) Prepare to support per-chip resolution and sample time Prepare the lm75 driver to support per-chip resolution and sample time. For now we only make the code generic enough to support it, but we still use the same, unchanged resolution (9-bit) and sample time (1.5 s) for all chips. Signed-off-by: Jean Delvare Acked-by: Guenter Roeck --- drivers/hwmon/lm75.c | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c index 4670fbe..559e675 100644 --- a/drivers/hwmon/lm75.c +++ b/drivers/hwmon/lm75.c @@ -71,9 +71,12 @@ struct lm75_data { struct device *hwmon_dev; struct mutex update_lock; u8 orig_conf; + u8 resolution; /* In bits, between 9 and 12 */ + u8 resolution_limits; char valid; /* !=0 if registers are valid */ unsigned long last_updated; /* In jiffies */ - u16 temp[3]; /* Register values, + unsigned long sample_time; /* In jiffies */ + s16 temp[3]; /* Register values, 0 = input 1 = max 2 = hyst */ @@ -93,12 +96,15 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *da, { struct sensor_device_attribute *attr = to_sensor_dev_attr(da); struct lm75_data *data = lm75_update_device(dev); + long temp; if (IS_ERR(data)) return PTR_ERR(data); - return sprintf(buf, "%d\n", - LM75_TEMP_FROM_REG(data->temp[attr->index])); + temp = ((data->temp[attr->index] >> (16 - data->resolution)) * 1000) + >> (data->resolution - 8); + + return sprintf(buf, "%ld\n", temp); } static ssize_t set_temp(struct device *dev, struct device_attribute *da, @@ -110,13 +116,25 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *da, int nr = attr->index; long temp; int error; + u8 resolution; error = kstrtol(buf, 10, &temp); if (error) return error; + /* + * Resolution of limit registers is assumed to be the same as the + * temperature input register resolution unless given explicitly. + */ + if (attr->index && data->resolution_limits) + resolution = data->resolution_limits; + else + resolution = data->resolution; + mutex_lock(&data->update_lock); - data->temp[nr] = LM75_TEMP_TO_REG(temp); + temp = clamp_val(temp, LM75_TEMP_MIN, LM75_TEMP_MAX); + data->temp[nr] = DIV_ROUND_CLOSEST(temp << (resolution - 8), + 1000) << (16 - resolution); lm75_write_value(client, LM75_REG_TEMP[nr], data->temp[nr]); mutex_unlock(&data->update_lock); return count; @@ -190,6 +208,9 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id) break; } + data->resolution = 9; + data->sample_time = HZ + HZ / 2; + /* configure as specified */ status = lm75_read_value(client, LM75_REG_CONF); if (status < 0) { @@ -427,7 +448,7 @@ static struct lm75_data *lm75_update_device(struct device *dev) mutex_lock(&data->update_lock); - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + if (time_after(jiffies, data->last_updated + data->sample_time) || !data->valid) { int i; dev_dbg(&client->dev, "Starting lm75 update\n"); -- cgit v1.1 From 0cd2c72d765191f24d7be14366c0413bf139f3e3 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sat, 4 May 2013 14:49:36 +0200 Subject: hwmon: (lm75) Tune resolution and sample time per chip Most LM75-compatible chips can either sample much faster or with a much better resolution than the original LM75 chip. So far the lm75 driver did not let the user take benefit of these improvements. Do it now. I decided to almost always configure the chip to use the best resolution possible, which also means the longest sample time. The only chips for which I didn't are the DS75, DS1775 and STDS75, because they are really too slow in 12-bit mode (1.2 to 1.5 second worst case) so I went for 11-bit mode as a more reasonable tradeoff. This choice is dictated by the fact that the hwmon subsystem is meant for system monitoring, it has never been supposed to be ultra-fast, and as a matter of fact we do cache the sampled values in almost all drivers. If anyone isn't pleased with these default settings, they can always introduce a platform data structure or DT support for the lm75. That being said, it seems nobody ever complained that the driver wouldn't refresh the value faster than every 1.5 second, and the change made it faster for all chips even in 12-bit mode, so I don't expect any complaint. Signed-off-by: Jean Delvare Acked-by: Guenter Roeck --- drivers/hwmon/lm75.c | 42 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 6 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c index 559e675..9283411 100644 --- a/drivers/hwmon/lm75.c +++ b/drivers/hwmon/lm75.c @@ -169,6 +169,7 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id) int status; u8 set_mask, clr_mask; int new; + enum lm75_type kind = id->driver_data; if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) @@ -187,30 +188,59 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id) set_mask = 0; clr_mask = LM75_SHUTDOWN; /* continuous conversions */ - switch (id->driver_data) { + switch (kind) { case adt75: clr_mask |= 1 << 5; /* not one-shot mode */ + data->resolution = 12; + data->sample_time = HZ / 8; break; case ds1775: case ds75: case stds75: - clr_mask |= 3 << 5; /* 9-bit mode */ + clr_mask |= 3 << 5; + set_mask |= 2 << 5; /* 11-bit mode */ + data->resolution = 11; + data->sample_time = HZ; + break; + case lm75: + case lm75a: + data->resolution = 9; + data->sample_time = HZ / 2; + break; + case max6625: + data->resolution = 9; + data->sample_time = HZ / 4; + break; + case max6626: + data->resolution = 12; + data->resolution_limits = 9; + data->sample_time = HZ / 4; + break; + case tcn75: + data->resolution = 9; + data->sample_time = HZ / 8; break; case mcp980x: + data->resolution_limits = 9; + /* fall through */ case tmp100: case tmp101: + set_mask |= 3 << 5; /* 12-bit mode */ + data->resolution = 12; + data->sample_time = HZ; + clr_mask |= 1 << 7; /* not one-shot mode */ + break; case tmp105: case tmp175: case tmp275: case tmp75: - clr_mask |= 3 << 5; /* 9-bit mode */ + set_mask |= 3 << 5; /* 12-bit mode */ clr_mask |= 1 << 7; /* not one-shot mode */ + data->resolution = 12; + data->sample_time = HZ / 2; break; } - data->resolution = 9; - data->sample_time = HZ + HZ / 2; - /* configure as specified */ status = lm75_read_value(client, LM75_REG_CONF); if (status < 0) { -- cgit v1.1 From 3fbc81e3c0257c756c0955bcb291374d74c11f61 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sat, 4 May 2013 14:49:36 +0200 Subject: hwmon: (lm75) Add support for the Dallas/Maxim DS7505 Basically it's the same as the original DS75 but much faster. Signed-off-by: Jean Delvare Acked-by: Guenter Roeck --- drivers/hwmon/Kconfig | 2 +- drivers/hwmon/lm75.c | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 9c333d4..0428e8a 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -630,7 +630,7 @@ config SENSORS_LM75 temperature sensor chip, with models including: - Analog Devices ADT75 - - Dallas Semiconductor DS75 and DS1775 + - Dallas Semiconductor DS75, DS1775 and DS7505 - Maxim MAX6625 and MAX6626 - Microchip MCP980x - National Semiconductor LM75, LM75A diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c index 9283411..c03b490 100644 --- a/drivers/hwmon/lm75.c +++ b/drivers/hwmon/lm75.c @@ -38,6 +38,7 @@ enum lm75_type { /* keep sorted in alphabetical order */ adt75, ds1775, ds75, + ds7505, lm75, lm75a, max6625, @@ -202,6 +203,11 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id) data->resolution = 11; data->sample_time = HZ; break; + case ds7505: + set_mask |= 3 << 5; /* 12-bit mode */ + data->resolution = 12; + data->sample_time = HZ / 4; + break; case lm75: case lm75a: data->resolution = 9; @@ -289,6 +295,7 @@ static const struct i2c_device_id lm75_ids[] = { { "adt75", adt75, }, { "ds1775", ds1775, }, { "ds75", ds75, }, + { "ds7505", ds7505, }, { "lm75", lm75, }, { "lm75a", lm75a, }, { "max6625", max6625, }, -- cgit v1.1