hp206c.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. /*
  2. * hp206c.c - HOPERF HP206C precision barometer and altimeter sensor
  3. *
  4. * Copyright (c) 2016, Intel Corporation.
  5. *
  6. * This file is subject to the terms and conditions of version 2 of
  7. * the GNU General Public License. See the file COPYING in the main
  8. * directory of this archive for more details.
  9. *
  10. * (7-bit I2C slave address 0x76)
  11. *
  12. * Datasheet:
  13. * http://www.hoperf.com/upload/sensor/HP206C_DataSheet_EN_V2.0.pdf
  14. */
  15. #include <linux/module.h>
  16. #include <linux/i2c.h>
  17. #include <linux/iio/iio.h>
  18. #include <linux/iio/sysfs.h>
  19. #include <linux/delay.h>
  20. #include <linux/util_macros.h>
  21. #include <linux/acpi.h>
  22. /* I2C commands: */
  23. #define HP206C_CMD_SOFT_RST 0x06
  24. #define HP206C_CMD_ADC_CVT 0x40
  25. #define HP206C_CMD_ADC_CVT_OSR_4096 0x00
  26. #define HP206C_CMD_ADC_CVT_OSR_2048 0x04
  27. #define HP206C_CMD_ADC_CVT_OSR_1024 0x08
  28. #define HP206C_CMD_ADC_CVT_OSR_512 0x0c
  29. #define HP206C_CMD_ADC_CVT_OSR_256 0x10
  30. #define HP206C_CMD_ADC_CVT_OSR_128 0x14
  31. #define HP206C_CMD_ADC_CVT_CHNL_PT 0x00
  32. #define HP206C_CMD_ADC_CVT_CHNL_T 0x02
  33. #define HP206C_CMD_READ_P 0x30
  34. #define HP206C_CMD_READ_T 0x32
  35. #define HP206C_CMD_READ_REG 0x80
  36. #define HP206C_CMD_WRITE_REG 0xc0
  37. #define HP206C_REG_INT_EN 0x0b
  38. #define HP206C_REG_INT_CFG 0x0c
  39. #define HP206C_REG_INT_SRC 0x0d
  40. #define HP206C_FLAG_DEV_RDY 0x40
  41. #define HP206C_REG_PARA 0x0f
  42. #define HP206C_FLAG_CMPS_EN 0x80
  43. /* Maximum spin for DEV_RDY */
  44. #define HP206C_MAX_DEV_RDY_WAIT_COUNT 20
  45. #define HP206C_DEV_RDY_WAIT_US 20000
  46. struct hp206c_data {
  47. struct mutex mutex;
  48. struct i2c_client *client;
  49. int temp_osr_index;
  50. int pres_osr_index;
  51. };
  52. struct hp206c_osr_setting {
  53. u8 osr_mask;
  54. unsigned int temp_conv_time_us;
  55. unsigned int pres_conv_time_us;
  56. };
  57. /* Data from Table 5 in datasheet. */
  58. static const struct hp206c_osr_setting hp206c_osr_settings[] = {
  59. { HP206C_CMD_ADC_CVT_OSR_4096, 65600, 131100 },
  60. { HP206C_CMD_ADC_CVT_OSR_2048, 32800, 65600 },
  61. { HP206C_CMD_ADC_CVT_OSR_1024, 16400, 32800 },
  62. { HP206C_CMD_ADC_CVT_OSR_512, 8200, 16400 },
  63. { HP206C_CMD_ADC_CVT_OSR_256, 4100, 8200 },
  64. { HP206C_CMD_ADC_CVT_OSR_128, 2100, 4100 },
  65. };
  66. static const int hp206c_osr_rates[] = { 4096, 2048, 1024, 512, 256, 128 };
  67. static const char hp206c_osr_rates_str[] = "4096 2048 1024 512 256 128";
  68. static inline int hp206c_read_reg(struct i2c_client *client, u8 reg)
  69. {
  70. return i2c_smbus_read_byte_data(client, HP206C_CMD_READ_REG | reg);
  71. }
  72. static inline int hp206c_write_reg(struct i2c_client *client, u8 reg, u8 val)
  73. {
  74. return i2c_smbus_write_byte_data(client,
  75. HP206C_CMD_WRITE_REG | reg, val);
  76. }
  77. static int hp206c_read_20bit(struct i2c_client *client, u8 cmd)
  78. {
  79. int ret;
  80. u8 values[3];
  81. ret = i2c_smbus_read_i2c_block_data(client, cmd, 3, values);
  82. if (ret < 0)
  83. return ret;
  84. if (ret != 3)
  85. return -EIO;
  86. return ((values[0] & 0xF) << 16) | (values[1] << 8) | (values[2]);
  87. }
  88. /* Spin for max 160ms until DEV_RDY is 1, or return error. */
  89. static int hp206c_wait_dev_rdy(struct iio_dev *indio_dev)
  90. {
  91. int ret;
  92. int count = 0;
  93. struct hp206c_data *data = iio_priv(indio_dev);
  94. struct i2c_client *client = data->client;
  95. while (++count <= HP206C_MAX_DEV_RDY_WAIT_COUNT) {
  96. ret = hp206c_read_reg(client, HP206C_REG_INT_SRC);
  97. if (ret < 0) {
  98. dev_err(&indio_dev->dev, "Failed READ_REG INT_SRC: %d\n", ret);
  99. return ret;
  100. }
  101. if (ret & HP206C_FLAG_DEV_RDY)
  102. return 0;
  103. usleep_range(HP206C_DEV_RDY_WAIT_US, HP206C_DEV_RDY_WAIT_US * 3 / 2);
  104. }
  105. return -ETIMEDOUT;
  106. }
  107. static int hp206c_set_compensation(struct i2c_client *client, bool enabled)
  108. {
  109. int val;
  110. val = hp206c_read_reg(client, HP206C_REG_PARA);
  111. if (val < 0)
  112. return val;
  113. if (enabled)
  114. val |= HP206C_FLAG_CMPS_EN;
  115. else
  116. val &= ~HP206C_FLAG_CMPS_EN;
  117. return hp206c_write_reg(client, HP206C_REG_PARA, val);
  118. }
  119. /* Do a soft reset */
  120. static int hp206c_soft_reset(struct iio_dev *indio_dev)
  121. {
  122. int ret;
  123. struct hp206c_data *data = iio_priv(indio_dev);
  124. struct i2c_client *client = data->client;
  125. ret = i2c_smbus_write_byte(client, HP206C_CMD_SOFT_RST);
  126. if (ret) {
  127. dev_err(&client->dev, "Failed to reset device: %d\n", ret);
  128. return ret;
  129. }
  130. usleep_range(400, 600);
  131. ret = hp206c_wait_dev_rdy(indio_dev);
  132. if (ret) {
  133. dev_err(&client->dev, "Device not ready after soft reset: %d\n", ret);
  134. return ret;
  135. }
  136. ret = hp206c_set_compensation(client, true);
  137. if (ret)
  138. dev_err(&client->dev, "Failed to enable compensation: %d\n", ret);
  139. return ret;
  140. }
  141. static int hp206c_conv_and_read(struct iio_dev *indio_dev,
  142. u8 conv_cmd, u8 read_cmd,
  143. unsigned int sleep_us)
  144. {
  145. int ret;
  146. struct hp206c_data *data = iio_priv(indio_dev);
  147. struct i2c_client *client = data->client;
  148. ret = hp206c_wait_dev_rdy(indio_dev);
  149. if (ret < 0) {
  150. dev_err(&indio_dev->dev, "Device not ready: %d\n", ret);
  151. return ret;
  152. }
  153. ret = i2c_smbus_write_byte(client, conv_cmd);
  154. if (ret < 0) {
  155. dev_err(&indio_dev->dev, "Failed convert: %d\n", ret);
  156. return ret;
  157. }
  158. usleep_range(sleep_us, sleep_us * 3 / 2);
  159. ret = hp206c_wait_dev_rdy(indio_dev);
  160. if (ret < 0) {
  161. dev_err(&indio_dev->dev, "Device not ready: %d\n", ret);
  162. return ret;
  163. }
  164. ret = hp206c_read_20bit(client, read_cmd);
  165. if (ret < 0)
  166. dev_err(&indio_dev->dev, "Failed read: %d\n", ret);
  167. return ret;
  168. }
  169. static int hp206c_read_raw(struct iio_dev *indio_dev,
  170. struct iio_chan_spec const *chan, int *val,
  171. int *val2, long mask)
  172. {
  173. int ret;
  174. struct hp206c_data *data = iio_priv(indio_dev);
  175. const struct hp206c_osr_setting *osr_setting;
  176. u8 conv_cmd;
  177. mutex_lock(&data->mutex);
  178. switch (mask) {
  179. case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
  180. switch (chan->type) {
  181. case IIO_TEMP:
  182. *val = hp206c_osr_rates[data->temp_osr_index];
  183. ret = IIO_VAL_INT;
  184. break;
  185. case IIO_PRESSURE:
  186. *val = hp206c_osr_rates[data->pres_osr_index];
  187. ret = IIO_VAL_INT;
  188. break;
  189. default:
  190. ret = -EINVAL;
  191. }
  192. break;
  193. case IIO_CHAN_INFO_RAW:
  194. switch (chan->type) {
  195. case IIO_TEMP:
  196. osr_setting = &hp206c_osr_settings[data->temp_osr_index];
  197. conv_cmd = HP206C_CMD_ADC_CVT |
  198. osr_setting->osr_mask |
  199. HP206C_CMD_ADC_CVT_CHNL_T;
  200. ret = hp206c_conv_and_read(indio_dev,
  201. conv_cmd,
  202. HP206C_CMD_READ_T,
  203. osr_setting->temp_conv_time_us);
  204. if (ret >= 0) {
  205. /* 20 significant bits are provided.
  206. * Extend sign over the rest.
  207. */
  208. *val = sign_extend32(ret, 19);
  209. ret = IIO_VAL_INT;
  210. }
  211. break;
  212. case IIO_PRESSURE:
  213. osr_setting = &hp206c_osr_settings[data->pres_osr_index];
  214. conv_cmd = HP206C_CMD_ADC_CVT |
  215. osr_setting->osr_mask |
  216. HP206C_CMD_ADC_CVT_CHNL_PT;
  217. ret = hp206c_conv_and_read(indio_dev,
  218. conv_cmd,
  219. HP206C_CMD_READ_P,
  220. osr_setting->pres_conv_time_us);
  221. if (ret >= 0) {
  222. *val = ret;
  223. ret = IIO_VAL_INT;
  224. }
  225. break;
  226. default:
  227. ret = -EINVAL;
  228. }
  229. break;
  230. case IIO_CHAN_INFO_SCALE:
  231. switch (chan->type) {
  232. case IIO_TEMP:
  233. *val = 0;
  234. *val2 = 10000;
  235. ret = IIO_VAL_INT_PLUS_MICRO;
  236. break;
  237. case IIO_PRESSURE:
  238. *val = 0;
  239. *val2 = 1000;
  240. ret = IIO_VAL_INT_PLUS_MICRO;
  241. break;
  242. default:
  243. ret = -EINVAL;
  244. }
  245. break;
  246. default:
  247. ret = -EINVAL;
  248. }
  249. mutex_unlock(&data->mutex);
  250. return ret;
  251. }
  252. static int hp206c_write_raw(struct iio_dev *indio_dev,
  253. struct iio_chan_spec const *chan,
  254. int val, int val2, long mask)
  255. {
  256. int ret = 0;
  257. struct hp206c_data *data = iio_priv(indio_dev);
  258. if (mask != IIO_CHAN_INFO_OVERSAMPLING_RATIO)
  259. return -EINVAL;
  260. mutex_lock(&data->mutex);
  261. switch (chan->type) {
  262. case IIO_TEMP:
  263. data->temp_osr_index = find_closest_descending(val,
  264. hp206c_osr_rates, ARRAY_SIZE(hp206c_osr_rates));
  265. break;
  266. case IIO_PRESSURE:
  267. data->pres_osr_index = find_closest_descending(val,
  268. hp206c_osr_rates, ARRAY_SIZE(hp206c_osr_rates));
  269. break;
  270. default:
  271. ret = -EINVAL;
  272. }
  273. mutex_unlock(&data->mutex);
  274. return ret;
  275. }
  276. static const struct iio_chan_spec hp206c_channels[] = {
  277. {
  278. .type = IIO_TEMP,
  279. .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
  280. BIT(IIO_CHAN_INFO_SCALE) |
  281. BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
  282. },
  283. {
  284. .type = IIO_PRESSURE,
  285. .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
  286. BIT(IIO_CHAN_INFO_SCALE) |
  287. BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
  288. }
  289. };
  290. static IIO_CONST_ATTR_SAMP_FREQ_AVAIL(hp206c_osr_rates_str);
  291. static struct attribute *hp206c_attributes[] = {
  292. &iio_const_attr_sampling_frequency_available.dev_attr.attr,
  293. NULL,
  294. };
  295. static const struct attribute_group hp206c_attribute_group = {
  296. .attrs = hp206c_attributes,
  297. };
  298. static const struct iio_info hp206c_info = {
  299. .attrs = &hp206c_attribute_group,
  300. .read_raw = hp206c_read_raw,
  301. .write_raw = hp206c_write_raw,
  302. };
  303. static int hp206c_probe(struct i2c_client *client,
  304. const struct i2c_device_id *id)
  305. {
  306. struct iio_dev *indio_dev;
  307. struct hp206c_data *data;
  308. int ret;
  309. if (!i2c_check_functionality(client->adapter,
  310. I2C_FUNC_SMBUS_BYTE |
  311. I2C_FUNC_SMBUS_BYTE_DATA |
  312. I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
  313. dev_err(&client->dev, "Adapter does not support "
  314. "all required i2c functionality\n");
  315. return -ENODEV;
  316. }
  317. indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
  318. if (!indio_dev)
  319. return -ENOMEM;
  320. data = iio_priv(indio_dev);
  321. data->client = client;
  322. mutex_init(&data->mutex);
  323. indio_dev->info = &hp206c_info;
  324. indio_dev->name = id->name;
  325. indio_dev->dev.parent = &client->dev;
  326. indio_dev->modes = INDIO_DIRECT_MODE;
  327. indio_dev->channels = hp206c_channels;
  328. indio_dev->num_channels = ARRAY_SIZE(hp206c_channels);
  329. i2c_set_clientdata(client, indio_dev);
  330. /* Do a soft reset on probe */
  331. ret = hp206c_soft_reset(indio_dev);
  332. if (ret) {
  333. dev_err(&client->dev, "Failed to reset on startup: %d\n", ret);
  334. return -ENODEV;
  335. }
  336. return devm_iio_device_register(&client->dev, indio_dev);
  337. }
  338. static const struct i2c_device_id hp206c_id[] = {
  339. {"hp206c"},
  340. {}
  341. };
  342. MODULE_DEVICE_TABLE(i2c, hp206c_id);
  343. #ifdef CONFIG_ACPI
  344. static const struct acpi_device_id hp206c_acpi_match[] = {
  345. {"HOP206C", 0},
  346. { },
  347. };
  348. MODULE_DEVICE_TABLE(acpi, hp206c_acpi_match);
  349. #endif
  350. static struct i2c_driver hp206c_driver = {
  351. .probe = hp206c_probe,
  352. .id_table = hp206c_id,
  353. .driver = {
  354. .name = "hp206c",
  355. .acpi_match_table = ACPI_PTR(hp206c_acpi_match),
  356. },
  357. };
  358. module_i2c_driver(hp206c_driver);
  359. MODULE_DESCRIPTION("HOPERF HP206C precision barometer and altimeter sensor");
  360. MODULE_AUTHOR("Leonard Crestez <leonard.crestez@intel.com>");
  361. MODULE_LICENSE("GPL v2");