diff options
author | H. Nikolaus Schaller <hns@goldelico.com> | 2015-10-16 08:53:38 -0400 |
---|---|---|
committer | Jonathan Cameron <jic23@kernel.org> | 2015-10-25 08:02:41 -0400 |
commit | e08e19c331fb249e6dc86365ee80d16045c4aeb1 (patch) | |
tree | 4981f2fae39537788f0da5a1b39a65395b231755 | |
parent | 75b6548f1793c7a79a8b063cd575df9c04dcc122 (diff) |
iio:adc: add iio driver for Palmas (twl6035/7) gpadc
This driver code was found as:
https://android.googlesource.com/kernel/tegra/+/aaabb2e045f31e5a970109ffdaae900dd403d17e/drivers/staging/iio/adc
Fixed various compilation issues and test this driver on omap5 evm.
Signed-off-by: Pradeep Goudagunta <pgoudagunta@nvidia.com>
Signed-off-by: H. Nikolaus Schaller <hns@goldelico.com>
Signed-off-by: Marek Belisko <marek@goldelico.com>
Acked-by: Laxman Dewangan <ldewangan@nvidia.com>
Reviewed-by: Jonathan Cameron <jic23@kernel.org>
Acked-by: Lee Jones <lee.jones@linaro.org>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
-rw-r--r-- | drivers/iio/adc/Kconfig | 8 | ||||
-rw-r--r-- | drivers/iio/adc/Makefile | 1 | ||||
-rw-r--r-- | drivers/iio/adc/palmas_gpadc.c | 817 | ||||
-rw-r--r-- | include/linux/mfd/palmas.h | 75 |
4 files changed, 877 insertions, 24 deletions
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 7868c744fd4b..daad72e1266d 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig | |||
@@ -275,6 +275,14 @@ config NAU7802 | |||
275 | To compile this driver as a module, choose M here: the | 275 | To compile this driver as a module, choose M here: the |
276 | module will be called nau7802. | 276 | module will be called nau7802. |
277 | 277 | ||
278 | config PALMAS_GPADC | ||
279 | tristate "TI Palmas General Purpose ADC" | ||
280 | depends on MFD_PALMAS | ||
281 | help | ||
282 | Palmas series pmic chip by Texas Instruments (twl6035/6037) | ||
283 | is used in smartphones and tablets and supports a 16 channel | ||
284 | general purpose ADC. | ||
285 | |||
278 | config QCOM_SPMI_IADC | 286 | config QCOM_SPMI_IADC |
279 | tristate "Qualcomm SPMI PMIC current ADC" | 287 | tristate "Qualcomm SPMI PMIC current ADC" |
280 | depends on SPMI | 288 | depends on SPMI |
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 99b37a963a1e..11cfdfd76798 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile | |||
@@ -27,6 +27,7 @@ obj-$(CONFIG_MCP320X) += mcp320x.o | |||
27 | obj-$(CONFIG_MCP3422) += mcp3422.o | 27 | obj-$(CONFIG_MCP3422) += mcp3422.o |
28 | obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o | 28 | obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o |
29 | obj-$(CONFIG_NAU7802) += nau7802.o | 29 | obj-$(CONFIG_NAU7802) += nau7802.o |
30 | obj-$(CONFIG_PALMAS_GPADC) += palmas_gpadc.o | ||
30 | obj-$(CONFIG_QCOM_SPMI_IADC) += qcom-spmi-iadc.o | 31 | obj-$(CONFIG_QCOM_SPMI_IADC) += qcom-spmi-iadc.o |
31 | obj-$(CONFIG_QCOM_SPMI_VADC) += qcom-spmi-vadc.o | 32 | obj-$(CONFIG_QCOM_SPMI_VADC) += qcom-spmi-vadc.o |
32 | obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o | 33 | obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o |
diff --git a/drivers/iio/adc/palmas_gpadc.c b/drivers/iio/adc/palmas_gpadc.c new file mode 100644 index 000000000000..71763c5da2ab --- /dev/null +++ b/drivers/iio/adc/palmas_gpadc.c | |||
@@ -0,0 +1,817 @@ | |||
1 | /* | ||
2 | * palmas-adc.c -- TI PALMAS GPADC. | ||
3 | * | ||
4 | * Copyright (c) 2013, NVIDIA Corporation. All rights reserved. | ||
5 | * | ||
6 | * Author: Pradeep Goudagunta <pgoudagunta@nvidia.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License as | ||
10 | * published by the Free Software Foundation version 2. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/err.h> | ||
15 | #include <linux/irq.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/slab.h> | ||
19 | #include <linux/delay.h> | ||
20 | #include <linux/i2c.h> | ||
21 | #include <linux/pm.h> | ||
22 | #include <linux/mfd/palmas.h> | ||
23 | #include <linux/completion.h> | ||
24 | #include <linux/iio/iio.h> | ||
25 | #include <linux/iio/machine.h> | ||
26 | #include <linux/iio/driver.h> | ||
27 | |||
28 | #define MOD_NAME "palmas-gpadc" | ||
29 | #define PALMAS_ADC_CONVERSION_TIMEOUT (msecs_to_jiffies(5000)) | ||
30 | #define PALMAS_TO_BE_CALCULATED 0 | ||
31 | #define PALMAS_GPADC_TRIMINVALID -1 | ||
32 | |||
33 | struct palmas_gpadc_info { | ||
34 | /* calibration codes and regs */ | ||
35 | int x1; /* lower ideal code */ | ||
36 | int x2; /* higher ideal code */ | ||
37 | int v1; /* expected lower volt reading */ | ||
38 | int v2; /* expected higher volt reading */ | ||
39 | u8 trim1_reg; /* register number for lower trim */ | ||
40 | u8 trim2_reg; /* register number for upper trim */ | ||
41 | int gain; /* calculated from above (after reading trim regs) */ | ||
42 | int offset; /* calculated from above (after reading trim regs) */ | ||
43 | int gain_error; /* calculated from above (after reading trim regs) */ | ||
44 | bool is_uncalibrated; /* if channel has calibration data */ | ||
45 | }; | ||
46 | |||
47 | #define PALMAS_ADC_INFO(_chan, _x1, _x2, _v1, _v2, _t1, _t2, _is_uncalibrated) \ | ||
48 | [PALMAS_ADC_CH_##_chan] = { \ | ||
49 | .x1 = _x1, \ | ||
50 | .x2 = _x2, \ | ||
51 | .v1 = _v1, \ | ||
52 | .v2 = _v2, \ | ||
53 | .gain = PALMAS_TO_BE_CALCULATED, \ | ||
54 | .offset = PALMAS_TO_BE_CALCULATED, \ | ||
55 | .gain_error = PALMAS_TO_BE_CALCULATED, \ | ||
56 | .trim1_reg = PALMAS_GPADC_TRIM##_t1, \ | ||
57 | .trim2_reg = PALMAS_GPADC_TRIM##_t2, \ | ||
58 | .is_uncalibrated = _is_uncalibrated \ | ||
59 | } | ||
60 | |||
61 | static struct palmas_gpadc_info palmas_gpadc_info[] = { | ||
62 | PALMAS_ADC_INFO(IN0, 2064, 3112, 630, 950, 1, 2, false), | ||
63 | PALMAS_ADC_INFO(IN1, 2064, 3112, 630, 950, 1, 2, false), | ||
64 | PALMAS_ADC_INFO(IN2, 2064, 3112, 1260, 1900, 3, 4, false), | ||
65 | PALMAS_ADC_INFO(IN3, 2064, 3112, 630, 950, 1, 2, false), | ||
66 | PALMAS_ADC_INFO(IN4, 2064, 3112, 630, 950, 1, 2, false), | ||
67 | PALMAS_ADC_INFO(IN5, 2064, 3112, 630, 950, 1, 2, false), | ||
68 | PALMAS_ADC_INFO(IN6, 2064, 3112, 2520, 3800, 5, 6, false), | ||
69 | PALMAS_ADC_INFO(IN7, 2064, 3112, 2520, 3800, 7, 8, false), | ||
70 | PALMAS_ADC_INFO(IN8, 2064, 3112, 3150, 4750, 9, 10, false), | ||
71 | PALMAS_ADC_INFO(IN9, 2064, 3112, 5670, 8550, 11, 12, false), | ||
72 | PALMAS_ADC_INFO(IN10, 2064, 3112, 3465, 5225, 13, 14, false), | ||
73 | PALMAS_ADC_INFO(IN11, 0, 0, 0, 0, INVALID, INVALID, true), | ||
74 | PALMAS_ADC_INFO(IN12, 0, 0, 0, 0, INVALID, INVALID, true), | ||
75 | PALMAS_ADC_INFO(IN13, 0, 0, 0, 0, INVALID, INVALID, true), | ||
76 | PALMAS_ADC_INFO(IN14, 2064, 3112, 3645, 5225, 15, 16, false), | ||
77 | PALMAS_ADC_INFO(IN15, 0, 0, 0, 0, INVALID, INVALID, true), | ||
78 | }; | ||
79 | |||
80 | /** | ||
81 | * struct palmas_gpadc - the palmas_gpadc structure | ||
82 | * @ch0_current: channel 0 current source setting | ||
83 | * 0: 0 uA | ||
84 | * 1: 5 uA | ||
85 | * 2: 15 uA | ||
86 | * 3: 20 uA | ||
87 | * @ch3_current: channel 0 current source setting | ||
88 | * 0: 0 uA | ||
89 | * 1: 10 uA | ||
90 | * 2: 400 uA | ||
91 | * 3: 800 uA | ||
92 | * @extended_delay: enable the gpadc extended delay mode | ||
93 | * @auto_conversion_period: define the auto_conversion_period | ||
94 | * | ||
95 | * This is the palmas_gpadc structure to store run-time information | ||
96 | * and pointers for this driver instance. | ||
97 | */ | ||
98 | |||
99 | struct palmas_gpadc { | ||
100 | struct device *dev; | ||
101 | struct palmas *palmas; | ||
102 | u8 ch0_current; | ||
103 | u8 ch3_current; | ||
104 | bool extended_delay; | ||
105 | int irq; | ||
106 | int irq_auto_0; | ||
107 | int irq_auto_1; | ||
108 | struct palmas_gpadc_info *adc_info; | ||
109 | struct completion conv_completion; | ||
110 | struct palmas_adc_wakeup_property wakeup1_data; | ||
111 | struct palmas_adc_wakeup_property wakeup2_data; | ||
112 | bool wakeup1_enable; | ||
113 | bool wakeup2_enable; | ||
114 | int auto_conversion_period; | ||
115 | }; | ||
116 | |||
117 | /* | ||
118 | * GPADC lock issue in AUTO mode. | ||
119 | * Impact: In AUTO mode, GPADC conversion can be locked after disabling AUTO | ||
120 | * mode feature. | ||
121 | * Details: | ||
122 | * When the AUTO mode is the only conversion mode enabled, if the AUTO | ||
123 | * mode feature is disabled with bit GPADC_AUTO_CTRL. AUTO_CONV1_EN = 0 | ||
124 | * or bit GPADC_AUTO_CTRL. AUTO_CONV0_EN = 0 during a conversion, the | ||
125 | * conversion mechanism can be seen as locked meaning that all following | ||
126 | * conversion will give 0 as a result. Bit GPADC_STATUS.GPADC_AVAILABLE | ||
127 | * will stay at 0 meaning that GPADC is busy. An RT conversion can unlock | ||
128 | * the GPADC. | ||
129 | * | ||
130 | * Workaround(s): | ||
131 | * To avoid the lock mechanism, the workaround to follow before any stop | ||
132 | * conversion request is: | ||
133 | * Force the GPADC state machine to be ON by using the GPADC_CTRL1. | ||
134 | * GPADC_FORCE bit = 1 | ||
135 | * Shutdown the GPADC AUTO conversion using | ||
136 | * GPADC_AUTO_CTRL.SHUTDOWN_CONV[01] = 0. | ||
137 | * After 100us, force the GPADC state machine to be OFF by using the | ||
138 | * GPADC_CTRL1. GPADC_FORCE bit = 0 | ||
139 | */ | ||
140 | |||
141 | static int palmas_disable_auto_conversion(struct palmas_gpadc *adc) | ||
142 | { | ||
143 | int ret; | ||
144 | |||
145 | ret = palmas_update_bits(adc->palmas, PALMAS_GPADC_BASE, | ||
146 | PALMAS_GPADC_CTRL1, | ||
147 | PALMAS_GPADC_CTRL1_GPADC_FORCE, | ||
148 | PALMAS_GPADC_CTRL1_GPADC_FORCE); | ||
149 | if (ret < 0) { | ||
150 | dev_err(adc->dev, "GPADC_CTRL1 update failed: %d\n", ret); | ||
151 | return ret; | ||
152 | } | ||
153 | |||
154 | ret = palmas_update_bits(adc->palmas, PALMAS_GPADC_BASE, | ||
155 | PALMAS_GPADC_AUTO_CTRL, | ||
156 | PALMAS_GPADC_AUTO_CTRL_SHUTDOWN_CONV1 | | ||
157 | PALMAS_GPADC_AUTO_CTRL_SHUTDOWN_CONV0, | ||
158 | 0); | ||
159 | if (ret < 0) { | ||
160 | dev_err(adc->dev, "AUTO_CTRL update failed: %d\n", ret); | ||
161 | return ret; | ||
162 | } | ||
163 | |||
164 | udelay(100); | ||
165 | |||
166 | ret = palmas_update_bits(adc->palmas, PALMAS_GPADC_BASE, | ||
167 | PALMAS_GPADC_CTRL1, | ||
168 | PALMAS_GPADC_CTRL1_GPADC_FORCE, 0); | ||
169 | if (ret < 0) | ||
170 | dev_err(adc->dev, "GPADC_CTRL1 update failed: %d\n", ret); | ||
171 | |||
172 | return ret; | ||
173 | } | ||
174 | |||
175 | static irqreturn_t palmas_gpadc_irq(int irq, void *data) | ||
176 | { | ||
177 | struct palmas_gpadc *adc = data; | ||
178 | |||
179 | complete(&adc->conv_completion); | ||
180 | |||
181 | return IRQ_HANDLED; | ||
182 | } | ||
183 | |||
184 | static irqreturn_t palmas_gpadc_irq_auto(int irq, void *data) | ||
185 | { | ||
186 | struct palmas_gpadc *adc = data; | ||
187 | |||
188 | dev_dbg(adc->dev, "Threshold interrupt %d occurs\n", irq); | ||
189 | palmas_disable_auto_conversion(adc); | ||
190 | |||
191 | return IRQ_HANDLED; | ||
192 | } | ||
193 | |||
194 | static int palmas_gpadc_start_mask_interrupt(struct palmas_gpadc *adc, | ||
195 | bool mask) | ||
196 | { | ||
197 | int ret; | ||
198 | |||
199 | if (!mask) | ||
200 | ret = palmas_update_bits(adc->palmas, PALMAS_INTERRUPT_BASE, | ||
201 | PALMAS_INT3_MASK, | ||
202 | PALMAS_INT3_MASK_GPADC_EOC_SW, 0); | ||
203 | else | ||
204 | ret = palmas_update_bits(adc->palmas, PALMAS_INTERRUPT_BASE, | ||
205 | PALMAS_INT3_MASK, | ||
206 | PALMAS_INT3_MASK_GPADC_EOC_SW, | ||
207 | PALMAS_INT3_MASK_GPADC_EOC_SW); | ||
208 | if (ret < 0) | ||
209 | dev_err(adc->dev, "GPADC INT MASK update failed: %d\n", ret); | ||
210 | |||
211 | return ret; | ||
212 | } | ||
213 | |||
214 | static int palmas_gpadc_enable(struct palmas_gpadc *adc, int adc_chan, | ||
215 | int enable) | ||
216 | { | ||
217 | unsigned int mask, val; | ||
218 | int ret; | ||
219 | |||
220 | if (enable) { | ||
221 | val = (adc->extended_delay | ||
222 | << PALMAS_GPADC_RT_CTRL_EXTEND_DELAY_SHIFT); | ||
223 | ret = palmas_update_bits(adc->palmas, PALMAS_GPADC_BASE, | ||
224 | PALMAS_GPADC_RT_CTRL, | ||
225 | PALMAS_GPADC_RT_CTRL_EXTEND_DELAY, val); | ||
226 | if (ret < 0) { | ||
227 | dev_err(adc->dev, "RT_CTRL update failed: %d\n", ret); | ||
228 | return ret; | ||
229 | } | ||
230 | |||
231 | mask = (PALMAS_GPADC_CTRL1_CURRENT_SRC_CH0_MASK | | ||
232 | PALMAS_GPADC_CTRL1_CURRENT_SRC_CH3_MASK | | ||
233 | PALMAS_GPADC_CTRL1_GPADC_FORCE); | ||
234 | val = (adc->ch0_current | ||
235 | << PALMAS_GPADC_CTRL1_CURRENT_SRC_CH0_SHIFT); | ||
236 | val |= (adc->ch3_current | ||
237 | << PALMAS_GPADC_CTRL1_CURRENT_SRC_CH3_SHIFT); | ||
238 | val |= PALMAS_GPADC_CTRL1_GPADC_FORCE; | ||
239 | ret = palmas_update_bits(adc->palmas, PALMAS_GPADC_BASE, | ||
240 | PALMAS_GPADC_CTRL1, mask, val); | ||
241 | if (ret < 0) { | ||
242 | dev_err(adc->dev, | ||
243 | "Failed to update current setting: %d\n", ret); | ||
244 | return ret; | ||
245 | } | ||
246 | |||
247 | mask = (PALMAS_GPADC_SW_SELECT_SW_CONV0_SEL_MASK | | ||
248 | PALMAS_GPADC_SW_SELECT_SW_CONV_EN); | ||
249 | val = (adc_chan | PALMAS_GPADC_SW_SELECT_SW_CONV_EN); | ||
250 | ret = palmas_update_bits(adc->palmas, PALMAS_GPADC_BASE, | ||
251 | PALMAS_GPADC_SW_SELECT, mask, val); | ||
252 | if (ret < 0) { | ||
253 | dev_err(adc->dev, "SW_SELECT update failed: %d\n", ret); | ||
254 | return ret; | ||
255 | } | ||
256 | } else { | ||
257 | ret = palmas_write(adc->palmas, PALMAS_GPADC_BASE, | ||
258 | PALMAS_GPADC_SW_SELECT, 0); | ||
259 | if (ret < 0) | ||
260 | dev_err(adc->dev, "SW_SELECT write failed: %d\n", ret); | ||
261 | |||
262 | ret = palmas_update_bits(adc->palmas, PALMAS_GPADC_BASE, | ||
263 | PALMAS_GPADC_CTRL1, | ||
264 | PALMAS_GPADC_CTRL1_GPADC_FORCE, 0); | ||
265 | if (ret < 0) { | ||
266 | dev_err(adc->dev, "CTRL1 update failed: %d\n", ret); | ||
267 | return ret; | ||
268 | } | ||
269 | } | ||
270 | |||
271 | return ret; | ||
272 | } | ||
273 | |||
274 | static int palmas_gpadc_read_prepare(struct palmas_gpadc *adc, int adc_chan) | ||
275 | { | ||
276 | int ret; | ||
277 | |||
278 | ret = palmas_gpadc_enable(adc, adc_chan, true); | ||
279 | if (ret < 0) | ||
280 | return ret; | ||
281 | |||
282 | return palmas_gpadc_start_mask_interrupt(adc, 0); | ||
283 | } | ||
284 | |||
285 | static void palmas_gpadc_read_done(struct palmas_gpadc *adc, int adc_chan) | ||
286 | { | ||
287 | palmas_gpadc_start_mask_interrupt(adc, 1); | ||
288 | palmas_gpadc_enable(adc, adc_chan, false); | ||
289 | } | ||
290 | |||
291 | static int palmas_gpadc_calibrate(struct palmas_gpadc *adc, int adc_chan) | ||
292 | { | ||
293 | int k; | ||
294 | int d1; | ||
295 | int d2; | ||
296 | int ret; | ||
297 | int gain; | ||
298 | int x1 = adc->adc_info[adc_chan].x1; | ||
299 | int x2 = adc->adc_info[adc_chan].x2; | ||
300 | int v1 = adc->adc_info[adc_chan].v1; | ||
301 | int v2 = adc->adc_info[adc_chan].v2; | ||
302 | |||
303 | ret = palmas_read(adc->palmas, PALMAS_TRIM_GPADC_BASE, | ||
304 | adc->adc_info[adc_chan].trim1_reg, &d1); | ||
305 | if (ret < 0) { | ||
306 | dev_err(adc->dev, "TRIM read failed: %d\n", ret); | ||
307 | goto scrub; | ||
308 | } | ||
309 | |||
310 | ret = palmas_read(adc->palmas, PALMAS_TRIM_GPADC_BASE, | ||
311 | adc->adc_info[adc_chan].trim2_reg, &d2); | ||
312 | if (ret < 0) { | ||
313 | dev_err(adc->dev, "TRIM read failed: %d\n", ret); | ||
314 | goto scrub; | ||
315 | } | ||
316 | |||
317 | /* gain error calculation */ | ||
318 | k = (1000 + (1000 * (d2 - d1)) / (x2 - x1)); | ||
319 | |||
320 | /* gain calculation */ | ||
321 | gain = ((v2 - v1) * 1000) / (x2 - x1); | ||
322 | |||
323 | adc->adc_info[adc_chan].gain_error = k; | ||
324 | adc->adc_info[adc_chan].gain = gain; | ||
325 | /* offset Calculation */ | ||
326 | adc->adc_info[adc_chan].offset = (d1 * 1000) - ((k - 1000) * x1); | ||
327 | |||
328 | scrub: | ||
329 | return ret; | ||
330 | } | ||
331 | |||
332 | static int palmas_gpadc_start_conversion(struct palmas_gpadc *adc, int adc_chan) | ||
333 | { | ||
334 | unsigned int val; | ||
335 | int ret; | ||
336 | |||
337 | init_completion(&adc->conv_completion); | ||
338 | ret = palmas_update_bits(adc->palmas, PALMAS_GPADC_BASE, | ||
339 | PALMAS_GPADC_SW_SELECT, | ||
340 | PALMAS_GPADC_SW_SELECT_SW_START_CONV0, | ||
341 | PALMAS_GPADC_SW_SELECT_SW_START_CONV0); | ||
342 | if (ret < 0) { | ||
343 | dev_err(adc->dev, "SELECT_SW_START write failed: %d\n", ret); | ||
344 | return ret; | ||
345 | } | ||
346 | |||
347 | ret = wait_for_completion_timeout(&adc->conv_completion, | ||
348 | PALMAS_ADC_CONVERSION_TIMEOUT); | ||
349 | if (ret == 0) { | ||
350 | dev_err(adc->dev, "conversion not completed\n"); | ||
351 | return -ETIMEDOUT; | ||
352 | } | ||
353 | |||
354 | ret = palmas_bulk_read(adc->palmas, PALMAS_GPADC_BASE, | ||
355 | PALMAS_GPADC_SW_CONV0_LSB, &val, 2); | ||
356 | if (ret < 0) { | ||
357 | dev_err(adc->dev, "SW_CONV0_LSB read failed: %d\n", ret); | ||
358 | return ret; | ||
359 | } | ||
360 | |||
361 | ret = val & 0xFFF; | ||
362 | |||
363 | return ret; | ||
364 | } | ||
365 | |||
366 | static int palmas_gpadc_get_calibrated_code(struct palmas_gpadc *adc, | ||
367 | int adc_chan, int val) | ||
368 | { | ||
369 | if (!adc->adc_info[adc_chan].is_uncalibrated) | ||
370 | val = (val*1000 - adc->adc_info[adc_chan].offset) / | ||
371 | adc->adc_info[adc_chan].gain_error; | ||
372 | |||
373 | if (val < 0) { | ||
374 | dev_err(adc->dev, "Mismatch with calibration\n"); | ||
375 | return 0; | ||
376 | } | ||
377 | |||
378 | val = (val * adc->adc_info[adc_chan].gain) / 1000; | ||
379 | |||
380 | return val; | ||
381 | } | ||
382 | |||
383 | static int palmas_gpadc_read_raw(struct iio_dev *indio_dev, | ||
384 | struct iio_chan_spec const *chan, int *val, int *val2, long mask) | ||
385 | { | ||
386 | struct palmas_gpadc *adc = iio_priv(indio_dev); | ||
387 | int adc_chan = chan->channel; | ||
388 | int ret = 0; | ||
389 | |||
390 | if (adc_chan > PALMAS_ADC_CH_MAX) | ||
391 | return -EINVAL; | ||
392 | |||
393 | mutex_lock(&indio_dev->mlock); | ||
394 | |||
395 | switch (mask) { | ||
396 | case IIO_CHAN_INFO_RAW: | ||
397 | case IIO_CHAN_INFO_PROCESSED: | ||
398 | ret = palmas_gpadc_read_prepare(adc, adc_chan); | ||
399 | if (ret < 0) | ||
400 | goto out; | ||
401 | |||
402 | ret = palmas_gpadc_start_conversion(adc, adc_chan); | ||
403 | if (ret < 0) { | ||
404 | dev_err(adc->dev, | ||
405 | "ADC start conversion failed\n"); | ||
406 | goto out; | ||
407 | } | ||
408 | |||
409 | if (mask == IIO_CHAN_INFO_PROCESSED) | ||
410 | ret = palmas_gpadc_get_calibrated_code( | ||
411 | adc, adc_chan, ret); | ||
412 | |||
413 | *val = ret; | ||
414 | |||
415 | ret = IIO_VAL_INT; | ||
416 | goto out; | ||
417 | } | ||
418 | |||
419 | mutex_unlock(&indio_dev->mlock); | ||
420 | return ret; | ||
421 | |||
422 | out: | ||
423 | palmas_gpadc_read_done(adc, adc_chan); | ||
424 | mutex_unlock(&indio_dev->mlock); | ||
425 | |||
426 | return ret; | ||
427 | } | ||
428 | |||
429 | static const struct iio_info palmas_gpadc_iio_info = { | ||
430 | .read_raw = palmas_gpadc_read_raw, | ||
431 | .driver_module = THIS_MODULE, | ||
432 | }; | ||
433 | |||
434 | #define PALMAS_ADC_CHAN_IIO(chan, _type, chan_info) \ | ||
435 | { \ | ||
436 | .datasheet_name = PALMAS_DATASHEET_NAME(chan), \ | ||
437 | .type = _type, \ | ||
438 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ | ||
439 | BIT(chan_info), \ | ||
440 | .indexed = 1, \ | ||
441 | .channel = PALMAS_ADC_CH_##chan, \ | ||
442 | } | ||
443 | |||
444 | static const struct iio_chan_spec palmas_gpadc_iio_channel[] = { | ||
445 | PALMAS_ADC_CHAN_IIO(IN0, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED), | ||
446 | PALMAS_ADC_CHAN_IIO(IN1, IIO_TEMP, IIO_CHAN_INFO_RAW), | ||
447 | PALMAS_ADC_CHAN_IIO(IN2, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED), | ||
448 | PALMAS_ADC_CHAN_IIO(IN3, IIO_TEMP, IIO_CHAN_INFO_RAW), | ||
449 | PALMAS_ADC_CHAN_IIO(IN4, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED), | ||
450 | PALMAS_ADC_CHAN_IIO(IN5, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED), | ||
451 | PALMAS_ADC_CHAN_IIO(IN6, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED), | ||
452 | PALMAS_ADC_CHAN_IIO(IN7, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED), | ||
453 | PALMAS_ADC_CHAN_IIO(IN8, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED), | ||
454 | PALMAS_ADC_CHAN_IIO(IN9, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED), | ||
455 | PALMAS_ADC_CHAN_IIO(IN10, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED), | ||
456 | PALMAS_ADC_CHAN_IIO(IN11, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED), | ||
457 | PALMAS_ADC_CHAN_IIO(IN12, IIO_TEMP, IIO_CHAN_INFO_RAW), | ||
458 | PALMAS_ADC_CHAN_IIO(IN13, IIO_TEMP, IIO_CHAN_INFO_RAW), | ||
459 | PALMAS_ADC_CHAN_IIO(IN14, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED), | ||
460 | PALMAS_ADC_CHAN_IIO(IN15, IIO_VOLTAGE, IIO_CHAN_INFO_PROCESSED), | ||
461 | }; | ||
462 | |||
463 | static int palmas_gpadc_probe(struct platform_device *pdev) | ||
464 | { | ||
465 | struct palmas_gpadc *adc; | ||
466 | struct palmas_platform_data *pdata; | ||
467 | struct palmas_gpadc_platform_data *gpadc_pdata = NULL; | ||
468 | struct iio_dev *indio_dev; | ||
469 | int ret, i; | ||
470 | |||
471 | pdata = dev_get_platdata(pdev->dev.parent); | ||
472 | if (!pdata || !pdata->gpadc_pdata) { | ||
473 | dev_err(&pdev->dev, "No platform data\n"); | ||
474 | return -ENODEV; | ||
475 | } | ||
476 | |||
477 | gpadc_pdata = pdata->gpadc_pdata; | ||
478 | |||
479 | indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc)); | ||
480 | if (!indio_dev) { | ||
481 | dev_err(&pdev->dev, "iio_device_alloc failed\n"); | ||
482 | return -ENOMEM; | ||
483 | } | ||
484 | |||
485 | adc = iio_priv(indio_dev); | ||
486 | adc->dev = &pdev->dev; | ||
487 | adc->palmas = dev_get_drvdata(pdev->dev.parent); | ||
488 | adc->adc_info = palmas_gpadc_info; | ||
489 | init_completion(&adc->conv_completion); | ||
490 | dev_set_drvdata(&pdev->dev, indio_dev); | ||
491 | |||
492 | adc->auto_conversion_period = gpadc_pdata->auto_conversion_period_ms; | ||
493 | adc->irq = palmas_irq_get_virq(adc->palmas, PALMAS_GPADC_EOC_SW_IRQ); | ||
494 | if (adc->irq < 0) { | ||
495 | dev_err(adc->dev, | ||
496 | "get virq failed: %d\n", adc->irq); | ||
497 | ret = adc->irq; | ||
498 | goto out; | ||
499 | } | ||
500 | ret = request_threaded_irq(adc->irq, NULL, | ||
501 | palmas_gpadc_irq, | ||
502 | IRQF_ONESHOT | IRQF_EARLY_RESUME, dev_name(adc->dev), | ||
503 | adc); | ||
504 | if (ret < 0) { | ||
505 | dev_err(adc->dev, | ||
506 | "request irq %d failed: %d\n", adc->irq, ret); | ||
507 | goto out; | ||
508 | } | ||
509 | |||
510 | if (gpadc_pdata->adc_wakeup1_data) { | ||
511 | memcpy(&adc->wakeup1_data, gpadc_pdata->adc_wakeup1_data, | ||
512 | sizeof(adc->wakeup1_data)); | ||
513 | adc->wakeup1_enable = true; | ||
514 | adc->irq_auto_0 = platform_get_irq(pdev, 1); | ||
515 | ret = request_threaded_irq(adc->irq_auto_0, NULL, | ||
516 | palmas_gpadc_irq_auto, | ||
517 | IRQF_ONESHOT | IRQF_EARLY_RESUME, | ||
518 | "palmas-adc-auto-0", adc); | ||
519 | if (ret < 0) { | ||
520 | dev_err(adc->dev, "request auto0 irq %d failed: %d\n", | ||
521 | adc->irq_auto_0, ret); | ||
522 | goto out_irq_free; | ||
523 | } | ||
524 | } | ||
525 | |||
526 | if (gpadc_pdata->adc_wakeup2_data) { | ||
527 | memcpy(&adc->wakeup2_data, gpadc_pdata->adc_wakeup2_data, | ||
528 | sizeof(adc->wakeup2_data)); | ||
529 | adc->wakeup2_enable = true; | ||
530 | adc->irq_auto_1 = platform_get_irq(pdev, 2); | ||
531 | ret = request_threaded_irq(adc->irq_auto_1, NULL, | ||
532 | palmas_gpadc_irq_auto, | ||
533 | IRQF_ONESHOT | IRQF_EARLY_RESUME, | ||
534 | "palmas-adc-auto-1", adc); | ||
535 | if (ret < 0) { | ||
536 | dev_err(adc->dev, "request auto1 irq %d failed: %d\n", | ||
537 | adc->irq_auto_1, ret); | ||
538 | goto out_irq_auto0_free; | ||
539 | } | ||
540 | } | ||
541 | |||
542 | /* set the current source 0 (value 0/5/15/20 uA => 0..3) */ | ||
543 | if (gpadc_pdata->ch0_current <= 1) | ||
544 | adc->ch0_current = PALMAS_ADC_CH0_CURRENT_SRC_0; | ||
545 | else if (gpadc_pdata->ch0_current <= 5) | ||
546 | adc->ch0_current = PALMAS_ADC_CH0_CURRENT_SRC_5; | ||
547 | else if (gpadc_pdata->ch0_current <= 15) | ||
548 | adc->ch0_current = PALMAS_ADC_CH0_CURRENT_SRC_15; | ||
549 | else | ||
550 | adc->ch0_current = PALMAS_ADC_CH0_CURRENT_SRC_20; | ||
551 | |||
552 | /* set the current source 3 (value 0/10/400/800 uA => 0..3) */ | ||
553 | if (gpadc_pdata->ch3_current <= 1) | ||
554 | adc->ch3_current = PALMAS_ADC_CH3_CURRENT_SRC_0; | ||
555 | else if (gpadc_pdata->ch3_current <= 10) | ||
556 | adc->ch3_current = PALMAS_ADC_CH3_CURRENT_SRC_10; | ||
557 | else if (gpadc_pdata->ch3_current <= 400) | ||
558 | adc->ch3_current = PALMAS_ADC_CH3_CURRENT_SRC_400; | ||
559 | else | ||
560 | adc->ch3_current = PALMAS_ADC_CH3_CURRENT_SRC_800; | ||
561 | |||
562 | adc->extended_delay = gpadc_pdata->extended_delay; | ||
563 | |||
564 | indio_dev->name = MOD_NAME; | ||
565 | indio_dev->dev.parent = &pdev->dev; | ||
566 | indio_dev->info = &palmas_gpadc_iio_info; | ||
567 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
568 | indio_dev->channels = palmas_gpadc_iio_channel; | ||
569 | indio_dev->num_channels = ARRAY_SIZE(palmas_gpadc_iio_channel); | ||
570 | |||
571 | ret = iio_device_register(indio_dev); | ||
572 | if (ret < 0) { | ||
573 | dev_err(adc->dev, "iio_device_register() failed: %d\n", ret); | ||
574 | goto out_irq_auto1_free; | ||
575 | } | ||
576 | |||
577 | device_set_wakeup_capable(&pdev->dev, 1); | ||
578 | for (i = 0; i < PALMAS_ADC_CH_MAX; i++) { | ||
579 | if (!(adc->adc_info[i].is_uncalibrated)) | ||
580 | palmas_gpadc_calibrate(adc, i); | ||
581 | } | ||
582 | |||
583 | if (adc->wakeup1_enable || adc->wakeup2_enable) | ||
584 | device_wakeup_enable(&pdev->dev); | ||
585 | |||
586 | return 0; | ||
587 | |||
588 | out_irq_auto1_free: | ||
589 | if (gpadc_pdata->adc_wakeup2_data) | ||
590 | free_irq(adc->irq_auto_1, adc); | ||
591 | out_irq_auto0_free: | ||
592 | if (gpadc_pdata->adc_wakeup1_data) | ||
593 | free_irq(adc->irq_auto_0, adc); | ||
594 | out_irq_free: | ||
595 | free_irq(adc->irq, adc); | ||
596 | out: | ||
597 | return ret; | ||
598 | } | ||
599 | |||
600 | static int palmas_gpadc_remove(struct platform_device *pdev) | ||
601 | { | ||
602 | struct iio_dev *indio_dev = dev_to_iio_dev(&pdev->dev); | ||
603 | struct palmas_gpadc *adc = iio_priv(indio_dev); | ||
604 | |||
605 | if (adc->wakeup1_enable || adc->wakeup2_enable) | ||
606 | device_wakeup_disable(&pdev->dev); | ||
607 | iio_device_unregister(indio_dev); | ||
608 | free_irq(adc->irq, adc); | ||
609 | if (adc->wakeup1_enable) | ||
610 | free_irq(adc->irq_auto_0, adc); | ||
611 | if (adc->wakeup2_enable) | ||
612 | free_irq(adc->irq_auto_1, adc); | ||
613 | |||
614 | return 0; | ||
615 | } | ||
616 | |||
617 | #ifdef CONFIG_PM_SLEEP | ||
618 | static int palmas_adc_wakeup_configure(struct palmas_gpadc *adc) | ||
619 | { | ||
620 | int adc_period, conv; | ||
621 | int i; | ||
622 | int ch0 = 0, ch1 = 0; | ||
623 | int thres; | ||
624 | int ret; | ||
625 | |||
626 | adc_period = adc->auto_conversion_period; | ||
627 | for (i = 0; i < 16; ++i) { | ||
628 | if (((1000 * (1 << i)) / 32) < adc_period) | ||
629 | continue; | ||
630 | } | ||
631 | if (i > 0) | ||
632 | i--; | ||
633 | adc_period = i; | ||
634 | ret = palmas_update_bits(adc->palmas, PALMAS_GPADC_BASE, | ||
635 | PALMAS_GPADC_AUTO_CTRL, | ||
636 | PALMAS_GPADC_AUTO_CTRL_COUNTER_CONV_MASK, | ||
637 | adc_period); | ||
638 | if (ret < 0) { | ||
639 | dev_err(adc->dev, "AUTO_CTRL write failed: %d\n", ret); | ||
640 | return ret; | ||
641 | } | ||
642 | |||
643 | conv = 0; | ||
644 | if (adc->wakeup1_enable) { | ||
645 | int polarity; | ||
646 | |||
647 | ch0 = adc->wakeup1_data.adc_channel_number; | ||
648 | conv |= PALMAS_GPADC_AUTO_CTRL_AUTO_CONV0_EN; | ||
649 | if (adc->wakeup1_data.adc_high_threshold > 0) { | ||
650 | thres = adc->wakeup1_data.adc_high_threshold; | ||
651 | polarity = 0; | ||
652 | } else { | ||
653 | thres = adc->wakeup1_data.adc_low_threshold; | ||
654 | polarity = PALMAS_GPADC_THRES_CONV0_MSB_THRES_CONV0_POL; | ||
655 | } | ||
656 | |||
657 | ret = palmas_write(adc->palmas, PALMAS_GPADC_BASE, | ||
658 | PALMAS_GPADC_THRES_CONV0_LSB, thres & 0xFF); | ||
659 | if (ret < 0) { | ||
660 | dev_err(adc->dev, | ||
661 | "THRES_CONV0_LSB write failed: %d\n", ret); | ||
662 | return ret; | ||
663 | } | ||
664 | |||
665 | ret = palmas_write(adc->palmas, PALMAS_GPADC_BASE, | ||
666 | PALMAS_GPADC_THRES_CONV0_MSB, | ||
667 | ((thres >> 8) & 0xF) | polarity); | ||
668 | if (ret < 0) { | ||
669 | dev_err(adc->dev, | ||
670 | "THRES_CONV0_MSB write failed: %d\n", ret); | ||
671 | return ret; | ||
672 | } | ||
673 | } | ||
674 | |||
675 | if (adc->wakeup2_enable) { | ||
676 | int polarity; | ||
677 | |||
678 | ch1 = adc->wakeup2_data.adc_channel_number; | ||
679 | conv |= PALMAS_GPADC_AUTO_CTRL_AUTO_CONV1_EN; | ||
680 | if (adc->wakeup2_data.adc_high_threshold > 0) { | ||
681 | thres = adc->wakeup2_data.adc_high_threshold; | ||
682 | polarity = 0; | ||
683 | } else { | ||
684 | thres = adc->wakeup2_data.adc_low_threshold; | ||
685 | polarity = PALMAS_GPADC_THRES_CONV1_MSB_THRES_CONV1_POL; | ||
686 | } | ||
687 | |||
688 | ret = palmas_write(adc->palmas, PALMAS_GPADC_BASE, | ||
689 | PALMAS_GPADC_THRES_CONV1_LSB, thres & 0xFF); | ||
690 | if (ret < 0) { | ||
691 | dev_err(adc->dev, | ||
692 | "THRES_CONV1_LSB write failed: %d\n", ret); | ||
693 | return ret; | ||
694 | } | ||
695 | |||
696 | ret = palmas_write(adc->palmas, PALMAS_GPADC_BASE, | ||
697 | PALMAS_GPADC_THRES_CONV1_MSB, | ||
698 | ((thres >> 8) & 0xF) | polarity); | ||
699 | if (ret < 0) { | ||
700 | dev_err(adc->dev, | ||
701 | "THRES_CONV1_MSB write failed: %d\n", ret); | ||
702 | return ret; | ||
703 | } | ||
704 | } | ||
705 | |||
706 | ret = palmas_write(adc->palmas, PALMAS_GPADC_BASE, | ||
707 | PALMAS_GPADC_AUTO_SELECT, (ch1 << 4) | ch0); | ||
708 | if (ret < 0) { | ||
709 | dev_err(adc->dev, "AUTO_SELECT write failed: %d\n", ret); | ||
710 | return ret; | ||
711 | } | ||
712 | |||
713 | ret = palmas_update_bits(adc->palmas, PALMAS_GPADC_BASE, | ||
714 | PALMAS_GPADC_AUTO_CTRL, | ||
715 | PALMAS_GPADC_AUTO_CTRL_AUTO_CONV1_EN | | ||
716 | PALMAS_GPADC_AUTO_CTRL_AUTO_CONV0_EN, conv); | ||
717 | if (ret < 0) | ||
718 | dev_err(adc->dev, "AUTO_CTRL write failed: %d\n", ret); | ||
719 | |||
720 | return ret; | ||
721 | } | ||
722 | |||
723 | static int palmas_adc_wakeup_reset(struct palmas_gpadc *adc) | ||
724 | { | ||
725 | int ret; | ||
726 | |||
727 | ret = palmas_write(adc->palmas, PALMAS_GPADC_BASE, | ||
728 | PALMAS_GPADC_AUTO_SELECT, 0); | ||
729 | if (ret < 0) { | ||
730 | dev_err(adc->dev, "AUTO_SELECT write failed: %d\n", ret); | ||
731 | return ret; | ||
732 | } | ||
733 | |||
734 | ret = palmas_disable_auto_conversion(adc); | ||
735 | if (ret < 0) | ||
736 | dev_err(adc->dev, "Disable auto conversion failed: %d\n", ret); | ||
737 | |||
738 | return ret; | ||
739 | } | ||
740 | |||
741 | static int palmas_gpadc_suspend(struct device *dev) | ||
742 | { | ||
743 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | ||
744 | struct palmas_gpadc *adc = iio_priv(indio_dev); | ||
745 | int wakeup = adc->wakeup1_enable || adc->wakeup2_enable; | ||
746 | int ret; | ||
747 | |||
748 | if (!device_may_wakeup(dev) || !wakeup) | ||
749 | return 0; | ||
750 | |||
751 | ret = palmas_adc_wakeup_configure(adc); | ||
752 | if (ret < 0) | ||
753 | return ret; | ||
754 | |||
755 | if (adc->wakeup1_enable) | ||
756 | enable_irq_wake(adc->irq_auto_0); | ||
757 | |||
758 | if (adc->wakeup2_enable) | ||
759 | enable_irq_wake(adc->irq_auto_1); | ||
760 | |||
761 | return 0; | ||
762 | } | ||
763 | |||
764 | static int palmas_gpadc_resume(struct device *dev) | ||
765 | { | ||
766 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | ||
767 | struct palmas_gpadc *adc = iio_priv(indio_dev); | ||
768 | int wakeup = adc->wakeup1_enable || adc->wakeup2_enable; | ||
769 | int ret; | ||
770 | |||
771 | if (!device_may_wakeup(dev) || !wakeup) | ||
772 | return 0; | ||
773 | |||
774 | ret = palmas_adc_wakeup_reset(adc); | ||
775 | if (ret < 0) | ||
776 | return ret; | ||
777 | |||
778 | if (adc->wakeup1_enable) | ||
779 | disable_irq_wake(adc->irq_auto_0); | ||
780 | |||
781 | if (adc->wakeup2_enable) | ||
782 | disable_irq_wake(adc->irq_auto_1); | ||
783 | |||
784 | return 0; | ||
785 | }; | ||
786 | #endif | ||
787 | |||
788 | static const struct dev_pm_ops palmas_pm_ops = { | ||
789 | SET_SYSTEM_SLEEP_PM_OPS(palmas_gpadc_suspend, | ||
790 | palmas_gpadc_resume) | ||
791 | }; | ||
792 | |||
793 | static struct platform_driver palmas_gpadc_driver = { | ||
794 | .probe = palmas_gpadc_probe, | ||
795 | .remove = palmas_gpadc_remove, | ||
796 | .driver = { | ||
797 | .name = MOD_NAME, | ||
798 | .pm = &palmas_pm_ops, | ||
799 | }, | ||
800 | }; | ||
801 | |||
802 | static int __init palmas_gpadc_init(void) | ||
803 | { | ||
804 | return platform_driver_register(&palmas_gpadc_driver); | ||
805 | } | ||
806 | module_init(palmas_gpadc_init); | ||
807 | |||
808 | static void __exit palmas_gpadc_exit(void) | ||
809 | { | ||
810 | platform_driver_unregister(&palmas_gpadc_driver); | ||
811 | } | ||
812 | module_exit(palmas_gpadc_exit); | ||
813 | |||
814 | MODULE_DESCRIPTION("palmas GPADC driver"); | ||
815 | MODULE_AUTHOR("Pradeep Goudagunta<pgoudagunta@nvidia.com>"); | ||
816 | MODULE_ALIAS("platform:palmas-gpadc"); | ||
817 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/include/linux/mfd/palmas.h b/include/linux/mfd/palmas.h index 13e1d96935ed..c800dbc42079 100644 --- a/include/linux/mfd/palmas.h +++ b/include/linux/mfd/palmas.h | |||
@@ -134,21 +134,32 @@ struct palmas_pmic_driver_data { | |||
134 | struct regulator_config config); | 134 | struct regulator_config config); |
135 | }; | 135 | }; |
136 | 136 | ||
137 | struct palmas_adc_wakeup_property { | ||
138 | int adc_channel_number; | ||
139 | int adc_high_threshold; | ||
140 | int adc_low_threshold; | ||
141 | }; | ||
142 | |||
137 | struct palmas_gpadc_platform_data { | 143 | struct palmas_gpadc_platform_data { |
138 | /* Channel 3 current source is only enabled during conversion */ | 144 | /* Channel 3 current source is only enabled during conversion */ |
139 | int ch3_current; | 145 | int ch3_current; /* 0: off; 1: 10uA; 2: 400uA; 3: 800 uA */ |
140 | 146 | ||
141 | /* Channel 0 current source can be used for battery detection. | 147 | /* Channel 0 current source can be used for battery detection. |
142 | * If used for battery detection this will cause a permanent current | 148 | * If used for battery detection this will cause a permanent current |
143 | * consumption depending on current level set here. | 149 | * consumption depending on current level set here. |
144 | */ | 150 | */ |
145 | int ch0_current; | 151 | int ch0_current; /* 0: off; 1: 5uA; 2: 15uA; 3: 20 uA */ |
152 | bool extended_delay; /* use extended delay for conversion */ | ||
146 | 153 | ||
147 | /* default BAT_REMOVAL_DAT setting on device probe */ | 154 | /* default BAT_REMOVAL_DAT setting on device probe */ |
148 | int bat_removal; | 155 | int bat_removal; |
149 | 156 | ||
150 | /* Sets the START_POLARITY bit in the RT_CTRL register */ | 157 | /* Sets the START_POLARITY bit in the RT_CTRL register */ |
151 | int start_polarity; | 158 | int start_polarity; |
159 | |||
160 | int auto_conversion_period_ms; | ||
161 | struct palmas_adc_wakeup_property *adc_wakeup1_data; | ||
162 | struct palmas_adc_wakeup_property *adc_wakeup2_data; | ||
152 | }; | 163 | }; |
153 | 164 | ||
154 | struct palmas_reg_init { | 165 | struct palmas_reg_init { |
@@ -405,28 +416,7 @@ struct palmas_gpadc_calibration { | |||
405 | s32 offset_error; | 416 | s32 offset_error; |
406 | }; | 417 | }; |
407 | 418 | ||
408 | struct palmas_gpadc { | 419 | #define PALMAS_DATASHEET_NAME(_name) "palmas-gpadc-chan-"#_name |
409 | struct device *dev; | ||
410 | struct palmas *palmas; | ||
411 | |||
412 | int ch3_current; | ||
413 | int ch0_current; | ||
414 | |||
415 | int gpadc_force; | ||
416 | |||
417 | int bat_removal; | ||
418 | |||
419 | struct mutex reading_lock; | ||
420 | struct completion irq_complete; | ||
421 | |||
422 | int eoc_sw_irq; | ||
423 | |||
424 | struct palmas_gpadc_calibration *palmas_cal_tbl; | ||
425 | |||
426 | int conv0_channel; | ||
427 | int conv1_channel; | ||
428 | int rt_channel; | ||
429 | }; | ||
430 | 420 | ||
431 | struct palmas_gpadc_result { | 421 | struct palmas_gpadc_result { |
432 | s32 raw_code; | 422 | s32 raw_code; |
@@ -520,6 +510,43 @@ enum palmas_irqs { | |||
520 | PALMAS_NUM_IRQ, | 510 | PALMAS_NUM_IRQ, |
521 | }; | 511 | }; |
522 | 512 | ||
513 | /* Palmas GPADC Channels */ | ||
514 | enum { | ||
515 | PALMAS_ADC_CH_IN0, | ||
516 | PALMAS_ADC_CH_IN1, | ||
517 | PALMAS_ADC_CH_IN2, | ||
518 | PALMAS_ADC_CH_IN3, | ||
519 | PALMAS_ADC_CH_IN4, | ||
520 | PALMAS_ADC_CH_IN5, | ||
521 | PALMAS_ADC_CH_IN6, | ||
522 | PALMAS_ADC_CH_IN7, | ||
523 | PALMAS_ADC_CH_IN8, | ||
524 | PALMAS_ADC_CH_IN9, | ||
525 | PALMAS_ADC_CH_IN10, | ||
526 | PALMAS_ADC_CH_IN11, | ||
527 | PALMAS_ADC_CH_IN12, | ||
528 | PALMAS_ADC_CH_IN13, | ||
529 | PALMAS_ADC_CH_IN14, | ||
530 | PALMAS_ADC_CH_IN15, | ||
531 | PALMAS_ADC_CH_MAX, | ||
532 | }; | ||
533 | |||
534 | /* Palmas GPADC Channel0 Current Source */ | ||
535 | enum { | ||
536 | PALMAS_ADC_CH0_CURRENT_SRC_0, | ||
537 | PALMAS_ADC_CH0_CURRENT_SRC_5, | ||
538 | PALMAS_ADC_CH0_CURRENT_SRC_15, | ||
539 | PALMAS_ADC_CH0_CURRENT_SRC_20, | ||
540 | }; | ||
541 | |||
542 | /* Palmas GPADC Channel3 Current Source */ | ||
543 | enum { | ||
544 | PALMAS_ADC_CH3_CURRENT_SRC_0, | ||
545 | PALMAS_ADC_CH3_CURRENT_SRC_10, | ||
546 | PALMAS_ADC_CH3_CURRENT_SRC_400, | ||
547 | PALMAS_ADC_CH3_CURRENT_SRC_800, | ||
548 | }; | ||
549 | |||
523 | struct palmas_pmic { | 550 | struct palmas_pmic { |
524 | struct palmas *palmas; | 551 | struct palmas *palmas; |
525 | struct device *dev; | 552 | struct device *dev; |