mpl115.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * mpl115.c - Support for Freescale MPL115A pressure/temperature sensor
  4. *
  5. * Copyright (c) 2014 Peter Meerwald <pmeerw@pmeerw.net>
  6. *
  7. * TODO: synchronization with system suspend
  8. */
  9. #include <linux/module.h>
  10. #include <linux/iio/iio.h>
  11. #include <linux/delay.h>
  12. #include <linux/gpio/consumer.h>
  13. #include "mpl115.h"
  14. #define MPL115_PADC 0x00 /* pressure ADC output value, MSB first, 10 bit */
  15. #define MPL115_TADC 0x02 /* temperature ADC output value, MSB first, 10 bit */
  16. #define MPL115_A0 0x04 /* 12 bit integer, 3 bit fraction */
  17. #define MPL115_B1 0x06 /* 2 bit integer, 13 bit fraction */
  18. #define MPL115_B2 0x08 /* 1 bit integer, 14 bit fraction */
  19. #define MPL115_C12 0x0a /* 0 bit integer, 13 bit fraction */
  20. #define MPL115_CONVERT 0x12 /* convert temperature and pressure */
  21. struct mpl115_data {
  22. struct device *dev;
  23. struct mutex lock;
  24. s16 a0;
  25. s16 b1, b2;
  26. s16 c12;
  27. struct gpio_desc *shutdown;
  28. const struct mpl115_ops *ops;
  29. };
  30. static int mpl115_request(struct mpl115_data *data)
  31. {
  32. int ret = data->ops->write(data->dev, MPL115_CONVERT, 0);
  33. if (ret < 0)
  34. return ret;
  35. usleep_range(3000, 4000);
  36. return 0;
  37. }
  38. static int mpl115_comp_pressure(struct mpl115_data *data, int *val, int *val2)
  39. {
  40. int ret;
  41. u16 padc, tadc;
  42. int a1, y1, pcomp;
  43. unsigned kpa;
  44. mutex_lock(&data->lock);
  45. ret = mpl115_request(data);
  46. if (ret < 0)
  47. goto done;
  48. ret = data->ops->read(data->dev, MPL115_PADC);
  49. if (ret < 0)
  50. goto done;
  51. padc = ret >> 6;
  52. ret = data->ops->read(data->dev, MPL115_TADC);
  53. if (ret < 0)
  54. goto done;
  55. tadc = ret >> 6;
  56. /* see Freescale AN3785 */
  57. a1 = data->b1 + ((data->c12 * tadc) >> 11);
  58. y1 = (data->a0 << 10) + a1 * padc;
  59. /* compensated pressure with 4 fractional bits */
  60. pcomp = (y1 + ((data->b2 * (int) tadc) >> 1)) >> 9;
  61. kpa = pcomp * (115 - 50) / 1023 + (50 << 4);
  62. *val = kpa >> 4;
  63. *val2 = (kpa & 15) * (1000000 >> 4);
  64. done:
  65. mutex_unlock(&data->lock);
  66. return ret;
  67. }
  68. static int mpl115_read_temp(struct mpl115_data *data)
  69. {
  70. int ret;
  71. mutex_lock(&data->lock);
  72. ret = mpl115_request(data);
  73. if (ret < 0)
  74. goto done;
  75. ret = data->ops->read(data->dev, MPL115_TADC);
  76. done:
  77. mutex_unlock(&data->lock);
  78. return ret;
  79. }
  80. static int mpl115_read_raw(struct iio_dev *indio_dev,
  81. struct iio_chan_spec const *chan,
  82. int *val, int *val2, long mask)
  83. {
  84. struct mpl115_data *data = iio_priv(indio_dev);
  85. int ret;
  86. switch (mask) {
  87. case IIO_CHAN_INFO_PROCESSED:
  88. pm_runtime_get_sync(data->dev);
  89. ret = mpl115_comp_pressure(data, val, val2);
  90. if (ret < 0)
  91. return ret;
  92. pm_runtime_put_autosuspend(data->dev);
  93. return IIO_VAL_INT_PLUS_MICRO;
  94. case IIO_CHAN_INFO_RAW:
  95. pm_runtime_get_sync(data->dev);
  96. /* temperature -5.35 C / LSB, 472 LSB is 25 C */
  97. ret = mpl115_read_temp(data);
  98. if (ret < 0)
  99. return ret;
  100. pm_runtime_put_autosuspend(data->dev);
  101. *val = ret >> 6;
  102. return IIO_VAL_INT;
  103. case IIO_CHAN_INFO_OFFSET:
  104. *val = -605;
  105. *val2 = 750000;
  106. return IIO_VAL_INT_PLUS_MICRO;
  107. case IIO_CHAN_INFO_SCALE:
  108. *val = -186;
  109. *val2 = 915888;
  110. return IIO_VAL_INT_PLUS_MICRO;
  111. }
  112. return -EINVAL;
  113. }
  114. static const struct iio_chan_spec mpl115_channels[] = {
  115. {
  116. .type = IIO_PRESSURE,
  117. .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
  118. },
  119. {
  120. .type = IIO_TEMP,
  121. .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
  122. .info_mask_shared_by_type =
  123. BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_SCALE),
  124. },
  125. };
  126. static const struct iio_info mpl115_info = {
  127. .read_raw = &mpl115_read_raw,
  128. };
  129. int mpl115_probe(struct device *dev, const char *name,
  130. const struct mpl115_ops *ops)
  131. {
  132. struct mpl115_data *data;
  133. struct iio_dev *indio_dev;
  134. int ret;
  135. indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
  136. if (!indio_dev)
  137. return -ENOMEM;
  138. data = iio_priv(indio_dev);
  139. data->dev = dev;
  140. data->ops = ops;
  141. mutex_init(&data->lock);
  142. indio_dev->info = &mpl115_info;
  143. indio_dev->name = name;
  144. indio_dev->modes = INDIO_DIRECT_MODE;
  145. indio_dev->channels = mpl115_channels;
  146. indio_dev->num_channels = ARRAY_SIZE(mpl115_channels);
  147. ret = data->ops->init(data->dev);
  148. if (ret)
  149. return ret;
  150. dev_set_drvdata(dev, indio_dev);
  151. ret = data->ops->read(data->dev, MPL115_A0);
  152. if (ret < 0)
  153. return ret;
  154. data->a0 = ret;
  155. ret = data->ops->read(data->dev, MPL115_B1);
  156. if (ret < 0)
  157. return ret;
  158. data->b1 = ret;
  159. ret = data->ops->read(data->dev, MPL115_B2);
  160. if (ret < 0)
  161. return ret;
  162. data->b2 = ret;
  163. ret = data->ops->read(data->dev, MPL115_C12);
  164. if (ret < 0)
  165. return ret;
  166. data->c12 = ret;
  167. data->shutdown = devm_gpiod_get_optional(dev, "shutdown",
  168. GPIOD_OUT_LOW);
  169. if (IS_ERR(data->shutdown))
  170. return dev_err_probe(dev, PTR_ERR(data->shutdown),
  171. "cannot get shutdown gpio\n");
  172. if (data->shutdown) {
  173. /* Enable runtime PM */
  174. pm_runtime_get_noresume(dev);
  175. pm_runtime_set_active(dev);
  176. pm_runtime_enable(dev);
  177. /*
  178. * As the device takes 3 ms to come up with a fresh
  179. * reading after power-on and 5 ms to actually power-on,
  180. * do not shut it down unnecessarily. Set autosuspend to
  181. * 2000 ms.
  182. */
  183. pm_runtime_set_autosuspend_delay(dev, 2000);
  184. pm_runtime_use_autosuspend(dev);
  185. pm_runtime_put(dev);
  186. dev_dbg(dev, "low-power mode enabled");
  187. } else
  188. dev_dbg(dev, "low-power mode disabled");
  189. return devm_iio_device_register(dev, indio_dev);
  190. }
  191. EXPORT_SYMBOL_NS_GPL(mpl115_probe, "IIO_MPL115");
  192. static int mpl115_runtime_suspend(struct device *dev)
  193. {
  194. struct mpl115_data *data = iio_priv(dev_get_drvdata(dev));
  195. gpiod_set_value(data->shutdown, 1);
  196. return 0;
  197. }
  198. static int mpl115_runtime_resume(struct device *dev)
  199. {
  200. struct mpl115_data *data = iio_priv(dev_get_drvdata(dev));
  201. gpiod_set_value(data->shutdown, 0);
  202. usleep_range(5000, 6000);
  203. return 0;
  204. }
  205. EXPORT_NS_RUNTIME_DEV_PM_OPS(mpl115_dev_pm_ops, mpl115_runtime_suspend,
  206. mpl115_runtime_resume, NULL, IIO_MPL115);
  207. MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
  208. MODULE_DESCRIPTION("Freescale MPL115 pressure/temperature driver");
  209. MODULE_LICENSE("GPL");