wm831x-auxadc.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. /*
  2. * wm831x-auxadc.c -- AUXADC for Wolfson WM831x PMICs
  3. *
  4. * Copyright 2009-2011 Wolfson Microelectronics PLC.
  5. *
  6. * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
  7. *
  8. * This program is free software; you can redistribute it and/or modify it
  9. * under the terms of the GNU General Public License as published by the
  10. * Free Software Foundation; either version 2 of the License, or (at your
  11. * option) any later version.
  12. *
  13. */
  14. #include <linux/kernel.h>
  15. #include <linux/module.h>
  16. #include <linux/delay.h>
  17. #include <linux/mfd/core.h>
  18. #include <linux/slab.h>
  19. #include <linux/list.h>
  20. #include <linux/mfd/wm831x/core.h>
  21. #include <linux/mfd/wm831x/pdata.h>
  22. #include <linux/mfd/wm831x/irq.h>
  23. #include <linux/mfd/wm831x/auxadc.h>
  24. #include <linux/mfd/wm831x/otp.h>
  25. #include <linux/mfd/wm831x/regulator.h>
  26. struct wm831x_auxadc_req {
  27. struct list_head list;
  28. enum wm831x_auxadc input;
  29. int val;
  30. struct completion done;
  31. };
  32. static int wm831x_auxadc_read_irq(struct wm831x *wm831x,
  33. enum wm831x_auxadc input)
  34. {
  35. struct wm831x_auxadc_req *req;
  36. int ret;
  37. bool ena = false;
  38. req = kzalloc(sizeof(*req), GFP_KERNEL);
  39. if (!req)
  40. return -ENOMEM;
  41. init_completion(&req->done);
  42. req->input = input;
  43. req->val = -ETIMEDOUT;
  44. mutex_lock(&wm831x->auxadc_lock);
  45. /* Enqueue the request */
  46. list_add(&req->list, &wm831x->auxadc_pending);
  47. ena = !wm831x->auxadc_active;
  48. if (ena) {
  49. ret = wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL,
  50. WM831X_AUX_ENA, WM831X_AUX_ENA);
  51. if (ret != 0) {
  52. dev_err(wm831x->dev, "Failed to enable AUXADC: %d\n",
  53. ret);
  54. goto out;
  55. }
  56. }
  57. /* Enable the conversion if not already running */
  58. if (!(wm831x->auxadc_active & (1 << input))) {
  59. ret = wm831x_set_bits(wm831x, WM831X_AUXADC_SOURCE,
  60. 1 << input, 1 << input);
  61. if (ret != 0) {
  62. dev_err(wm831x->dev,
  63. "Failed to set AUXADC source: %d\n", ret);
  64. goto out;
  65. }
  66. wm831x->auxadc_active |= 1 << input;
  67. }
  68. /* We convert at the fastest rate possible */
  69. if (ena) {
  70. ret = wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL,
  71. WM831X_AUX_CVT_ENA |
  72. WM831X_AUX_RATE_MASK,
  73. WM831X_AUX_CVT_ENA |
  74. WM831X_AUX_RATE_MASK);
  75. if (ret != 0) {
  76. dev_err(wm831x->dev, "Failed to start AUXADC: %d\n",
  77. ret);
  78. goto out;
  79. }
  80. }
  81. mutex_unlock(&wm831x->auxadc_lock);
  82. /* Wait for an interrupt */
  83. wait_for_completion_timeout(&req->done, msecs_to_jiffies(500));
  84. mutex_lock(&wm831x->auxadc_lock);
  85. list_del(&req->list);
  86. ret = req->val;
  87. out:
  88. mutex_unlock(&wm831x->auxadc_lock);
  89. kfree(req);
  90. return ret;
  91. }
  92. static irqreturn_t wm831x_auxadc_irq(int irq, void *irq_data)
  93. {
  94. struct wm831x *wm831x = irq_data;
  95. struct wm831x_auxadc_req *req;
  96. int ret, input, val;
  97. ret = wm831x_reg_read(wm831x, WM831X_AUXADC_DATA);
  98. if (ret < 0) {
  99. dev_err(wm831x->dev,
  100. "Failed to read AUXADC data: %d\n", ret);
  101. return IRQ_NONE;
  102. }
  103. input = ((ret & WM831X_AUX_DATA_SRC_MASK)
  104. >> WM831X_AUX_DATA_SRC_SHIFT) - 1;
  105. if (input == 14)
  106. input = WM831X_AUX_CAL;
  107. val = ret & WM831X_AUX_DATA_MASK;
  108. mutex_lock(&wm831x->auxadc_lock);
  109. /* Disable this conversion, we're about to complete all users */
  110. wm831x_set_bits(wm831x, WM831X_AUXADC_SOURCE,
  111. 1 << input, 0);
  112. wm831x->auxadc_active &= ~(1 << input);
  113. /* Turn off the entire convertor if idle */
  114. if (!wm831x->auxadc_active)
  115. wm831x_reg_write(wm831x, WM831X_AUXADC_CONTROL, 0);
  116. /* Wake up any threads waiting for this request */
  117. list_for_each_entry(req, &wm831x->auxadc_pending, list) {
  118. if (req->input == input) {
  119. req->val = val;
  120. complete(&req->done);
  121. }
  122. }
  123. mutex_unlock(&wm831x->auxadc_lock);
  124. return IRQ_HANDLED;
  125. }
  126. static int wm831x_auxadc_read_polled(struct wm831x *wm831x,
  127. enum wm831x_auxadc input)
  128. {
  129. int ret, src, timeout;
  130. mutex_lock(&wm831x->auxadc_lock);
  131. ret = wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL,
  132. WM831X_AUX_ENA, WM831X_AUX_ENA);
  133. if (ret < 0) {
  134. dev_err(wm831x->dev, "Failed to enable AUXADC: %d\n", ret);
  135. goto out;
  136. }
  137. /* We force a single source at present */
  138. src = input;
  139. ret = wm831x_reg_write(wm831x, WM831X_AUXADC_SOURCE,
  140. 1 << src);
  141. if (ret < 0) {
  142. dev_err(wm831x->dev, "Failed to set AUXADC source: %d\n", ret);
  143. goto out;
  144. }
  145. ret = wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL,
  146. WM831X_AUX_CVT_ENA, WM831X_AUX_CVT_ENA);
  147. if (ret < 0) {
  148. dev_err(wm831x->dev, "Failed to start AUXADC: %d\n", ret);
  149. goto disable;
  150. }
  151. /* If we're not using interrupts then poll the
  152. * interrupt status register */
  153. timeout = 5;
  154. while (timeout) {
  155. msleep(1);
  156. ret = wm831x_reg_read(wm831x,
  157. WM831X_INTERRUPT_STATUS_1);
  158. if (ret < 0) {
  159. dev_err(wm831x->dev,
  160. "ISR 1 read failed: %d\n", ret);
  161. goto disable;
  162. }
  163. /* Did it complete? */
  164. if (ret & WM831X_AUXADC_DATA_EINT) {
  165. wm831x_reg_write(wm831x,
  166. WM831X_INTERRUPT_STATUS_1,
  167. WM831X_AUXADC_DATA_EINT);
  168. break;
  169. } else {
  170. dev_err(wm831x->dev,
  171. "AUXADC conversion timeout\n");
  172. ret = -EBUSY;
  173. goto disable;
  174. }
  175. }
  176. ret = wm831x_reg_read(wm831x, WM831X_AUXADC_DATA);
  177. if (ret < 0) {
  178. dev_err(wm831x->dev,
  179. "Failed to read AUXADC data: %d\n", ret);
  180. goto disable;
  181. }
  182. src = ((ret & WM831X_AUX_DATA_SRC_MASK)
  183. >> WM831X_AUX_DATA_SRC_SHIFT) - 1;
  184. if (src == 14)
  185. src = WM831X_AUX_CAL;
  186. if (src != input) {
  187. dev_err(wm831x->dev, "Data from source %d not %d\n",
  188. src, input);
  189. ret = -EINVAL;
  190. } else {
  191. ret &= WM831X_AUX_DATA_MASK;
  192. }
  193. disable:
  194. wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL, WM831X_AUX_ENA, 0);
  195. out:
  196. mutex_unlock(&wm831x->auxadc_lock);
  197. return ret;
  198. }
  199. /**
  200. * wm831x_auxadc_read: Read a value from the WM831x AUXADC
  201. *
  202. * @wm831x: Device to read from.
  203. * @input: AUXADC input to read.
  204. */
  205. int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input)
  206. {
  207. return wm831x->auxadc_read(wm831x, input);
  208. }
  209. EXPORT_SYMBOL_GPL(wm831x_auxadc_read);
  210. /**
  211. * wm831x_auxadc_read_uv: Read a voltage from the WM831x AUXADC
  212. *
  213. * @wm831x: Device to read from.
  214. * @input: AUXADC input to read.
  215. */
  216. int wm831x_auxadc_read_uv(struct wm831x *wm831x, enum wm831x_auxadc input)
  217. {
  218. int ret;
  219. ret = wm831x_auxadc_read(wm831x, input);
  220. if (ret < 0)
  221. return ret;
  222. ret *= 1465;
  223. return ret;
  224. }
  225. EXPORT_SYMBOL_GPL(wm831x_auxadc_read_uv);
  226. void wm831x_auxadc_init(struct wm831x *wm831x)
  227. {
  228. int ret;
  229. mutex_init(&wm831x->auxadc_lock);
  230. INIT_LIST_HEAD(&wm831x->auxadc_pending);
  231. if (wm831x->irq) {
  232. wm831x->auxadc_read = wm831x_auxadc_read_irq;
  233. ret = request_threaded_irq(wm831x_irq(wm831x,
  234. WM831X_IRQ_AUXADC_DATA),
  235. NULL, wm831x_auxadc_irq,
  236. IRQF_ONESHOT,
  237. "auxadc", wm831x);
  238. if (ret < 0) {
  239. dev_err(wm831x->dev, "AUXADC IRQ request failed: %d\n",
  240. ret);
  241. wm831x->auxadc_read = NULL;
  242. }
  243. }
  244. if (!wm831x->auxadc_read)
  245. wm831x->auxadc_read = wm831x_auxadc_read_polled;
  246. }