Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
wm831x-auxadc.c
Go to the documentation of this file.
1 /*
2  * wm831x-auxadc.c -- AUXADC for Wolfson WM831x PMICs
3  *
4  * Copyright 2009-2011 Wolfson Microelectronics PLC.
5  *
6  * Author: Mark Brown <[email protected]>
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 
15 #include <linux/kernel.h>
16 #include <linux/module.h>
17 #include <linux/delay.h>
18 #include <linux/mfd/core.h>
19 #include <linux/slab.h>
20 #include <linux/list.h>
21 
22 #include <linux/mfd/wm831x/core.h>
23 #include <linux/mfd/wm831x/pdata.h>
24 #include <linux/mfd/wm831x/irq.h>
26 #include <linux/mfd/wm831x/otp.h>
28 
30  struct list_head list;
32  int val;
33  struct completion done;
34 };
35 
36 static int wm831x_auxadc_read_irq(struct wm831x *wm831x,
37  enum wm831x_auxadc input)
38 {
39  struct wm831x_auxadc_req *req;
40  int ret;
41  bool ena = false;
42 
43  req = kzalloc(sizeof(*req), GFP_KERNEL);
44  if (!req)
45  return -ENOMEM;
46 
47  init_completion(&req->done);
48  req->input = input;
49  req->val = -ETIMEDOUT;
50 
51  mutex_lock(&wm831x->auxadc_lock);
52 
53  /* Enqueue the request */
54  list_add(&req->list, &wm831x->auxadc_pending);
55 
56  ena = !wm831x->auxadc_active;
57 
58  if (ena) {
61  if (ret != 0) {
62  dev_err(wm831x->dev, "Failed to enable AUXADC: %d\n",
63  ret);
64  goto out;
65  }
66  }
67 
68  /* Enable the conversion if not already running */
69  if (!(wm831x->auxadc_active & (1 << input))) {
71  1 << input, 1 << input);
72  if (ret != 0) {
73  dev_err(wm831x->dev,
74  "Failed to set AUXADC source: %d\n", ret);
75  goto out;
76  }
77 
78  wm831x->auxadc_active |= 1 << input;
79  }
80 
81  /* We convert at the fastest rate possible */
82  if (ena) {
88  if (ret != 0) {
89  dev_err(wm831x->dev, "Failed to start AUXADC: %d\n",
90  ret);
91  goto out;
92  }
93  }
94 
95  mutex_unlock(&wm831x->auxadc_lock);
96 
97  /* Wait for an interrupt */
99 
100  mutex_lock(&wm831x->auxadc_lock);
101 
102  list_del(&req->list);
103  ret = req->val;
104 
105 out:
106  mutex_unlock(&wm831x->auxadc_lock);
107 
108  kfree(req);
109 
110  return ret;
111 }
112 
113 static irqreturn_t wm831x_auxadc_irq(int irq, void *irq_data)
114 {
115  struct wm831x *wm831x = irq_data;
116  struct wm831x_auxadc_req *req;
117  int ret, input, val;
118 
119  ret = wm831x_reg_read(wm831x, WM831X_AUXADC_DATA);
120  if (ret < 0) {
121  dev_err(wm831x->dev,
122  "Failed to read AUXADC data: %d\n", ret);
123  return IRQ_NONE;
124  }
125 
126  input = ((ret & WM831X_AUX_DATA_SRC_MASK)
128 
129  if (input == 14)
130  input = WM831X_AUX_CAL;
131 
132  val = ret & WM831X_AUX_DATA_MASK;
133 
134  mutex_lock(&wm831x->auxadc_lock);
135 
136  /* Disable this conversion, we're about to complete all users */
138  1 << input, 0);
139  wm831x->auxadc_active &= ~(1 << input);
140 
141  /* Turn off the entire convertor if idle */
142  if (!wm831x->auxadc_active)
144 
145  /* Wake up any threads waiting for this request */
146  list_for_each_entry(req, &wm831x->auxadc_pending, list) {
147  if (req->input == input) {
148  req->val = val;
149  complete(&req->done);
150  }
151  }
152 
153  mutex_unlock(&wm831x->auxadc_lock);
154 
155  return IRQ_HANDLED;
156 }
157 
158 static int wm831x_auxadc_read_polled(struct wm831x *wm831x,
159  enum wm831x_auxadc input)
160 {
161  int ret, src, timeout;
162 
163  mutex_lock(&wm831x->auxadc_lock);
164 
167  if (ret < 0) {
168  dev_err(wm831x->dev, "Failed to enable AUXADC: %d\n", ret);
169  goto out;
170  }
171 
172  /* We force a single source at present */
173  src = input;
175  1 << src);
176  if (ret < 0) {
177  dev_err(wm831x->dev, "Failed to set AUXADC source: %d\n", ret);
178  goto out;
179  }
180 
183  if (ret < 0) {
184  dev_err(wm831x->dev, "Failed to start AUXADC: %d\n", ret);
185  goto disable;
186  }
187 
188  /* If we're not using interrupts then poll the
189  * interrupt status register */
190  timeout = 5;
191  while (timeout) {
192  msleep(1);
193 
194  ret = wm831x_reg_read(wm831x,
196  if (ret < 0) {
197  dev_err(wm831x->dev,
198  "ISR 1 read failed: %d\n", ret);
199  goto disable;
200  }
201 
202  /* Did it complete? */
203  if (ret & WM831X_AUXADC_DATA_EINT) {
204  wm831x_reg_write(wm831x,
206  WM831X_AUXADC_DATA_EINT);
207  break;
208  } else {
209  dev_err(wm831x->dev,
210  "AUXADC conversion timeout\n");
211  ret = -EBUSY;
212  goto disable;
213  }
214  }
215 
216  ret = wm831x_reg_read(wm831x, WM831X_AUXADC_DATA);
217  if (ret < 0) {
218  dev_err(wm831x->dev,
219  "Failed to read AUXADC data: %d\n", ret);
220  goto disable;
221  }
222 
223  src = ((ret & WM831X_AUX_DATA_SRC_MASK)
225 
226  if (src == 14)
227  src = WM831X_AUX_CAL;
228 
229  if (src != input) {
230  dev_err(wm831x->dev, "Data from source %d not %d\n",
231  src, input);
232  ret = -EINVAL;
233  } else {
234  ret &= WM831X_AUX_DATA_MASK;
235  }
236 
237 disable:
239 out:
240  mutex_unlock(&wm831x->auxadc_lock);
241  return ret;
242 }
243 
250 int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input)
251 {
252  return wm831x->auxadc_read(wm831x, input);
253 }
255 
262 int wm831x_auxadc_read_uv(struct wm831x *wm831x, enum wm831x_auxadc input)
263 {
264  int ret;
265 
266  ret = wm831x_auxadc_read(wm831x, input);
267  if (ret < 0)
268  return ret;
269 
270  ret *= 1465;
271 
272  return ret;
273 }
275 
276 void wm831x_auxadc_init(struct wm831x *wm831x)
277 {
278  int ret;
279 
280  mutex_init(&wm831x->auxadc_lock);
281  INIT_LIST_HEAD(&wm831x->auxadc_pending);
282 
283  if (wm831x->irq) {
284  wm831x->auxadc_read = wm831x_auxadc_read_irq;
285 
286  ret = request_threaded_irq(wm831x_irq(wm831x,
288  NULL, wm831x_auxadc_irq, 0,
289  "auxadc", wm831x);
290  if (ret < 0) {
291  dev_err(wm831x->dev, "AUXADC IRQ request failed: %d\n",
292  ret);
293  wm831x->auxadc_read = NULL;
294  }
295  }
296 
297  if (!wm831x->auxadc_read)
298  wm831x->auxadc_read = wm831x_auxadc_read_polled;
299 }