Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
drivers
mfd
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
>
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
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
)
127
>>
WM831X_AUX_DATA_SRC_SHIFT
) - 1;
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 */
137
wm831x_set_bits
(wm831x,
WM831X_AUXADC_SOURCE
,
138
1 << input, 0);
139
wm831x->
auxadc_active
&= ~(1 <<
input
);
140
141
/* Turn off the entire convertor if idle */
142
if
(!wm831x->
auxadc_active
)
143
wm831x_reg_write
(wm831x,
WM831X_AUXADC_CONTROL
, 0);
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
165
ret =
wm831x_set_bits
(wm831x,
WM831X_AUXADC_CONTROL
,
166
WM831X_AUX_ENA
,
WM831X_AUX_ENA
);
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
;
174
ret =
wm831x_reg_write
(wm831x,
WM831X_AUXADC_SOURCE
,
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
181
ret =
wm831x_set_bits
(wm831x,
WM831X_AUXADC_CONTROL
,
182
WM831X_AUX_CVT_ENA
,
WM831X_AUX_CVT_ENA
);
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,
195
WM831X_INTERRUPT_STATUS_1
);
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,
205
WM831X_INTERRUPT_STATUS_1
,
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
)
224
>>
WM831X_AUX_DATA_SRC_SHIFT
) - 1;
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
:
238
wm831x_set_bits
(wm831x,
WM831X_AUXADC_CONTROL
,
WM831X_AUX_ENA
, 0);
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
}
254
EXPORT_SYMBOL_GPL
(
wm831x_auxadc_read
);
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
}
274
EXPORT_SYMBOL_GPL
(
wm831x_auxadc_read_uv
);
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,
287
WM831X_IRQ_AUXADC_DATA
),
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
}
Generated on Thu Jan 10 2013 13:54:26 for Linux Kernel by
1.8.2