lp8788_adc.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * TI LP8788 MFD - ADC driver
  4. *
  5. * Copyright 2012 Texas Instruments
  6. *
  7. * Author: Milo(Woogyom) Kim <milo.kim@ti.com>
  8. */
  9. #include <linux/delay.h>
  10. #include <linux/iio/iio.h>
  11. #include <linux/iio/driver.h>
  12. #include <linux/iio/machine.h>
  13. #include <linux/mfd/lp8788.h>
  14. #include <linux/module.h>
  15. #include <linux/mutex.h>
  16. #include <linux/platform_device.h>
  17. #include <linux/slab.h>
  18. /* register address */
  19. #define LP8788_ADC_CONF 0x60
  20. #define LP8788_ADC_RAW 0x61
  21. #define LP8788_ADC_DONE 0x63
  22. #define ADC_CONV_START 1
  23. struct lp8788_adc {
  24. struct lp8788 *lp;
  25. struct iio_map *map;
  26. struct mutex lock;
  27. };
  28. static const int lp8788_scale[LPADC_MAX] = {
  29. [LPADC_VBATT_5P5] = 1343101,
  30. [LPADC_VIN_CHG] = 3052503,
  31. [LPADC_IBATT] = 610500,
  32. [LPADC_IC_TEMP] = 61050,
  33. [LPADC_VBATT_6P0] = 1465201,
  34. [LPADC_VBATT_5P0] = 1221001,
  35. [LPADC_ADC1] = 610500,
  36. [LPADC_ADC2] = 610500,
  37. [LPADC_VDD] = 1025641,
  38. [LPADC_VCOIN] = 757020,
  39. [LPADC_ADC3] = 610500,
  40. [LPADC_ADC4] = 610500,
  41. };
  42. static int lp8788_get_adc_result(struct lp8788_adc *adc, enum lp8788_adc_id id,
  43. int *val)
  44. {
  45. unsigned int msb;
  46. unsigned int lsb;
  47. unsigned int result;
  48. u8 data;
  49. u8 rawdata[2];
  50. int size = ARRAY_SIZE(rawdata);
  51. int retry = 5;
  52. int ret;
  53. data = (id << 1) | ADC_CONV_START;
  54. ret = lp8788_write_byte(adc->lp, LP8788_ADC_CONF, data);
  55. if (ret)
  56. goto err_io;
  57. /* retry until adc conversion is done */
  58. data = 0;
  59. while (retry--) {
  60. usleep_range(100, 200);
  61. ret = lp8788_read_byte(adc->lp, LP8788_ADC_DONE, &data);
  62. if (ret)
  63. goto err_io;
  64. /* conversion done */
  65. if (data)
  66. break;
  67. }
  68. ret = lp8788_read_multi_bytes(adc->lp, LP8788_ADC_RAW, rawdata, size);
  69. if (ret)
  70. goto err_io;
  71. msb = (rawdata[0] << 4) & 0x00000ff0;
  72. lsb = (rawdata[1] >> 4) & 0x0000000f;
  73. result = msb | lsb;
  74. *val = result;
  75. return 0;
  76. err_io:
  77. return ret;
  78. }
  79. static int lp8788_adc_read_raw(struct iio_dev *indio_dev,
  80. struct iio_chan_spec const *chan,
  81. int *val, int *val2, long mask)
  82. {
  83. struct lp8788_adc *adc = iio_priv(indio_dev);
  84. enum lp8788_adc_id id = chan->channel;
  85. int ret;
  86. mutex_lock(&adc->lock);
  87. switch (mask) {
  88. case IIO_CHAN_INFO_RAW:
  89. ret = lp8788_get_adc_result(adc, id, val) ? -EIO : IIO_VAL_INT;
  90. break;
  91. case IIO_CHAN_INFO_SCALE:
  92. *val = lp8788_scale[id] / 1000000;
  93. *val2 = lp8788_scale[id] % 1000000;
  94. ret = IIO_VAL_INT_PLUS_MICRO;
  95. break;
  96. default:
  97. ret = -EINVAL;
  98. break;
  99. }
  100. mutex_unlock(&adc->lock);
  101. return ret;
  102. }
  103. static const struct iio_info lp8788_adc_info = {
  104. .read_raw = &lp8788_adc_read_raw,
  105. };
  106. #define LP8788_CHAN(_id, _type) { \
  107. .type = _type, \
  108. .indexed = 1, \
  109. .channel = LPADC_##_id, \
  110. .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
  111. BIT(IIO_CHAN_INFO_SCALE), \
  112. .datasheet_name = #_id, \
  113. }
  114. static const struct iio_chan_spec lp8788_adc_channels[] = {
  115. [LPADC_VBATT_5P5] = LP8788_CHAN(VBATT_5P5, IIO_VOLTAGE),
  116. [LPADC_VIN_CHG] = LP8788_CHAN(VIN_CHG, IIO_VOLTAGE),
  117. [LPADC_IBATT] = LP8788_CHAN(IBATT, IIO_CURRENT),
  118. [LPADC_IC_TEMP] = LP8788_CHAN(IC_TEMP, IIO_TEMP),
  119. [LPADC_VBATT_6P0] = LP8788_CHAN(VBATT_6P0, IIO_VOLTAGE),
  120. [LPADC_VBATT_5P0] = LP8788_CHAN(VBATT_5P0, IIO_VOLTAGE),
  121. [LPADC_ADC1] = LP8788_CHAN(ADC1, IIO_VOLTAGE),
  122. [LPADC_ADC2] = LP8788_CHAN(ADC2, IIO_VOLTAGE),
  123. [LPADC_VDD] = LP8788_CHAN(VDD, IIO_VOLTAGE),
  124. [LPADC_VCOIN] = LP8788_CHAN(VCOIN, IIO_VOLTAGE),
  125. [LPADC_ADC3] = LP8788_CHAN(ADC3, IIO_VOLTAGE),
  126. [LPADC_ADC4] = LP8788_CHAN(ADC4, IIO_VOLTAGE),
  127. };
  128. /* default maps used by iio consumer (lp8788-charger driver) */
  129. static struct iio_map lp8788_default_iio_maps[] = {
  130. {
  131. .consumer_dev_name = "lp8788-charger",
  132. .consumer_channel = "lp8788_vbatt_5p0",
  133. .adc_channel_label = "VBATT_5P0",
  134. },
  135. {
  136. .consumer_dev_name = "lp8788-charger",
  137. .consumer_channel = "lp8788_adc1",
  138. .adc_channel_label = "ADC1",
  139. },
  140. { }
  141. };
  142. static int lp8788_iio_map_register(struct iio_dev *indio_dev,
  143. struct lp8788_platform_data *pdata,
  144. struct lp8788_adc *adc)
  145. {
  146. struct iio_map *map;
  147. int ret;
  148. map = (!pdata || !pdata->adc_pdata) ?
  149. lp8788_default_iio_maps : pdata->adc_pdata;
  150. ret = iio_map_array_register(indio_dev, map);
  151. if (ret) {
  152. dev_err(&indio_dev->dev, "iio map err: %d\n", ret);
  153. return ret;
  154. }
  155. adc->map = map;
  156. return 0;
  157. }
  158. static int lp8788_adc_probe(struct platform_device *pdev)
  159. {
  160. struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
  161. struct iio_dev *indio_dev;
  162. struct lp8788_adc *adc;
  163. int ret;
  164. indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc));
  165. if (!indio_dev)
  166. return -ENOMEM;
  167. adc = iio_priv(indio_dev);
  168. adc->lp = lp;
  169. platform_set_drvdata(pdev, indio_dev);
  170. ret = lp8788_iio_map_register(indio_dev, lp->pdata, adc);
  171. if (ret)
  172. return ret;
  173. mutex_init(&adc->lock);
  174. indio_dev->name = pdev->name;
  175. indio_dev->modes = INDIO_DIRECT_MODE;
  176. indio_dev->info = &lp8788_adc_info;
  177. indio_dev->channels = lp8788_adc_channels;
  178. indio_dev->num_channels = ARRAY_SIZE(lp8788_adc_channels);
  179. ret = iio_device_register(indio_dev);
  180. if (ret) {
  181. dev_err(&pdev->dev, "iio dev register err: %d\n", ret);
  182. goto err_iio_device;
  183. }
  184. return 0;
  185. err_iio_device:
  186. iio_map_array_unregister(indio_dev);
  187. return ret;
  188. }
  189. static int lp8788_adc_remove(struct platform_device *pdev)
  190. {
  191. struct iio_dev *indio_dev = platform_get_drvdata(pdev);
  192. iio_device_unregister(indio_dev);
  193. iio_map_array_unregister(indio_dev);
  194. return 0;
  195. }
  196. static struct platform_driver lp8788_adc_driver = {
  197. .probe = lp8788_adc_probe,
  198. .remove = lp8788_adc_remove,
  199. .driver = {
  200. .name = LP8788_DEV_ADC,
  201. },
  202. };
  203. module_platform_driver(lp8788_adc_driver);
  204. MODULE_DESCRIPTION("Texas Instruments LP8788 ADC Driver");
  205. MODULE_AUTHOR("Milo Kim");
  206. MODULE_LICENSE("GPL");
  207. MODULE_ALIAS("platform:lp8788-adc");