hp206c.c 9.9 KB

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