sht21.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. /* Sensirion SHT21 humidity and temperature sensor driver
  2. *
  3. * Copyright (C) 2010 Urs Fleisch <urs.fleisch@sensirion.com>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA
  18. *
  19. * Data sheet available (5/2010) at
  20. * http://www.sensirion.com/en/pdf/product_information/Datasheet-humidity-sensor-SHT21.pdf
  21. */
  22. #include <linux/module.h>
  23. #include <linux/init.h>
  24. #include <linux/slab.h>
  25. #include <linux/i2c.h>
  26. #include <linux/hwmon.h>
  27. #include <linux/hwmon-sysfs.h>
  28. #include <linux/err.h>
  29. #include <linux/mutex.h>
  30. #include <linux/device.h>
  31. /* I2C command bytes */
  32. #define SHT21_TRIG_T_MEASUREMENT_HM 0xe3
  33. #define SHT21_TRIG_RH_MEASUREMENT_HM 0xe5
  34. /**
  35. * struct sht21 - SHT21 device specific data
  36. * @hwmon_dev: device registered with hwmon
  37. * @lock: mutex to protect measurement values
  38. * @valid: only 0 before first measurement is taken
  39. * @last_update: time of last update (jiffies)
  40. * @temperature: cached temperature measurement value
  41. * @humidity: cached humidity measurement value
  42. */
  43. struct sht21 {
  44. struct device *hwmon_dev;
  45. struct mutex lock;
  46. char valid;
  47. unsigned long last_update;
  48. int temperature;
  49. int humidity;
  50. };
  51. /**
  52. * sht21_temp_ticks_to_millicelsius() - convert raw temperature ticks to
  53. * milli celsius
  54. * @ticks: temperature ticks value received from sensor
  55. */
  56. static inline int sht21_temp_ticks_to_millicelsius(int ticks)
  57. {
  58. ticks &= ~0x0003; /* clear status bits */
  59. /*
  60. * Formula T = -46.85 + 175.72 * ST / 2^16 from data sheet 6.2,
  61. * optimized for integer fixed point (3 digits) arithmetic
  62. */
  63. return ((21965 * ticks) >> 13) - 46850;
  64. }
  65. /**
  66. * sht21_rh_ticks_to_per_cent_mille() - convert raw humidity ticks to
  67. * one-thousandths of a percent relative humidity
  68. * @ticks: humidity ticks value received from sensor
  69. */
  70. static inline int sht21_rh_ticks_to_per_cent_mille(int ticks)
  71. {
  72. ticks &= ~0x0003; /* clear status bits */
  73. /*
  74. * Formula RH = -6 + 125 * SRH / 2^16 from data sheet 6.1,
  75. * optimized for integer fixed point (3 digits) arithmetic
  76. */
  77. return ((15625 * ticks) >> 13) - 6000;
  78. }
  79. /**
  80. * sht21_read_word_data() - read word from register
  81. * @client: I2C client device
  82. * @reg: I2C command byte
  83. *
  84. * Returns value, negative errno on error.
  85. */
  86. static inline int sht21_read_word_data(struct i2c_client *client, u8 reg)
  87. {
  88. int ret = i2c_smbus_read_word_data(client, reg);
  89. if (ret < 0)
  90. return ret;
  91. /*
  92. * SMBus specifies low byte first, but the SHT21 returns MSB
  93. * first, so we have to swab16 the values
  94. */
  95. return swab16(ret);
  96. }
  97. /**
  98. * sht21_update_measurements() - get updated measurements from device
  99. * @client: I2C client device
  100. *
  101. * Returns 0 on success, else negative errno.
  102. */
  103. static int sht21_update_measurements(struct i2c_client *client)
  104. {
  105. int ret = 0;
  106. struct sht21 *sht21 = i2c_get_clientdata(client);
  107. mutex_lock(&sht21->lock);
  108. /*
  109. * Data sheet 2.4:
  110. * SHT2x should not be active for more than 10% of the time - e.g.
  111. * maximum two measurements per second at 12bit accuracy shall be made.
  112. */
  113. if (time_after(jiffies, sht21->last_update + HZ / 2) || !sht21->valid) {
  114. ret = sht21_read_word_data(client, SHT21_TRIG_T_MEASUREMENT_HM);
  115. if (ret < 0)
  116. goto out;
  117. sht21->temperature = sht21_temp_ticks_to_millicelsius(ret);
  118. ret = sht21_read_word_data(client,
  119. SHT21_TRIG_RH_MEASUREMENT_HM);
  120. if (ret < 0)
  121. goto out;
  122. sht21->humidity = sht21_rh_ticks_to_per_cent_mille(ret);
  123. sht21->last_update = jiffies;
  124. sht21->valid = 1;
  125. }
  126. out:
  127. mutex_unlock(&sht21->lock);
  128. return ret >= 0 ? 0 : ret;
  129. }
  130. /**
  131. * sht21_show_temperature() - show temperature measurement value in sysfs
  132. * @dev: device
  133. * @attr: device attribute
  134. * @buf: sysfs buffer (PAGE_SIZE) where measurement values are written to
  135. *
  136. * Will be called on read access to temp1_input sysfs attribute.
  137. * Returns number of bytes written into buffer, negative errno on error.
  138. */
  139. static ssize_t sht21_show_temperature(struct device *dev,
  140. struct device_attribute *attr,
  141. char *buf)
  142. {
  143. struct i2c_client *client = to_i2c_client(dev);
  144. struct sht21 *sht21 = i2c_get_clientdata(client);
  145. int ret = sht21_update_measurements(client);
  146. if (ret < 0)
  147. return ret;
  148. return sprintf(buf, "%d\n", sht21->temperature);
  149. }
  150. /**
  151. * sht21_show_humidity() - show humidity measurement value in sysfs
  152. * @dev: device
  153. * @attr: device attribute
  154. * @buf: sysfs buffer (PAGE_SIZE) where measurement values are written to
  155. *
  156. * Will be called on read access to humidity1_input sysfs attribute.
  157. * Returns number of bytes written into buffer, negative errno on error.
  158. */
  159. static ssize_t sht21_show_humidity(struct device *dev,
  160. struct device_attribute *attr,
  161. char *buf)
  162. {
  163. struct i2c_client *client = to_i2c_client(dev);
  164. struct sht21 *sht21 = i2c_get_clientdata(client);
  165. int ret = sht21_update_measurements(client);
  166. if (ret < 0)
  167. return ret;
  168. return sprintf(buf, "%d\n", sht21->humidity);
  169. }
  170. /* sysfs attributes */
  171. static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, sht21_show_temperature,
  172. NULL, 0);
  173. static SENSOR_DEVICE_ATTR(humidity1_input, S_IRUGO, sht21_show_humidity,
  174. NULL, 0);
  175. static struct attribute *sht21_attributes[] = {
  176. &sensor_dev_attr_temp1_input.dev_attr.attr,
  177. &sensor_dev_attr_humidity1_input.dev_attr.attr,
  178. NULL
  179. };
  180. static const struct attribute_group sht21_attr_group = {
  181. .attrs = sht21_attributes,
  182. };
  183. /**
  184. * sht21_probe() - probe device
  185. * @client: I2C client device
  186. * @id: device ID
  187. *
  188. * Called by the I2C core when an entry in the ID table matches a
  189. * device's name.
  190. * Returns 0 on success.
  191. */
  192. static int __devinit sht21_probe(struct i2c_client *client,
  193. const struct i2c_device_id *id)
  194. {
  195. struct sht21 *sht21;
  196. int err;
  197. if (!i2c_check_functionality(client->adapter,
  198. I2C_FUNC_SMBUS_WORD_DATA)) {
  199. dev_err(&client->dev,
  200. "adapter does not support SMBus word transactions\n");
  201. return -ENODEV;
  202. }
  203. sht21 = kzalloc(sizeof(*sht21), GFP_KERNEL);
  204. if (!sht21) {
  205. dev_dbg(&client->dev, "kzalloc failed\n");
  206. return -ENOMEM;
  207. }
  208. i2c_set_clientdata(client, sht21);
  209. mutex_init(&sht21->lock);
  210. err = sysfs_create_group(&client->dev.kobj, &sht21_attr_group);
  211. if (err) {
  212. dev_dbg(&client->dev, "could not create sysfs files\n");
  213. goto fail_free;
  214. }
  215. sht21->hwmon_dev = hwmon_device_register(&client->dev);
  216. if (IS_ERR(sht21->hwmon_dev)) {
  217. dev_dbg(&client->dev, "unable to register hwmon device\n");
  218. err = PTR_ERR(sht21->hwmon_dev);
  219. goto fail_remove_sysfs;
  220. }
  221. dev_info(&client->dev, "initialized\n");
  222. return 0;
  223. fail_remove_sysfs:
  224. sysfs_remove_group(&client->dev.kobj, &sht21_attr_group);
  225. fail_free:
  226. kfree(sht21);
  227. return err;
  228. }
  229. /**
  230. * sht21_remove() - remove device
  231. * @client: I2C client device
  232. */
  233. static int __devexit sht21_remove(struct i2c_client *client)
  234. {
  235. struct sht21 *sht21 = i2c_get_clientdata(client);
  236. hwmon_device_unregister(sht21->hwmon_dev);
  237. sysfs_remove_group(&client->dev.kobj, &sht21_attr_group);
  238. kfree(sht21);
  239. return 0;
  240. }
  241. /* Device ID table */
  242. static const struct i2c_device_id sht21_id[] = {
  243. { "sht21", 0 },
  244. { }
  245. };
  246. MODULE_DEVICE_TABLE(i2c, sht21_id);
  247. static struct i2c_driver sht21_driver = {
  248. .driver.name = "sht21",
  249. .probe = sht21_probe,
  250. .remove = __devexit_p(sht21_remove),
  251. .id_table = sht21_id,
  252. };
  253. /**
  254. * sht21_init() - initialize driver
  255. *
  256. * Called when kernel is booted or module is inserted.
  257. * Returns 0 on success.
  258. */
  259. static int __init sht21_init(void)
  260. {
  261. return i2c_add_driver(&sht21_driver);
  262. }
  263. module_init(sht21_init);
  264. /**
  265. * sht21_init() - clean up driver
  266. *
  267. * Called when module is removed.
  268. */
  269. static void __exit sht21_exit(void)
  270. {
  271. i2c_del_driver(&sht21_driver);
  272. }
  273. module_exit(sht21_exit);
  274. MODULE_AUTHOR("Urs Fleisch <urs.fleisch@sensirion.com>");
  275. MODULE_DESCRIPTION("Sensirion SHT21 humidity and temperature sensor driver");
  276. MODULE_LICENSE("GPL");