aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobert Coulson <rob.coulson@gmail.com>2013-05-09 01:45:54 -0400
committerGuenter Roeck <linux@roeck-us.net>2013-06-27 13:29:01 -0400
commit3a8fe3315571e896489d2e271ffe7f935bfc5ce8 (patch)
treec97f18dc6b5326d0dfee71bac65d318d994896f8
parentcd6c8a4297ad036a155966db49982d6807e23ef8 (diff)
hwmon: (ds1621) Add ds1721 update interval sysfs attribute
The ds1721 device can be configured for 9..12 bit resolutions; add a sysfs attribute for userspace to configure this attribute. The definition, description, details, and usage are shown in the documentation and were crafted from an LM73 driver patch done by Chris Verges & Guenter Roeck). Signed-off-by: Robert Coulson <rob.coulson@gmail.com> Signed-off-by: Guenter Roeck <linux@roeck-us.net>
-rw-r--r--Documentation/hwmon/ds162165
-rw-r--r--drivers/hwmon/ds1621.c56
2 files changed, 121 insertions, 0 deletions
diff --git a/Documentation/hwmon/ds1621 b/Documentation/hwmon/ds1621
index d66f76f9d85d..b61e77c6b1cb 100644
--- a/Documentation/hwmon/ds1621
+++ b/Documentation/hwmon/ds1621
@@ -75,3 +75,68 @@ The DS1721 is pin compatible with the DS1621, has an accuracy of +/- 1.0
75degree Celsius over a -10 to +85 degree range, a minimum/maximum alarm 75degree Celsius over a -10 to +85 degree range, a minimum/maximum alarm
76default setting of 75 and 80 degrees respectively, and a maximum conversion 76default setting of 75 and 80 degrees respectively, and a maximum conversion
77time of 750ms. 77time of 750ms.
78
79In addition, the DS1721 supports four resolution settings from 9 to 12 bits
80(defined in degrees C per LSB: 0.5, 0.25, 0.125, and 0.0625, respectifully),
81that are set at device power on to the highest resolution: 12-bits (0.0625 degree C).
82
83Changing the DS1721 resolution mode affects the conversion time and can be
84done from userspace, via the device 'update_interval' sysfs attribute. This
85attribute will normalize range of input values to the device maximum resolution
86values defined in the datasheet as such:
87
88Resolution Conversion Time Input Range
89 (C/LSB) (msec) (msec)
90--------------------------------------------
910.5 93.75 0....94
920.25 187.5 95...187
930.125 375 188..375
940.0625 750 376..infinity
95--------------------------------------
96
97The following examples show how the 'update_interval' attribute can be
98used to change the conversion time:
99
100$ cat update_interval
101750
102$ cat temp1_input
10322062
104$
105$ echo 300 > update_interval
106$ cat update_interval
107375
108$ cat temp1_input
10922125
110$
111$ echo 150 > update_interval
112$ cat update_interval
113188
114$ cat temp1_input
11522250
116$
117$ echo 1 > update_interval
118$ cat update_interval
11994
120$ cat temp1_input
12122000
122$
123$ echo 1000 > update_interval
124$ cat update_interval
125750
126$ cat temp1_input
12722062
128$
129
130As shown, the ds1621 driver automatically adjusts the 'update_interval'
131user input, via a step function. Reading back the 'update_interval' value
132after a write operation provides the conversion time used by the device.
133
134Mathematically, the resolution can be derived from the conversion time
135via the following function:
136
137 g(x) = 0.5 * [minimum_conversion_time/x]
138
139where:
140 -> 'x' = the output from 'update_interval'
141 -> 'g(x)' = the resolution in degrees C per LSB.
142 -> 93.75ms = minimum conversion time
diff --git a/drivers/hwmon/ds1621.c b/drivers/hwmon/ds1621.c
index 6942617666a4..b5d80fb851d0 100644
--- a/drivers/hwmon/ds1621.c
+++ b/drivers/hwmon/ds1621.c
@@ -274,7 +274,47 @@ static ssize_t show_alarm(struct device *dev, struct device_attribute *da,
274 return sprintf(buf, "%d\n", !!(data->conf & attr->index)); 274 return sprintf(buf, "%d\n", !!(data->conf & attr->index));
275} 275}
276 276
277static ssize_t show_convrate(struct device *dev, struct device_attribute *da,
278 char *buf)
279{
280 struct i2c_client *client = to_i2c_client(dev);
281 struct ds1621_data *data = i2c_get_clientdata(client);
282 return scnprintf(buf, PAGE_SIZE, "%hu\n", data->update_interval);
283}
284
285static ssize_t set_convrate(struct device *dev, struct device_attribute *da,
286 const char *buf, size_t count)
287{
288 struct i2c_client *client = to_i2c_client(dev);
289 struct ds1621_data *data = i2c_get_clientdata(client);
290 unsigned long convrate;
291 s32 err;
292 int resol = 0;
293
294 err = kstrtoul(buf, 10, &convrate);
295 if (err)
296 return err;
297
298 /* Convert rate into resolution bits */
299 while (resol < (ARRAY_SIZE(ds1721_convrates) - 1) &&
300 convrate > ds1721_convrates[resol])
301 resol++;
302
303 mutex_lock(&data->update_lock);
304 data->conf = i2c_smbus_read_byte_data(client, DS1621_REG_CONF);
305 data->conf &= ~DS1621_REG_CONFIG_RESOL;
306 data->conf |= (resol << DS1621_REG_CONFIG_RESOL_SHIFT);
307 i2c_smbus_write_byte_data(client, DS1621_REG_CONF, data->conf);
308 data->update_interval = ds1721_convrates[resol];
309 mutex_unlock(&data->update_lock);
310
311 return count;
312}
313
277static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); 314static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
315static DEVICE_ATTR(update_interval, S_IWUSR | S_IRUGO, show_convrate,
316 set_convrate);
317
278static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); 318static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
279static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp, set_temp, 1); 319static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp, set_temp, 1);
280static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp, set_temp, 2); 320static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp, set_temp, 2);
@@ -290,11 +330,27 @@ static struct attribute *ds1621_attributes[] = {
290 &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, 330 &sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
291 &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, 331 &sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
292 &dev_attr_alarms.attr, 332 &dev_attr_alarms.attr,
333 &dev_attr_update_interval.attr,
293 NULL 334 NULL
294}; 335};
295 336
337static umode_t ds1621_attribute_visible(struct kobject *kobj,
338 struct attribute *attr, int index)
339{
340 struct device *dev = container_of(kobj, struct device, kobj);
341 struct i2c_client *client = to_i2c_client(dev);
342 struct ds1621_data *data = i2c_get_clientdata(client);
343
344 if (attr == &dev_attr_update_interval.attr)
345 if (data->kind != ds1721)
346 /* shhh, we're hiding update_interval */
347 return 0;
348 return attr->mode;
349}
350
296static const struct attribute_group ds1621_group = { 351static const struct attribute_group ds1621_group = {
297 .attrs = ds1621_attributes, 352 .attrs = ds1621_attributes,
353 .is_visible = ds1621_attribute_visible
298}; 354};
299 355
300 356