aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobert Coulson <rob.coulson@gmail.com>2013-05-09 01:45:53 -0400
committerGuenter Roeck <linux@roeck-us.net>2013-06-27 13:28:59 -0400
commitcd6c8a4297ad036a155966db49982d6807e23ef8 (patch)
treedfdd6d11da901cd8c5d915e5f321e82aa150bc99
parentcd275a5635511922f8b11f8a2a42b6d8b1e88237 (diff)
hwmon: (ds1621) Add ds1721 chip support
Update the ds1621 documentation, driver, and Kconfig with ds1721 chip support. Signed-off-by: Robert Coulson <rob.coulson@gmail.com> Signed-off-by: Guenter Roeck <linux@roeck-us.net>
-rw-r--r--Documentation/hwmon/ds162126
-rw-r--r--drivers/hwmon/Kconfig9
-rw-r--r--drivers/hwmon/ds1621.c120
3 files changed, 132 insertions, 23 deletions
diff --git a/Documentation/hwmon/ds1621 b/Documentation/hwmon/ds1621
index 5e97f333c4df..d66f76f9d85d 100644
--- a/Documentation/hwmon/ds1621
+++ b/Documentation/hwmon/ds1621
@@ -2,16 +2,22 @@ Kernel driver ds1621
2==================== 2====================
3 3
4Supported chips: 4Supported chips:
5 * Dallas Semiconductor DS1621 5 * Dallas Semiconductor / Maxim Integrated DS1621
6 Prefix: 'ds1621' 6 Prefix: 'ds1621'
7 Addresses scanned: I2C 0x48 - 0x4f 7 Addresses scanned: I2C 0x48 - 0x4f
8 Datasheet: Publicly available at the Dallas Semiconductor website 8 Datasheet: Publicly available from www.maximintegrated.com
9 http://www.dalsemi.com/ 9
10 * Dallas Semiconductor DS1625 10 * Dallas Semiconductor DS1625
11 Prefix: 'ds1621' 11 Prefix:
12 'ds1621' - if binding via _detect function
13 'ds1625' - explicit instantiation
14 Addresses scanned: I2C 0x48 - 0x4f
15 Datasheet: Publicly available from www.datasheetarchive.com
16
17 * Maxim Integrated DS1721
18 Prefix: 'ds1721'
12 Addresses scanned: I2C 0x48 - 0x4f 19 Addresses scanned: I2C 0x48 - 0x4f
13 Datasheet: Publicly available at the Dallas Semiconductor website 20 Datasheet: Publicly available from www.maximintegrated.com
14 http://www.dalsemi.com/
15 21
16Authors: 22Authors:
17 Christian W. Zuckschwerdt <zany@triq.net> 23 Christian W. Zuckschwerdt <zany@triq.net>
@@ -61,3 +67,11 @@ with neither of the alarms set.
61 67
62Temperature conversion of the DS1621 takes up to 1000ms; internal access to 68Temperature conversion of the DS1621 takes up to 1000ms; internal access to
63non-volatile registers may last for 10ms or below. 69non-volatile registers may last for 10ms or below.
70
71The DS1625 is pin compatible and functionally equivalent with the DS1621,
72but the DS1621 is meant to replace it.
73
74The 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
76default setting of 75 and 80 degrees respectively, and a maximum conversion
77time of 750ms.
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 0428e8a74b19..0114ed4b3c07 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -348,11 +348,14 @@ config SENSORS_DS620
348 will be called ds620. 348 will be called ds620.
349 349
350config SENSORS_DS1621 350config SENSORS_DS1621
351 tristate "Dallas Semiconductor DS1621 and DS1625" 351 tristate "Dallas Semiconductor DS1621 and compatibles"
352 depends on I2C 352 depends on I2C
353 help 353 help
354 If you say yes here you get support for Dallas Semiconductor 354 If you say yes here you get support for Dallas Semiconductor/Maxim
355 DS1621 and DS1625 sensor chips. 355 Integrated DS1621 sensor chips and compatible models including:
356
357 - Dallas Semiconductor DS1625
358 - Maxim Integrated DS1721
356 359
357 This driver can also be built as a module. If so, the module 360 This driver can also be built as a module. If so, the module
358 will be called ds1621. 361 will be called ds1621.
diff --git a/drivers/hwmon/ds1621.c b/drivers/hwmon/ds1621.c
index 1c568736baff..6942617666a4 100644
--- a/drivers/hwmon/ds1621.c
+++ b/drivers/hwmon/ds1621.c
@@ -6,6 +6,19 @@
6 * Ported to Linux 2.6 by Aurelien Jarno <aurelien@aurel32.net> with 6 * Ported to Linux 2.6 by Aurelien Jarno <aurelien@aurel32.net> with
7 * the help of Jean Delvare <khali@linux-fr.org> 7 * the help of Jean Delvare <khali@linux-fr.org>
8 * 8 *
9 * The DS1621 device is a digital temperature/thermometer with 9-bit
10 * resolution, a thermal alarm output (Tout), and user-defined minimum
11 * and maximum temperature thresholds (TH and TL).
12 *
13 * The DS1625 and DS1721 are pin compatible with the DS1621 and similar
14 * in operation, with slight variations as noted in the device
15 * datasheets (please refer to www.maximintegrated.com for specific
16 * device information).
17 *
18 * Since the DS1621 was the first chipset supported by this driver,
19 * most comments will refer to this chipset, but are actually general
20 * and concern all supported chipsets, unless mentioned otherwise.
21 *
9 * This program is free software; you can redistribute it and/or modify 22 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by 23 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or 24 * the Free Software Foundation; either version 2 of the License, or
@@ -31,27 +44,62 @@
31#include <linux/err.h> 44#include <linux/err.h>
32#include <linux/mutex.h> 45#include <linux/mutex.h>
33#include <linux/sysfs.h> 46#include <linux/sysfs.h>
34#include "lm75.h" 47#include <linux/kernel.h>
35 48
36/* Addresses to scan */ 49/* Addresses to scan */
37static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c, 50static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c,
38 0x4d, 0x4e, 0x4f, I2C_CLIENT_END }; 51 0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
39 52
53/* Supported devices */
54enum chips { ds1621, ds1625, ds1721 };
55
40/* Insmod parameters */ 56/* Insmod parameters */
41static int polarity = -1; 57static int polarity = -1;
42module_param(polarity, int, 0); 58module_param(polarity, int, 0);
43MODULE_PARM_DESC(polarity, "Output's polarity: 0 = active high, 1 = active low"); 59MODULE_PARM_DESC(polarity, "Output's polarity: 0 = active high, 1 = active low");
44 60
45/* Many DS1621 constants specified below */ 61/*
46/* Config register used for detection */ 62 * The Configuration/Status register
47/* 7 6 5 4 3 2 1 0 */ 63 *
48/* |Done|THF |TLF |NVB | X | X |POL |1SHOT| */ 64 * - DS1621:
65 * 7 6 5 4 3 2 1 0
66 * |Done|THF |TLF |NVB | X | X |POL |1SHOT|
67 *
68 * - DS1625:
69 * 7 6 5 4 3 2 1 0
70 * |Done|THF |TLF |NVB | 1 | 0 |POL |1SHOT|
71 *
72 * - DS1721:
73 * 7 6 5 4 3 2 1 0
74 * |Done| X | X | U | R1 | R0 |POL |1SHOT|
75 *
76 * Where:
77 * - 'X' is Reserved
78 * - 'U' is Undefined
79 */
49#define DS1621_REG_CONFIG_NVB 0x10 80#define DS1621_REG_CONFIG_NVB 0x10
81#define DS1621_REG_CONFIG_RESOL 0x0C
50#define DS1621_REG_CONFIG_POLARITY 0x02 82#define DS1621_REG_CONFIG_POLARITY 0x02
51#define DS1621_REG_CONFIG_1SHOT 0x01 83#define DS1621_REG_CONFIG_1SHOT 0x01
52#define DS1621_REG_CONFIG_DONE 0x80 84#define DS1621_REG_CONFIG_DONE 0x80
53 85
54/* The DS1621 registers */ 86#define DS1621_REG_CONFIG_RESOL_SHIFT 2
87
88/* ds1721 conversion rates: {C/LSB, time(ms), resolution bit setting} */
89static const unsigned short ds1721_convrates[] = {
90 94, /* 9-bits (0.5, 93.75, RES[0..1] = 0 */
91 188, /* 10-bits (0.25, 187.5, RES[0..1] = 1 */
92 375, /* 11-bits (0.125, 375, RES[0..1] = 2 */
93 750, /* 12-bits (0.0625, 750, RES[0..1] = 3 */
94};
95
96#define DS1621_CONVERSION_MAX 750
97#define DS1625_CONVERSION_MAX 500
98
99#define DS1621_TEMP_MAX 125000
100#define DS1621_TEMP_MIN (-55000)
101
102/* The DS1621 temperature registers */
55static const u8 DS1621_REG_TEMP[3] = { 103static const u8 DS1621_REG_TEMP[3] = {
56 0xAA, /* input, word, RO */ 104 0xAA, /* input, word, RO */
57 0xA2, /* min, word, RW */ 105 0xA2, /* min, word, RW */
@@ -59,6 +107,7 @@ static const u8 DS1621_REG_TEMP[3] = {
59}; 107};
60#define DS1621_REG_CONF 0xAC /* byte, RW */ 108#define DS1621_REG_CONF 0xAC /* byte, RW */
61#define DS1621_COM_START 0xEE /* no data */ 109#define DS1621_COM_START 0xEE /* no data */
110#define DS1721_COM_START 0x51 /* no data */
62#define DS1621_COM_STOP 0x22 /* no data */ 111#define DS1621_COM_STOP 0x22 /* no data */
63 112
64/* The DS1621 configuration register */ 113/* The DS1621 configuration register */
@@ -75,14 +124,37 @@ struct ds1621_data {
75 struct mutex update_lock; 124 struct mutex update_lock;
76 char valid; /* !=0 if following fields are valid */ 125 char valid; /* !=0 if following fields are valid */
77 unsigned long last_updated; /* In jiffies */ 126 unsigned long last_updated; /* In jiffies */
127 enum chips kind; /* device type */
78 128
79 u16 temp[3]; /* Register values, word */ 129 u16 temp[3]; /* Register values, word */
80 u8 conf; /* Register encoding, combined */ 130 u8 conf; /* Register encoding, combined */
131 u16 update_interval; /* Conversion rate in milliseconds */
81}; 132};
82 133
134static inline int DS1621_TEMP_FROM_REG(u16 reg)
135{
136 return DIV_ROUND_CLOSEST(((s16)reg / 16) * 625, 10);
137}
138
139/*
140 * TEMP: 0.001C/bit (-55C to +125C)
141 * REG:
142 * - 1621, 1625: x = 0.5C
143 * - 1721: x = 0.0625C
144 * Assume highest resolution and let the bits fall where they may..
145 */
146static inline u16 DS1621_TEMP_TO_REG(long temp)
147{
148 int ntemp = clamp_val(temp, DS1621_TEMP_MIN, DS1621_TEMP_MAX);
149 ntemp += (ntemp < 0 ? -31 : 31);
150 ntemp = DIV_ROUND_CLOSEST(ntemp * 10, 625) << 4;
151 return (u16)ntemp;
152}
153
83static void ds1621_init_client(struct i2c_client *client) 154static void ds1621_init_client(struct i2c_client *client)
84{ 155{
85 u8 conf, new_conf; 156 u8 conf, new_conf, sreg, resol;
157 struct ds1621_data *data = i2c_get_clientdata(client);
86 158
87 new_conf = conf = i2c_smbus_read_byte_data(client, DS1621_REG_CONF); 159 new_conf = conf = i2c_smbus_read_byte_data(client, DS1621_REG_CONF);
88 /* switch to continuous conversion mode */ 160 /* switch to continuous conversion mode */
@@ -97,8 +169,25 @@ static void ds1621_init_client(struct i2c_client *client)
97 if (conf != new_conf) 169 if (conf != new_conf)
98 i2c_smbus_write_byte_data(client, DS1621_REG_CONF, new_conf); 170 i2c_smbus_write_byte_data(client, DS1621_REG_CONF, new_conf);
99 171
172 switch (data->kind) {
173 case ds1625:
174 data->update_interval = DS1625_CONVERSION_MAX;
175 sreg = DS1621_COM_START;
176 break;
177 case ds1721:
178 resol = (new_conf & DS1621_REG_CONFIG_RESOL) >>
179 DS1621_REG_CONFIG_RESOL_SHIFT;
180 data->update_interval = ds1721_convrates[resol];
181 sreg = DS1721_COM_START;
182 break;
183 default:
184 data->update_interval = DS1621_CONVERSION_MAX;
185 sreg = DS1621_COM_START;
186 break;
187 }
188
100 /* start conversion */ 189 /* start conversion */
101 i2c_smbus_write_byte(client, DS1621_COM_START); 190 i2c_smbus_write_byte(client, sreg);
102} 191}
103 192
104static struct ds1621_data *ds1621_update_client(struct device *dev) 193static struct ds1621_data *ds1621_update_client(struct device *dev)
@@ -109,8 +198,8 @@ static struct ds1621_data *ds1621_update_client(struct device *dev)
109 198
110 mutex_lock(&data->update_lock); 199 mutex_lock(&data->update_lock);
111 200
112 if (time_after(jiffies, data->last_updated + HZ + HZ / 2) 201 if (time_after(jiffies, data->last_updated + data->update_interval) ||
113 || !data->valid) { 202 !data->valid) {
114 int i; 203 int i;
115 204
116 dev_dbg(&client->dev, "Starting ds1621 update\n"); 205 dev_dbg(&client->dev, "Starting ds1621 update\n");
@@ -146,7 +235,7 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *da,
146 struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 235 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
147 struct ds1621_data *data = ds1621_update_client(dev); 236 struct ds1621_data *data = ds1621_update_client(dev);
148 return sprintf(buf, "%d\n", 237 return sprintf(buf, "%d\n",
149 LM75_TEMP_FROM_REG(data->temp[attr->index])); 238 DS1621_TEMP_FROM_REG(data->temp[attr->index]));
150} 239}
151 240
152static ssize_t set_temp(struct device *dev, struct device_attribute *da, 241static ssize_t set_temp(struct device *dev, struct device_attribute *da,
@@ -163,7 +252,7 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *da,
163 return err; 252 return err;
164 253
165 mutex_lock(&data->update_lock); 254 mutex_lock(&data->update_lock);
166 data->temp[attr->index] = LM75_TEMP_TO_REG(val); 255 data->temp[attr->index] = DS1621_TEMP_TO_REG(val);
167 i2c_smbus_write_word_swapped(client, DS1621_REG_TEMP[attr->index], 256 i2c_smbus_write_word_swapped(client, DS1621_REG_TEMP[attr->index],
168 data->temp[attr->index]); 257 data->temp[attr->index]);
169 mutex_unlock(&data->update_lock); 258 mutex_unlock(&data->update_lock);
@@ -257,6 +346,8 @@ static int ds1621_probe(struct i2c_client *client,
257 i2c_set_clientdata(client, data); 346 i2c_set_clientdata(client, data);
258 mutex_init(&data->update_lock); 347 mutex_init(&data->update_lock);
259 348
349 data->kind = id->driver_data;
350
260 /* Initialize the DS1621 chip */ 351 /* Initialize the DS1621 chip */
261 ds1621_init_client(client); 352 ds1621_init_client(client);
262 353
@@ -289,8 +380,9 @@ static int ds1621_remove(struct i2c_client *client)
289} 380}
290 381
291static const struct i2c_device_id ds1621_id[] = { 382static const struct i2c_device_id ds1621_id[] = {
292 { "ds1621", 0 }, 383 { "ds1621", ds1621 },
293 { "ds1625", 0 }, 384 { "ds1625", ds1625 },
385 { "ds1721", ds1721 },
294 { } 386 { }
295}; 387};
296MODULE_DEVICE_TABLE(i2c, ds1621_id); 388MODULE_DEVICE_TABLE(i2c, ds1621_id);