diff options
author | Peter A. Bigot <pab@pabigot.com> | 2016-12-24 08:22:44 -0500 |
---|---|---|
committer | Guenter Roeck <linux@roeck-us.net> | 2017-01-02 13:19:45 -0500 |
commit | 53e678d75e7c22b251c6981ff8364b5c42c5eac4 (patch) | |
tree | 2886d135b167d53686c839802d655b5a312cce25 | |
parent | 5343aed12f262c87372c4f20b744756837240dc9 (diff) |
hwmon: (sht21) Add Electronic Identification Code retrieval
Expose the per-chip unique identifier so it can be used to identify the
sensor producing the measurements.
Signed-off-by: Peter A. Bigot <pab@pabigot.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
-rw-r--r-- | Documentation/hwmon/sht21 | 5 | ||||
-rw-r--r-- | drivers/hwmon/sht21.c | 92 |
2 files changed, 93 insertions, 4 deletions
diff --git a/Documentation/hwmon/sht21 b/Documentation/hwmon/sht21 index db17fda45c3e..47f4765db256 100644 --- a/Documentation/hwmon/sht21 +++ b/Documentation/hwmon/sht21 | |||
@@ -35,6 +35,7 @@ sysfs-Interface | |||
35 | 35 | ||
36 | temp1_input - temperature input | 36 | temp1_input - temperature input |
37 | humidity1_input - humidity input | 37 | humidity1_input - humidity input |
38 | eic - Electronic Identification Code | ||
38 | 39 | ||
39 | Notes | 40 | Notes |
40 | ----- | 41 | ----- |
@@ -45,5 +46,5 @@ humidity and 66 ms for temperature. To keep self heating below 0.1 degree | |||
45 | Celsius, the device should not be active for more than 10% of the time, | 46 | Celsius, the device should not be active for more than 10% of the time, |
46 | e.g. maximum two measurements per second at the given resolution. | 47 | e.g. maximum two measurements per second at the given resolution. |
47 | 48 | ||
48 | Different resolutions, the on-chip heater, using the CRC checksum and reading | 49 | Different resolutions, the on-chip heater, and using the CRC checksum |
49 | the serial number are not supported yet. | 50 | are not supported yet. |
diff --git a/drivers/hwmon/sht21.c b/drivers/hwmon/sht21.c index 84cdb1cf0fb4..06706d288355 100644 --- a/drivers/hwmon/sht21.c +++ b/drivers/hwmon/sht21.c | |||
@@ -34,23 +34,29 @@ | |||
34 | /* I2C command bytes */ | 34 | /* I2C command bytes */ |
35 | #define SHT21_TRIG_T_MEASUREMENT_HM 0xe3 | 35 | #define SHT21_TRIG_T_MEASUREMENT_HM 0xe3 |
36 | #define SHT21_TRIG_RH_MEASUREMENT_HM 0xe5 | 36 | #define SHT21_TRIG_RH_MEASUREMENT_HM 0xe5 |
37 | #define SHT21_READ_SNB_CMD1 0xFA | ||
38 | #define SHT21_READ_SNB_CMD2 0x0F | ||
39 | #define SHT21_READ_SNAC_CMD1 0xFC | ||
40 | #define SHT21_READ_SNAC_CMD2 0xC9 | ||
37 | 41 | ||
38 | /** | 42 | /** |
39 | * struct sht21 - SHT21 device specific data | 43 | * struct sht21 - SHT21 device specific data |
40 | * @hwmon_dev: device registered with hwmon | 44 | * @hwmon_dev: device registered with hwmon |
41 | * @lock: mutex to protect measurement values | 45 | * @lock: mutex to protect measurement values |
42 | * @valid: only 0 before first measurement is taken | ||
43 | * @last_update: time of last update (jiffies) | 46 | * @last_update: time of last update (jiffies) |
44 | * @temperature: cached temperature measurement value | 47 | * @temperature: cached temperature measurement value |
45 | * @humidity: cached humidity measurement value | 48 | * @humidity: cached humidity measurement value |
49 | * @valid: only 0 before first measurement is taken | ||
50 | * @eic: cached electronic identification code text | ||
46 | */ | 51 | */ |
47 | struct sht21 { | 52 | struct sht21 { |
48 | struct i2c_client *client; | 53 | struct i2c_client *client; |
49 | struct mutex lock; | 54 | struct mutex lock; |
50 | char valid; | ||
51 | unsigned long last_update; | 55 | unsigned long last_update; |
52 | int temperature; | 56 | int temperature; |
53 | int humidity; | 57 | int humidity; |
58 | char valid; | ||
59 | char eic[18]; | ||
54 | }; | 60 | }; |
55 | 61 | ||
56 | /** | 62 | /** |
@@ -165,15 +171,97 @@ static ssize_t sht21_show_humidity(struct device *dev, | |||
165 | return sprintf(buf, "%d\n", sht21->humidity); | 171 | return sprintf(buf, "%d\n", sht21->humidity); |
166 | } | 172 | } |
167 | 173 | ||
174 | static ssize_t eic_read(struct sht21 *sht21) | ||
175 | { | ||
176 | struct i2c_client *client = sht21->client; | ||
177 | u8 tx[2]; | ||
178 | u8 rx[8]; | ||
179 | u8 eic[8]; | ||
180 | struct i2c_msg msgs[2] = { | ||
181 | { | ||
182 | .addr = client->addr, | ||
183 | .flags = 0, | ||
184 | .len = 2, | ||
185 | .buf = tx, | ||
186 | }, | ||
187 | { | ||
188 | .addr = client->addr, | ||
189 | .flags = I2C_M_RD, | ||
190 | .len = 8, | ||
191 | .buf = rx, | ||
192 | }, | ||
193 | }; | ||
194 | int ret; | ||
195 | |||
196 | tx[0] = SHT21_READ_SNB_CMD1; | ||
197 | tx[1] = SHT21_READ_SNB_CMD2; | ||
198 | ret = i2c_transfer(client->adapter, msgs, 2); | ||
199 | if (ret < 0) | ||
200 | goto out; | ||
201 | eic[2] = rx[0]; | ||
202 | eic[3] = rx[2]; | ||
203 | eic[4] = rx[4]; | ||
204 | eic[5] = rx[6]; | ||
205 | |||
206 | tx[0] = SHT21_READ_SNAC_CMD1; | ||
207 | tx[1] = SHT21_READ_SNAC_CMD2; | ||
208 | msgs[1].len = 6; | ||
209 | ret = i2c_transfer(client->adapter, msgs, 2); | ||
210 | if (ret < 0) | ||
211 | goto out; | ||
212 | eic[0] = rx[3]; | ||
213 | eic[1] = rx[4]; | ||
214 | eic[6] = rx[0]; | ||
215 | eic[7] = rx[1]; | ||
216 | |||
217 | ret = snprintf(sht21->eic, sizeof(sht21->eic), | ||
218 | "%02x%02x%02x%02x%02x%02x%02x%02x\n", | ||
219 | eic[0], eic[1], eic[2], eic[3], | ||
220 | eic[4], eic[5], eic[6], eic[7]); | ||
221 | out: | ||
222 | if (ret < 0) | ||
223 | sht21->eic[0] = 0; | ||
224 | |||
225 | return ret; | ||
226 | } | ||
227 | |||
228 | /** | ||
229 | * eic_show() - show Electronic Identification Code in sysfs | ||
230 | * @dev: device | ||
231 | * @attr: device attribute | ||
232 | * @buf: sysfs buffer (PAGE_SIZE) where EIC is written | ||
233 | * | ||
234 | * Will be called on read access to eic sysfs attribute. | ||
235 | * Returns number of bytes written into buffer, negative errno on error. | ||
236 | */ | ||
237 | static ssize_t eic_show(struct device *dev, | ||
238 | struct device_attribute *attr, | ||
239 | char *buf) | ||
240 | { | ||
241 | struct sht21 *sht21 = dev_get_drvdata(dev); | ||
242 | int ret; | ||
243 | |||
244 | ret = sizeof(sht21->eic) - 1; | ||
245 | mutex_lock(&sht21->lock); | ||
246 | if (!sht21->eic[0]) | ||
247 | ret = eic_read(sht21); | ||
248 | if (ret > 0) | ||
249 | memcpy(buf, sht21->eic, ret); | ||
250 | mutex_unlock(&sht21->lock); | ||
251 | return ret; | ||
252 | } | ||
253 | |||
168 | /* sysfs attributes */ | 254 | /* sysfs attributes */ |
169 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, sht21_show_temperature, | 255 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, sht21_show_temperature, |
170 | NULL, 0); | 256 | NULL, 0); |
171 | static SENSOR_DEVICE_ATTR(humidity1_input, S_IRUGO, sht21_show_humidity, | 257 | static SENSOR_DEVICE_ATTR(humidity1_input, S_IRUGO, sht21_show_humidity, |
172 | NULL, 0); | 258 | NULL, 0); |
259 | static DEVICE_ATTR_RO(eic); | ||
173 | 260 | ||
174 | static struct attribute *sht21_attrs[] = { | 261 | static struct attribute *sht21_attrs[] = { |
175 | &sensor_dev_attr_temp1_input.dev_attr.attr, | 262 | &sensor_dev_attr_temp1_input.dev_attr.attr, |
176 | &sensor_dev_attr_humidity1_input.dev_attr.attr, | 263 | &sensor_dev_attr_humidity1_input.dev_attr.attr, |
264 | &dev_attr_eic.attr, | ||
177 | NULL | 265 | NULL |
178 | }; | 266 | }; |
179 | 267 | ||