GNU Linux-libre 4.14.332-gnu1
[releases.git] / drivers / mfd / wm831x-auxadc.c
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
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>
25 #include <linux/mfd/wm831x/auxadc.h>
26 #include <linux/mfd/wm831x/otp.h>
27 #include <linux/mfd/wm831x/regulator.h>
28
29 struct wm831x_auxadc_req {
30         struct list_head list;
31         enum wm831x_auxadc input;
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) {
59                 ret = wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL,
60                                       WM831X_AUX_ENA, WM831X_AUX_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))) {
70                 ret = wm831x_set_bits(wm831x, WM831X_AUXADC_SOURCE,
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) {
83                 ret = wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL,
84                                       WM831X_AUX_CVT_ENA |
85                                       WM831X_AUX_RATE_MASK,
86                                       WM831X_AUX_CVT_ENA |
87                                       WM831X_AUX_RATE_MASK);
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 */
98         wait_for_completion_timeout(&req->done, msecs_to_jiffies(500));
99
100         mutex_lock(&wm831x->auxadc_lock);
101         ret = req->val;
102
103 out:
104         list_del(&req->list);
105         mutex_unlock(&wm831x->auxadc_lock);
106
107         kfree(req);
108
109         return ret;
110 }
111
112 static irqreturn_t wm831x_auxadc_irq(int irq, void *irq_data)
113 {
114         struct wm831x *wm831x = irq_data;
115         struct wm831x_auxadc_req *req;
116         int ret, input, val;
117
118         ret = wm831x_reg_read(wm831x, WM831X_AUXADC_DATA);
119         if (ret < 0) {
120                 dev_err(wm831x->dev,
121                         "Failed to read AUXADC data: %d\n", ret);
122                 return IRQ_NONE;
123         }
124
125         input = ((ret & WM831X_AUX_DATA_SRC_MASK)
126                  >> WM831X_AUX_DATA_SRC_SHIFT) - 1;
127
128         if (input == 14)
129                 input = WM831X_AUX_CAL;
130
131         val = ret & WM831X_AUX_DATA_MASK;
132
133         mutex_lock(&wm831x->auxadc_lock);
134
135         /* Disable this conversion, we're about to complete all users */
136         wm831x_set_bits(wm831x, WM831X_AUXADC_SOURCE,
137                         1 << input, 0);
138         wm831x->auxadc_active &= ~(1 << input);
139
140         /* Turn off the entire convertor if idle */
141         if (!wm831x->auxadc_active)
142                 wm831x_reg_write(wm831x, WM831X_AUXADC_CONTROL, 0);
143
144         /* Wake up any threads waiting for this request */
145         list_for_each_entry(req, &wm831x->auxadc_pending, list) {
146                 if (req->input == input) {
147                         req->val = val;
148                         complete(&req->done);
149                 }
150         }
151
152         mutex_unlock(&wm831x->auxadc_lock);
153
154         return IRQ_HANDLED;
155 }
156
157 static int wm831x_auxadc_read_polled(struct wm831x *wm831x,
158                                      enum wm831x_auxadc input)
159 {
160         int ret, src, timeout;
161
162         mutex_lock(&wm831x->auxadc_lock);
163
164         ret = wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL,
165                               WM831X_AUX_ENA, WM831X_AUX_ENA);
166         if (ret < 0) {
167                 dev_err(wm831x->dev, "Failed to enable AUXADC: %d\n", ret);
168                 goto out;
169         }
170
171         /* We force a single source at present */
172         src = input;
173         ret = wm831x_reg_write(wm831x, WM831X_AUXADC_SOURCE,
174                                1 << src);
175         if (ret < 0) {
176                 dev_err(wm831x->dev, "Failed to set AUXADC source: %d\n", ret);
177                 goto out;
178         }
179
180         ret = wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL,
181                               WM831X_AUX_CVT_ENA, WM831X_AUX_CVT_ENA);
182         if (ret < 0) {
183                 dev_err(wm831x->dev, "Failed to start AUXADC: %d\n", ret);
184                 goto disable;
185         }
186
187         /* If we're not using interrupts then poll the
188          * interrupt status register */
189         timeout = 5;
190         while (timeout) {
191                 msleep(1);
192
193                 ret = wm831x_reg_read(wm831x,
194                                       WM831X_INTERRUPT_STATUS_1);
195                 if (ret < 0) {
196                         dev_err(wm831x->dev,
197                                 "ISR 1 read failed: %d\n", ret);
198                         goto disable;
199                 }
200
201                 /* Did it complete? */
202                 if (ret & WM831X_AUXADC_DATA_EINT) {
203                         wm831x_reg_write(wm831x,
204                                          WM831X_INTERRUPT_STATUS_1,
205                                          WM831X_AUXADC_DATA_EINT);
206                         break;
207                 } else {
208                         dev_err(wm831x->dev,
209                                 "AUXADC conversion timeout\n");
210                         ret = -EBUSY;
211                         goto disable;
212                 }
213         }
214
215         ret = wm831x_reg_read(wm831x, WM831X_AUXADC_DATA);
216         if (ret < 0) {
217                 dev_err(wm831x->dev,
218                         "Failed to read AUXADC data: %d\n", ret);
219                 goto disable;
220         }
221
222         src = ((ret & WM831X_AUX_DATA_SRC_MASK)
223                >> WM831X_AUX_DATA_SRC_SHIFT) - 1;
224
225         if (src == 14)
226                 src = WM831X_AUX_CAL;
227
228         if (src != input) {
229                 dev_err(wm831x->dev, "Data from source %d not %d\n",
230                         src, input);
231                 ret = -EINVAL;
232         } else {
233                 ret &= WM831X_AUX_DATA_MASK;
234         }
235
236 disable:
237         wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL, WM831X_AUX_ENA, 0);
238 out:
239         mutex_unlock(&wm831x->auxadc_lock);
240         return ret;
241 }
242
243 /**
244  * wm831x_auxadc_read: Read a value from the WM831x AUXADC
245  *
246  * @wm831x: Device to read from.
247  * @input: AUXADC input to read.
248  */
249 int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input)
250 {
251         return wm831x->auxadc_read(wm831x, input);
252 }
253 EXPORT_SYMBOL_GPL(wm831x_auxadc_read);
254
255 /**
256  * wm831x_auxadc_read_uv: Read a voltage from the WM831x AUXADC
257  *
258  * @wm831x: Device to read from.
259  * @input: AUXADC input to read.
260  */
261 int wm831x_auxadc_read_uv(struct wm831x *wm831x, enum wm831x_auxadc input)
262 {
263         int ret;
264
265         ret = wm831x_auxadc_read(wm831x, input);
266         if (ret < 0)
267                 return ret;
268
269         ret *= 1465;
270
271         return ret;
272 }
273 EXPORT_SYMBOL_GPL(wm831x_auxadc_read_uv);
274
275 void wm831x_auxadc_init(struct wm831x *wm831x)
276 {
277         int ret;
278
279         mutex_init(&wm831x->auxadc_lock);
280         INIT_LIST_HEAD(&wm831x->auxadc_pending);
281
282         if (wm831x->irq) {
283                 wm831x->auxadc_read = wm831x_auxadc_read_irq;
284
285                 ret = request_threaded_irq(wm831x_irq(wm831x,
286                                                       WM831X_IRQ_AUXADC_DATA),
287                                            NULL, wm831x_auxadc_irq,
288                                            IRQF_ONESHOT,
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 }