blob: 0470a62d30e8f4c34e2c42f96108e709a303aa7e [file] [log] [blame]
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#define pr_fmt(fmt) "%s: " fmt, __func__
14
15#include <linux/kernel.h>
16#include <linux/of.h>
17#include <linux/err.h>
18#include <linux/init.h>
19#include <linux/slab.h>
20#include <linux/delay.h>
21#include <linux/mutex.h>
22#include <linux/types.h>
23#include <linux/hwmon.h>
24#include <linux/module.h>
25#include <linux/debugfs.h>
26#include <linux/spmi.h>
27#include <linux/of_irq.h>
28#include <linux/interrupt.h>
29#include <linux/completion.h>
30#include <linux/hwmon-sysfs.h>
31#include <linux/qpnp/qpnp-adc.h>
32#include <linux/platform_device.h>
33
34/* QPNP VADC register definition */
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -070035#define QPNP_VADC_REVISION1 0x0
36#define QPNP_VADC_REVISION2 0x1
37#define QPNP_VADC_REVISION3 0x2
38#define QPNP_VADC_REVISION4 0x3
39#define QPNP_VADC_PERPH_TYPE 0x4
40#define QPNP_VADC_PERH_SUBTYPE 0x5
41
42#define QPNP_VADC_SUPPORTED_REVISION2 1
43
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -070044#define QPNP_VADC_STATUS1 0x8
45#define QPNP_VADC_STATUS1_OP_MODE 4
46#define QPNP_VADC_STATUS1_MEAS_INTERVAL_EN_STS BIT(2)
47#define QPNP_VADC_STATUS1_REQ_STS BIT(1)
48#define QPNP_VADC_STATUS1_EOC BIT(0)
Siddartha Mohanadossae1da732012-08-08 16:39:02 -070049#define QPNP_VADC_STATUS1_REQ_STS_EOC_MASK 0x3
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -070050#define QPNP_VADC_STATUS2 0x9
51#define QPNP_VADC_STATUS2_CONV_SEQ_STATE 6
52#define QPNP_VADC_STATUS2_FIFO_NOT_EMPTY_FLAG BIT(1)
53#define QPNP_VADC_STATUS2_CONV_SEQ_TIMEOUT_STS BIT(0)
54#define QPNP_VADC_STATUS2_CONV_SEQ_STATE_SHIFT 4
55#define QPNP_VADC_CONV_TIMEOUT_ERR 2
56
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -070057#define QPNP_VADC_MODE_CTL 0x40
58#define QPNP_VADC_OP_MODE_SHIFT 4
59#define QPNP_VADC_VREF_XO_THM_FORCE BIT(2)
60#define QPNP_VADC_AMUX_TRIM_EN BIT(1)
61#define QPNP_VADC_ADC_TRIM_EN BIT(0)
62#define QPNP_VADC_EN_CTL1 0x46
63#define QPNP_VADC_ADC_EN BIT(7)
64#define QPNP_VADC_ADC_CH_SEL_CTL 0x48
65#define QPNP_VADC_ADC_DIG_PARAM 0x50
66#define QPNP_VADC_ADC_DIG_DEC_RATIO_SEL_SHIFT 3
67#define QPNP_VADC_HW_SETTLE_DELAY 0x51
68#define QPNP_VADC_CONV_REQ 0x52
69#define QPNP_VADC_CONV_REQ_SET BIT(7)
70#define QPNP_VADC_CONV_SEQ_CTL 0x54
71#define QPNP_VADC_CONV_SEQ_HOLDOFF_SHIFT 4
72#define QPNP_VADC_CONV_SEQ_TRIG_CTL 0x55
73#define QPNP_VADC_CONV_SEQ_FALLING_EDGE 0x0
74#define QPNP_VADC_CONV_SEQ_RISING_EDGE 0x1
75#define QPNP_VADC_CONV_SEQ_EDGE_SHIFT 7
76#define QPNP_VADC_FAST_AVG_CTL 0x5a
77
78#define QPNP_VADC_M0_LOW_THR_LSB 0x5c
79#define QPNP_VADC_M0_LOW_THR_MSB 0x5d
80#define QPNP_VADC_M0_HIGH_THR_LSB 0x5e
81#define QPNP_VADC_M0_HIGH_THR_MSB 0x5f
82#define QPNP_VADC_M1_LOW_THR_LSB 0x69
83#define QPNP_VADC_M1_LOW_THR_MSB 0x6a
84#define QPNP_VADC_M1_HIGH_THR_LSB 0x6b
85#define QPNP_VADC_M1_HIGH_THR_MSB 0x6c
86
87#define QPNP_VADC_DATA0 0x60
88#define QPNP_VADC_DATA1 0x61
89#define QPNP_VADC_CONV_TIMEOUT_ERR 2
90#define QPNP_VADC_CONV_TIME_MIN 2000
91#define QPNP_VADC_CONV_TIME_MAX 2100
Siddartha Mohanadoss1a0d2032012-11-01 11:22:29 -070092#define QPNP_ADC_COMPLETION_TIMEOUT HZ
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -070093
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -070094struct qpnp_vadc_drv {
95 struct qpnp_adc_drv *adc;
96 struct dentry *dent;
97 struct device *vadc_hwmon;
98 bool vadc_init_calib;
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -070099 bool vadc_initialized;
100 int max_channels_available;
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -0800101 bool vadc_iadc_sync_lock;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700102 struct sensor_device_attribute sens_attr[0];
103};
104
105struct qpnp_vadc_drv *qpnp_vadc;
106
107static struct qpnp_vadc_scale_fn vadc_scale_fn[] = {
108 [SCALE_DEFAULT] = {qpnp_adc_scale_default},
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700109 [SCALE_BATT_THERM] = {qpnp_adc_scale_batt_therm},
110 [SCALE_PMIC_THERM] = {qpnp_adc_scale_pmic_therm},
111 [SCALE_XOTHERM] = {qpnp_adc_tdkntcg_therm},
Siddartha Mohanadosse77edf12012-09-13 14:26:32 -0700112 [SCALE_THERM_100K_PULLUP] = {qpnp_adc_scale_therm_pu2},
113 [SCALE_THERM_150K_PULLUP] = {qpnp_adc_scale_therm_pu1},
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700114};
115
116static int32_t qpnp_vadc_read_reg(int16_t reg, u8 *data)
117{
118 struct qpnp_vadc_drv *vadc = qpnp_vadc;
119 int rc;
120
121 rc = spmi_ext_register_readl(vadc->adc->spmi->ctrl, vadc->adc->slave,
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700122 (vadc->adc->offset + reg), data, 1);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700123 if (rc < 0) {
124 pr_err("qpnp adc read reg %d failed with %d\n", reg, rc);
125 return rc;
126 }
127
128 return 0;
129}
130
131static int32_t qpnp_vadc_write_reg(int16_t reg, u8 data)
132{
133 struct qpnp_vadc_drv *vadc = qpnp_vadc;
134 int rc;
135 u8 *buf;
136
137 buf = &data;
138
139 rc = spmi_ext_register_writel(vadc->adc->spmi->ctrl, vadc->adc->slave,
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700140 (vadc->adc->offset + reg), buf, 1);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700141 if (rc < 0) {
142 pr_err("qpnp adc write reg %d failed with %d\n", reg, rc);
143 return rc;
144 }
145
146 return 0;
147}
148
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700149static int32_t qpnp_vadc_enable(bool state)
150{
151 int rc = 0;
152 u8 data = 0;
153
154 data = QPNP_VADC_ADC_EN;
155 if (state) {
156 rc = qpnp_vadc_write_reg(QPNP_VADC_EN_CTL1,
157 data);
158 if (rc < 0) {
159 pr_err("VADC enable failed\n");
160 return rc;
161 }
162 } else {
163 rc = qpnp_vadc_write_reg(QPNP_VADC_EN_CTL1,
164 (~data & QPNP_VADC_ADC_EN));
165 if (rc < 0) {
166 pr_err("VADC disable failed\n");
167 return rc;
168 }
169 }
170
171 return 0;
172}
173
Siddartha Mohanadoss9cb2c652012-12-14 19:18:18 -0800174static int32_t qpnp_vadc_status_debug(void)
175{
176 int rc = 0;
177 u8 mode = 0, status1 = 0, chan = 0, dig = 0, en = 0, status2 = 0;
178
179 rc = qpnp_vadc_read_reg(QPNP_VADC_MODE_CTL, &mode);
180 if (rc < 0) {
181 pr_err("mode ctl register read failed with %d\n", rc);
182 return rc;
183 }
184
185 rc = qpnp_vadc_read_reg(QPNP_VADC_ADC_DIG_PARAM, &dig);
186 if (rc < 0) {
187 pr_err("digital param read failed with %d\n", rc);
188 return rc;
189 }
190
191 rc = qpnp_vadc_read_reg(QPNP_VADC_ADC_CH_SEL_CTL, &chan);
192 if (rc < 0) {
193 pr_err("channel read failed with %d\n", rc);
194 return rc;
195 }
196
197 rc = qpnp_vadc_read_reg(QPNP_VADC_STATUS1, &status1);
198 if (rc < 0) {
199 pr_err("status1 read failed with %d\n", rc);
200 return rc;
201 }
202
203 rc = qpnp_vadc_read_reg(QPNP_VADC_STATUS2, &status2);
204 if (rc < 0) {
205 pr_err("status2 read failed with %d\n", rc);
206 return rc;
207 }
208
209 rc = qpnp_vadc_read_reg(QPNP_VADC_EN_CTL1, &en);
210 if (rc < 0) {
211 pr_err("en read failed with %d\n", rc);
212 return rc;
213 }
214
215 pr_err("EOC not set - status1/2:%x/%x, dig:%x, ch:%x, mode:%x, en:%x\n",
216 status1, status2, dig, chan, mode, en);
217
218 rc = qpnp_vadc_enable(false);
219 if (rc < 0) {
220 pr_err("VADC disable failed with %d\n", rc);
221 return rc;
222 }
223
224 return 0;
225}
Siddartha Mohanadoss8dbb5c22012-12-11 14:50:45 -0800226static int32_t qpnp_vadc_configure(
Siddartha Mohanadossc4a6af12012-07-13 18:50:12 -0700227 struct qpnp_adc_amux_properties *chan_prop)
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700228{
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700229 struct qpnp_vadc_drv *vadc = qpnp_vadc;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700230 u8 decimation = 0, conv_sequence = 0, conv_sequence_trig = 0;
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700231 u8 mode_ctrl = 0;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700232 int rc = 0;
233
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700234 /* Mode selection */
Siddartha Mohanadoss429b4492012-12-11 13:29:58 -0800235 mode_ctrl |= ((chan_prop->mode_sel << QPNP_VADC_OP_MODE_SHIFT) |
236 (QPNP_VADC_ADC_TRIM_EN | QPNP_VADC_AMUX_TRIM_EN));
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700237 rc = qpnp_vadc_write_reg(QPNP_VADC_MODE_CTL, mode_ctrl);
238 if (rc < 0) {
239 pr_err("Mode configure write error\n");
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700240 return rc;
241 }
242
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700243
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700244 /* Channel selection */
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700245 rc = qpnp_vadc_write_reg(QPNP_VADC_ADC_CH_SEL_CTL,
246 chan_prop->amux_channel);
247 if (rc < 0) {
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700248 pr_err("Channel configure error\n");
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700249 return rc;
250 }
251
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700252 /* Digital parameter setup */
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700253 decimation = chan_prop->decimation <<
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700254 QPNP_VADC_ADC_DIG_DEC_RATIO_SEL_SHIFT;
255 rc = qpnp_vadc_write_reg(QPNP_VADC_ADC_DIG_PARAM, decimation);
256 if (rc < 0) {
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700257 pr_err("Digital parameter configure write error\n");
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700258 return rc;
259 }
260
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700261 /* HW settling time delay */
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700262 rc = qpnp_vadc_write_reg(QPNP_VADC_HW_SETTLE_DELAY,
263 chan_prop->hw_settle_time);
264 if (rc < 0) {
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700265 pr_err("HW settling time setup error\n");
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700266 return rc;
267 }
268
269 if (chan_prop->mode_sel == (ADC_OP_NORMAL_MODE <<
270 QPNP_VADC_OP_MODE_SHIFT)) {
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700271 /* Normal measurement mode */
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700272 rc = qpnp_vadc_write_reg(QPNP_VADC_FAST_AVG_CTL,
273 chan_prop->fast_avg_setup);
274 if (rc < 0) {
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700275 pr_err("Fast averaging configure error\n");
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700276 return rc;
277 }
278 } else if (chan_prop->mode_sel == (ADC_OP_CONVERSION_SEQUENCER <<
279 QPNP_VADC_OP_MODE_SHIFT)) {
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700280 /* Conversion sequence mode */
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700281 conv_sequence = ((ADC_SEQ_HOLD_100US <<
282 QPNP_VADC_CONV_SEQ_HOLDOFF_SHIFT) |
283 ADC_CONV_SEQ_TIMEOUT_5MS);
284 rc = qpnp_vadc_write_reg(QPNP_VADC_CONV_SEQ_CTL,
285 conv_sequence);
286 if (rc < 0) {
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700287 pr_err("Conversion sequence error\n");
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700288 return rc;
289 }
290
291 conv_sequence_trig = ((QPNP_VADC_CONV_SEQ_RISING_EDGE <<
292 QPNP_VADC_CONV_SEQ_EDGE_SHIFT) |
293 chan_prop->trigger_channel);
294 rc = qpnp_vadc_write_reg(QPNP_VADC_CONV_SEQ_TRIG_CTL,
295 conv_sequence_trig);
296 if (rc < 0) {
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700297 pr_err("Conversion trigger error\n");
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700298 return rc;
299 }
300 }
301
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700302 INIT_COMPLETION(vadc->adc->adc_rslt_completion);
303
304 rc = qpnp_vadc_enable(true);
305 if (rc)
306 return rc;
307
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -0800308 if (!vadc->vadc_iadc_sync_lock) {
309 /* Request conversion */
310 rc = qpnp_vadc_write_reg(QPNP_VADC_CONV_REQ,
311 QPNP_VADC_CONV_REQ_SET);
312 if (rc < 0) {
313 pr_err("Request conversion failed\n");
314 return rc;
315 }
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700316 }
317
318 return 0;
319}
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700320
321static int32_t qpnp_vadc_read_conversion_result(int32_t *data)
322{
323 uint8_t rslt_lsb, rslt_msb;
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700324 int rc = 0, status = 0;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700325
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700326 status = qpnp_vadc_read_reg(QPNP_VADC_DATA0, &rslt_lsb);
327 if (status < 0) {
328 pr_err("qpnp adc result read failed for data0\n");
329 goto fail;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700330 }
331
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700332 status = qpnp_vadc_read_reg(QPNP_VADC_DATA1, &rslt_msb);
333 if (status < 0) {
334 pr_err("qpnp adc result read failed for data1\n");
335 goto fail;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700336 }
337
338 *data = (rslt_msb << 8) | rslt_lsb;
339
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700340 status = qpnp_vadc_check_result(data);
341 if (status < 0) {
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700342 pr_err("VADC data check failed\n");
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700343 goto fail;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700344 }
345
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700346fail:
347 rc = qpnp_vadc_enable(false);
348 if (rc)
349 return rc;
350
351 return status;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700352}
353
354static int32_t qpnp_vadc_read_status(int mode_sel)
355{
356 u8 status1, status2, status2_conv_seq_state;
357 u8 status_err = QPNP_VADC_CONV_TIMEOUT_ERR;
358 int rc;
359
360 switch (mode_sel) {
361 case (ADC_OP_CONVERSION_SEQUENCER << QPNP_VADC_OP_MODE_SHIFT):
362 rc = qpnp_vadc_read_reg(QPNP_VADC_STATUS1, &status1);
363 if (rc) {
364 pr_err("qpnp_vadc read mask interrupt failed\n");
365 return rc;
366 }
367
368 rc = qpnp_vadc_read_reg(QPNP_VADC_STATUS2, &status2);
369 if (rc) {
370 pr_err("qpnp_vadc read mask interrupt failed\n");
371 return rc;
372 }
373
374 if (!(status2 & ~QPNP_VADC_STATUS2_CONV_SEQ_TIMEOUT_STS) &&
375 (status1 & (~QPNP_VADC_STATUS1_REQ_STS |
376 QPNP_VADC_STATUS1_EOC))) {
377 rc = status_err;
378 return rc;
379 }
380
381 status2_conv_seq_state = status2 >>
382 QPNP_VADC_STATUS2_CONV_SEQ_STATE_SHIFT;
383 if (status2_conv_seq_state != ADC_CONV_SEQ_IDLE) {
384 pr_err("qpnp vadc seq error with status %d\n",
385 status2);
386 rc = -EINVAL;
387 return rc;
388 }
389 }
390
391 return 0;
392}
393
394static void qpnp_vadc_work(struct work_struct *work)
395{
396 struct qpnp_vadc_drv *vadc = qpnp_vadc;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700397
Siddartha Mohanadossb60f6462012-11-20 18:06:51 -0800398 if (!vadc || !vadc->vadc_initialized)
399 return;
400
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700401 complete(&vadc->adc->adc_rslt_completion);
402
403 return;
404}
405DECLARE_WORK(trigger_completion_work, qpnp_vadc_work);
406
407static irqreturn_t qpnp_vadc_isr(int irq, void *dev_id)
408{
409 schedule_work(&trigger_completion_work);
410
411 return IRQ_HANDLED;
412}
413
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700414static int32_t qpnp_vadc_version_check(void)
415{
416 uint8_t revision;
417 int rc;
418
419 rc = qpnp_vadc_read_reg(QPNP_VADC_REVISION2, &revision);
420 if (rc < 0) {
421 pr_err("qpnp adc result read failed with %d\n", rc);
422 return rc;
423 }
424
425 if (revision < QPNP_VADC_SUPPORTED_REVISION2) {
426 pr_err("VADC Version not supported\n");
427 return -EINVAL;
428 }
429
430 return 0;
431}
432
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700433static uint32_t qpnp_vadc_calib_device(void)
434{
435 struct qpnp_vadc_drv *vadc = qpnp_vadc;
Siddartha Mohanadossc4a6af12012-07-13 18:50:12 -0700436 struct qpnp_adc_amux_properties conv;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700437 int rc, calib_read_1, calib_read_2;
438 u8 status1 = 0;
439
440 conv.amux_channel = REF_125V;
441 conv.decimation = DECIMATION_TYPE2;
442 conv.mode_sel = ADC_OP_NORMAL_MODE << QPNP_VADC_OP_MODE_SHIFT;
443 conv.hw_settle_time = ADC_CHANNEL_HW_SETTLE_DELAY_0US;
444 conv.fast_avg_setup = ADC_FAST_AVG_SAMPLE_1;
445
446 rc = qpnp_vadc_configure(&conv);
447 if (rc) {
448 pr_err("qpnp_vadc configure failed with %d\n", rc);
449 goto calib_fail;
450 }
451
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700452 while (status1 != QPNP_VADC_STATUS1_EOC) {
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700453 rc = qpnp_vadc_read_reg(QPNP_VADC_STATUS1, &status1);
454 if (rc < 0)
455 return rc;
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700456 status1 &= QPNP_VADC_STATUS1_REQ_STS_EOC_MASK;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700457 usleep_range(QPNP_VADC_CONV_TIME_MIN,
458 QPNP_VADC_CONV_TIME_MAX);
459 }
460
461 rc = qpnp_vadc_read_conversion_result(&calib_read_1);
462 if (rc) {
463 pr_err("qpnp adc read adc failed with %d\n", rc);
464 goto calib_fail;
465 }
466
467 conv.amux_channel = REF_625MV;
468 conv.decimation = DECIMATION_TYPE2;
469 conv.mode_sel = ADC_OP_NORMAL_MODE << QPNP_VADC_OP_MODE_SHIFT;
470 conv.hw_settle_time = ADC_CHANNEL_HW_SETTLE_DELAY_0US;
471 conv.fast_avg_setup = ADC_FAST_AVG_SAMPLE_1;
472 rc = qpnp_vadc_configure(&conv);
473 if (rc) {
474 pr_err("qpnp adc configure failed with %d\n", rc);
475 goto calib_fail;
476 }
477
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700478 status1 = 0;
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700479 while (status1 != QPNP_VADC_STATUS1_EOC) {
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700480 rc = qpnp_vadc_read_reg(QPNP_VADC_STATUS1, &status1);
481 if (rc < 0)
482 return rc;
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700483 status1 &= QPNP_VADC_STATUS1_REQ_STS_EOC_MASK;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700484 usleep_range(QPNP_VADC_CONV_TIME_MIN,
485 QPNP_VADC_CONV_TIME_MAX);
486 }
487
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700488 rc = qpnp_vadc_read_conversion_result(&calib_read_2);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700489 if (rc) {
490 pr_err("qpnp adc read adc failed with %d\n", rc);
491 goto calib_fail;
492 }
493
Siddartha Mohanadossb2a42372013-03-26 15:53:41 -0700494 pr_debug("absolute reference raw: 625mV:0x%x 1.25V:0x%x\n",
495 calib_read_1, calib_read_2);
496
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700497 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_ABSOLUTE].dy =
498 (calib_read_1 - calib_read_2);
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700499
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700500 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_ABSOLUTE].dx
501 = QPNP_ADC_625_UV;
502 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_ABSOLUTE].adc_vref =
503 calib_read_1;
504 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_ABSOLUTE].adc_gnd =
505 calib_read_2;
506 /* Ratiometric Calibration */
507 conv.amux_channel = VDD_VADC;
508 conv.decimation = DECIMATION_TYPE2;
509 conv.mode_sel = ADC_OP_NORMAL_MODE << QPNP_VADC_OP_MODE_SHIFT;
510 conv.hw_settle_time = ADC_CHANNEL_HW_SETTLE_DELAY_0US;
511 conv.fast_avg_setup = ADC_FAST_AVG_SAMPLE_1;
512 rc = qpnp_vadc_configure(&conv);
513 if (rc) {
514 pr_err("qpnp adc configure failed with %d\n", rc);
515 goto calib_fail;
516 }
517
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700518 status1 = 0;
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700519 while (status1 != QPNP_VADC_STATUS1_EOC) {
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700520 rc = qpnp_vadc_read_reg(QPNP_VADC_STATUS1, &status1);
521 if (rc < 0)
522 return rc;
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700523 status1 &= QPNP_VADC_STATUS1_REQ_STS_EOC_MASK;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700524 usleep_range(QPNP_VADC_CONV_TIME_MIN,
525 QPNP_VADC_CONV_TIME_MAX);
526 }
527
528 rc = qpnp_vadc_read_conversion_result(&calib_read_1);
529 if (rc) {
530 pr_err("qpnp adc read adc failed with %d\n", rc);
531 goto calib_fail;
532 }
533
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700534 conv.amux_channel = GND_REF;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700535 conv.decimation = DECIMATION_TYPE2;
536 conv.mode_sel = ADC_OP_NORMAL_MODE << QPNP_VADC_OP_MODE_SHIFT;
537 conv.hw_settle_time = ADC_CHANNEL_HW_SETTLE_DELAY_0US;
538 conv.fast_avg_setup = ADC_FAST_AVG_SAMPLE_1;
539 rc = qpnp_vadc_configure(&conv);
540 if (rc) {
541 pr_err("qpnp adc configure failed with %d\n", rc);
542 goto calib_fail;
543 }
544
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700545 status1 = 0;
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700546 while (status1 != QPNP_VADC_STATUS1_EOC) {
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700547 rc = qpnp_vadc_read_reg(QPNP_VADC_STATUS1, &status1);
548 if (rc < 0)
549 return rc;
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700550 status1 &= QPNP_VADC_STATUS1_REQ_STS_EOC_MASK;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700551 usleep_range(QPNP_VADC_CONV_TIME_MIN,
552 QPNP_VADC_CONV_TIME_MAX);
553 }
554
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700555 rc = qpnp_vadc_read_conversion_result(&calib_read_2);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700556 if (rc) {
557 pr_err("qpnp adc read adc failed with %d\n", rc);
558 goto calib_fail;
559 }
560
Siddartha Mohanadossb2a42372013-03-26 15:53:41 -0700561 pr_debug("ratiometric reference raw: VDD:0x%x GND:0x%x\n",
562 calib_read_1, calib_read_2);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700563 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_RATIOMETRIC].dy =
564 (calib_read_1 - calib_read_2);
565 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_RATIOMETRIC].dx =
566 vadc->adc->adc_prop->adc_vdd_reference;
567 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_RATIOMETRIC].adc_vref =
568 calib_read_1;
569 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_RATIOMETRIC].adc_gnd =
570 calib_read_2;
571
572calib_fail:
573 return rc;
574}
575
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800576int32_t qpnp_get_vadc_gain_and_offset(struct qpnp_vadc_linear_graph *param,
577 enum qpnp_adc_calib_type calib_type)
578{
579
580 struct qpnp_vadc_drv *vadc = qpnp_vadc;
581
582 switch (calib_type) {
583 case CALIB_RATIOMETRIC:
584 param->dy =
585 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_RATIOMETRIC].dy;
586 param->dx =
587 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_RATIOMETRIC].dx;
588 param->adc_vref = vadc->adc->adc_prop->adc_vdd_reference;
589 param->adc_gnd =
590 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_RATIOMETRIC].adc_gnd;
591 break;
592 case CALIB_ABSOLUTE:
593 param->dy =
594 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_ABSOLUTE].dy;
595 param->dx =
596 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_ABSOLUTE].dx;
597 param->adc_vref = vadc->adc->adc_prop->adc_vdd_reference;
598 param->adc_gnd =
599 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_ABSOLUTE].adc_gnd;
600 break;
601 default:
602 return -EINVAL;
603 }
604
605 return 0;
606}
607EXPORT_SYMBOL(qpnp_get_vadc_gain_and_offset);
608
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700609int32_t qpnp_vadc_is_ready(void)
610{
611 struct qpnp_vadc_drv *vadc = qpnp_vadc;
612
613 if (!vadc || !vadc->vadc_initialized)
614 return -EPROBE_DEFER;
615 else
616 return 0;
617}
618EXPORT_SYMBOL(qpnp_vadc_is_ready);
619
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700620int32_t qpnp_vadc_conv_seq_request(enum qpnp_vadc_trigger trigger_channel,
621 enum qpnp_vadc_channels channel,
622 struct qpnp_vadc_result *result)
623{
624 struct qpnp_vadc_drv *vadc = qpnp_vadc;
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700625 int rc = 0, scale_type, amux_prescaling, dt_index = 0;
626
627 if (!vadc || !vadc->vadc_initialized)
628 return -EPROBE_DEFER;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700629
Siddartha Mohanadoss64bc4f52012-12-19 20:26:32 -0800630 mutex_lock(&vadc->adc->adc_lock);
631
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700632 if (!vadc->vadc_init_calib) {
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700633 rc = qpnp_vadc_version_check();
634 if (rc)
Siddartha Mohanadoss64bc4f52012-12-19 20:26:32 -0800635 goto fail_unlock;
636
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700637 rc = qpnp_vadc_calib_device();
638 if (rc) {
639 pr_err("Calibration failed\n");
Siddartha Mohanadoss64bc4f52012-12-19 20:26:32 -0800640 goto fail_unlock;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700641 } else
642 vadc->vadc_init_calib = true;
643 }
644
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700645 vadc->adc->amux_prop->amux_channel = channel;
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700646
Siddartha Mohanadoss7126ce82012-12-11 14:33:11 -0800647 while ((vadc->adc->adc_channels[dt_index].channel_num
648 != channel) && (dt_index < vadc->max_channels_available))
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700649 dt_index++;
650
Siddartha Mohanadoss7126ce82012-12-11 14:33:11 -0800651 if (dt_index >= vadc->max_channels_available) {
Siddartha Mohanadoss1a0d2032012-11-01 11:22:29 -0700652 pr_err("not a valid VADC channel\n");
653 rc = -EINVAL;
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700654 goto fail_unlock;
Siddartha Mohanadoss1a0d2032012-11-01 11:22:29 -0700655 }
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700656
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700657 vadc->adc->amux_prop->decimation =
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700658 vadc->adc->adc_channels[dt_index].adc_decimation;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700659 vadc->adc->amux_prop->hw_settle_time =
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700660 vadc->adc->adc_channels[dt_index].hw_settle_time;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700661 vadc->adc->amux_prop->fast_avg_setup =
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700662 vadc->adc->adc_channels[dt_index].fast_avg_setup;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700663
664 if (trigger_channel < ADC_SEQ_NONE)
665 vadc->adc->amux_prop->mode_sel = (ADC_OP_CONVERSION_SEQUENCER
666 << QPNP_VADC_OP_MODE_SHIFT);
667 else if (trigger_channel == ADC_SEQ_NONE)
668 vadc->adc->amux_prop->mode_sel = (ADC_OP_NORMAL_MODE
669 << QPNP_VADC_OP_MODE_SHIFT);
670 else {
671 pr_err("Invalid trigger channel:%d\n", trigger_channel);
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700672 goto fail_unlock;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700673 }
674
675 vadc->adc->amux_prop->trigger_channel = trigger_channel;
676
677 rc = qpnp_vadc_configure(vadc->adc->amux_prop);
678 if (rc) {
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700679 pr_err("qpnp vadc configure failed with %d\n", rc);
680 goto fail_unlock;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700681 }
682
Siddartha Mohanadoss1a0d2032012-11-01 11:22:29 -0700683 rc = wait_for_completion_timeout(&vadc->adc->adc_rslt_completion,
684 QPNP_ADC_COMPLETION_TIMEOUT);
685 if (!rc) {
686 u8 status1 = 0;
687 rc = qpnp_vadc_read_reg(QPNP_VADC_STATUS1, &status1);
688 if (rc < 0)
689 goto fail_unlock;
690 status1 &= (QPNP_VADC_STATUS1_REQ_STS | QPNP_VADC_STATUS1_EOC);
691 if (status1 == QPNP_VADC_STATUS1_EOC)
692 pr_debug("End of conversion status set\n");
693 else {
Siddartha Mohanadoss9cb2c652012-12-14 19:18:18 -0800694 rc = qpnp_vadc_status_debug();
695 if (rc < 0)
696 pr_err("VADC disable failed\n");
Siddartha Mohanadoss1a0d2032012-11-01 11:22:29 -0700697 rc = -EINVAL;
698 goto fail_unlock;
699 }
700 }
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700701
702 if (trigger_channel < ADC_SEQ_NONE) {
703 rc = qpnp_vadc_read_status(vadc->adc->amux_prop->mode_sel);
704 if (rc)
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700705 pr_debug("Conversion sequence timed out - %d\n", rc);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700706 }
707
708 rc = qpnp_vadc_read_conversion_result(&result->adc_code);
709 if (rc) {
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700710 pr_err("qpnp vadc read adc code failed with %d\n", rc);
711 goto fail_unlock;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700712 }
713
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700714 amux_prescaling =
715 vadc->adc->adc_channels[dt_index].chan_path_prescaling;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700716
717 vadc->adc->amux_prop->chan_prop->offset_gain_numerator =
718 qpnp_vadc_amux_scaling_ratio[amux_prescaling].num;
719 vadc->adc->amux_prop->chan_prop->offset_gain_denominator =
720 qpnp_vadc_amux_scaling_ratio[amux_prescaling].den;
721
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700722 scale_type = vadc->adc->adc_channels[dt_index].adc_scale_fn;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700723 if (scale_type >= SCALE_NONE) {
724 rc = -EBADF;
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700725 goto fail_unlock;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700726 }
727
728 vadc_scale_fn[scale_type].chan(result->adc_code,
729 vadc->adc->adc_prop, vadc->adc->amux_prop->chan_prop, result);
730
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700731fail_unlock:
732 mutex_unlock(&vadc->adc->adc_lock);
733
734 return rc;
735}
736EXPORT_SYMBOL(qpnp_vadc_conv_seq_request);
737
738int32_t qpnp_vadc_read(enum qpnp_vadc_channels channel,
739 struct qpnp_vadc_result *result)
740{
741 return qpnp_vadc_conv_seq_request(ADC_SEQ_NONE,
742 channel, result);
743}
744EXPORT_SYMBOL_GPL(qpnp_vadc_read);
745
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -0800746static void qpnp_vadc_lock(void)
747{
748 struct qpnp_vadc_drv *vadc = qpnp_vadc;
749
750 mutex_lock(&vadc->adc->adc_lock);
751}
752
753static void qpnp_vadc_unlock(void)
754{
755 struct qpnp_vadc_drv *vadc = qpnp_vadc;
756
757 mutex_unlock(&vadc->adc->adc_lock);
758}
759
760int32_t qpnp_vadc_iadc_sync_request(enum qpnp_vadc_channels channel)
761{
762 struct qpnp_vadc_drv *vadc = qpnp_vadc;
763 int rc = 0, dt_index = 0;
764
765 if (!vadc || !vadc->vadc_initialized)
766 return -EPROBE_DEFER;
767
768 qpnp_vadc_lock();
769
770 if (!vadc->vadc_init_calib) {
771 rc = qpnp_vadc_version_check();
772 if (rc)
773 goto fail;
774
775 rc = qpnp_vadc_calib_device();
776 if (rc) {
777 pr_err("Calibration failed\n");
778 goto fail;
779 } else
780 vadc->vadc_init_calib = true;
781 }
782
783 vadc->adc->amux_prop->amux_channel = channel;
784
785 while ((vadc->adc->adc_channels[dt_index].channel_num
786 != channel) && (dt_index < vadc->max_channels_available))
787 dt_index++;
788
789 if (dt_index >= vadc->max_channels_available) {
790 pr_err("not a valid VADC channel\n");
791 rc = -EINVAL;
792 goto fail;
793 }
794
795 vadc->adc->amux_prop->decimation =
796 vadc->adc->adc_channels[dt_index].adc_decimation;
797 vadc->adc->amux_prop->hw_settle_time =
798 vadc->adc->adc_channels[dt_index].hw_settle_time;
799 vadc->adc->amux_prop->fast_avg_setup =
800 vadc->adc->adc_channels[dt_index].fast_avg_setup;
801 vadc->adc->amux_prop->mode_sel = (ADC_OP_NORMAL_MODE
802 << QPNP_VADC_OP_MODE_SHIFT);
803 vadc->vadc_iadc_sync_lock = true;
804
805 rc = qpnp_vadc_configure(vadc->adc->amux_prop);
806 if (rc) {
807 pr_err("qpnp vadc configure failed with %d\n", rc);
808 goto fail;
809 }
810
811 return rc;
812fail:
813 vadc->vadc_iadc_sync_lock = false;
814 qpnp_vadc_unlock();
815 return rc;
816}
817EXPORT_SYMBOL(qpnp_vadc_iadc_sync_request);
818
819int32_t qpnp_vadc_iadc_sync_complete_request(enum qpnp_vadc_channels channel,
820 struct qpnp_vadc_result *result)
821{
822 struct qpnp_vadc_drv *vadc = qpnp_vadc;
823 int rc = 0, scale_type, amux_prescaling, dt_index = 0;
824
825 vadc->adc->amux_prop->amux_channel = channel;
826
827 while ((vadc->adc->adc_channels[dt_index].channel_num
828 != channel) && (dt_index < vadc->max_channels_available))
829 dt_index++;
830
831 rc = qpnp_vadc_read_conversion_result(&result->adc_code);
832 if (rc) {
833 pr_err("qpnp vadc read adc code failed with %d\n", rc);
834 goto fail;
835 }
836
837 amux_prescaling =
838 vadc->adc->adc_channels[dt_index].chan_path_prescaling;
839
840 vadc->adc->amux_prop->chan_prop->offset_gain_numerator =
841 qpnp_vadc_amux_scaling_ratio[amux_prescaling].num;
842 vadc->adc->amux_prop->chan_prop->offset_gain_denominator =
843 qpnp_vadc_amux_scaling_ratio[amux_prescaling].den;
844
845 scale_type = vadc->adc->adc_channels[dt_index].adc_scale_fn;
846 if (scale_type >= SCALE_NONE) {
847 rc = -EBADF;
848 goto fail;
849 }
850
851 vadc_scale_fn[scale_type].chan(result->adc_code,
852 vadc->adc->adc_prop, vadc->adc->amux_prop->chan_prop, result);
853
854fail:
855 vadc->vadc_iadc_sync_lock = false;
856 qpnp_vadc_unlock();
857 return rc;
858}
859EXPORT_SYMBOL(qpnp_vadc_iadc_sync_complete_request);
860
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700861static ssize_t qpnp_adc_show(struct device *dev,
862 struct device_attribute *devattr, char *buf)
863{
864 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
865 struct qpnp_vadc_result result;
866 int rc = -1;
867
868 rc = qpnp_vadc_read(attr->index, &result);
869
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700870 if (rc) {
871 pr_err("VADC read error with %d\n", rc);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700872 return 0;
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700873 }
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700874
875 return snprintf(buf, QPNP_ADC_HWMON_NAME_LENGTH,
876 "Result:%lld Raw:%d\n", result.physical, result.adc_code);
877}
878
879static struct sensor_device_attribute qpnp_adc_attr =
880 SENSOR_ATTR(NULL, S_IRUGO, qpnp_adc_show, NULL, 0);
881
882static int32_t qpnp_vadc_init_hwmon(struct spmi_device *spmi)
883{
884 struct qpnp_vadc_drv *vadc = qpnp_vadc;
885 struct device_node *child;
886 struct device_node *node = spmi->dev.of_node;
887 int rc = 0, i = 0, channel;
888
889 for_each_child_of_node(node, child) {
890 channel = vadc->adc->adc_channels[i].channel_num;
891 qpnp_adc_attr.index = vadc->adc->adc_channels[i].channel_num;
892 qpnp_adc_attr.dev_attr.attr.name =
893 vadc->adc->adc_channels[i].name;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700894 memcpy(&vadc->sens_attr[i], &qpnp_adc_attr,
895 sizeof(qpnp_adc_attr));
Stephen Boydd7337962012-10-30 11:10:46 -0700896 sysfs_attr_init(&vadc->sens_attr[i].dev_attr.attr);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700897 rc = device_create_file(&spmi->dev,
898 &vadc->sens_attr[i].dev_attr);
899 if (rc) {
900 dev_err(&spmi->dev,
901 "device_create_file failed for dev %s\n",
902 vadc->adc->adc_channels[i].name);
903 goto hwmon_err_sens;
904 }
905 i++;
906 }
907
908 return 0;
909hwmon_err_sens:
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700910 pr_err("Init HWMON failed for qpnp_adc with %d\n", rc);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700911 return rc;
912}
913
914static int __devinit qpnp_vadc_probe(struct spmi_device *spmi)
915{
916 struct qpnp_vadc_drv *vadc;
917 struct qpnp_adc_drv *adc_qpnp;
918 struct device_node *node = spmi->dev.of_node;
919 struct device_node *child;
920 int rc, count_adc_channel_list = 0;
921
922 if (!node)
923 return -EINVAL;
924
925 if (qpnp_vadc) {
926 pr_err("VADC already in use\n");
927 return -EBUSY;
928 }
929
930 for_each_child_of_node(node, child)
931 count_adc_channel_list++;
932
933 if (!count_adc_channel_list) {
934 pr_err("No channel listing\n");
935 return -EINVAL;
936 }
937
938 vadc = devm_kzalloc(&spmi->dev, sizeof(struct qpnp_vadc_drv) +
939 (sizeof(struct sensor_device_attribute) *
940 count_adc_channel_list), GFP_KERNEL);
941 if (!vadc) {
942 dev_err(&spmi->dev, "Unable to allocate memory\n");
943 return -ENOMEM;
944 }
945
946 adc_qpnp = devm_kzalloc(&spmi->dev, sizeof(struct qpnp_adc_drv),
947 GFP_KERNEL);
948 if (!adc_qpnp) {
949 dev_err(&spmi->dev, "Unable to allocate memory\n");
Siddartha Mohanadossb60f6462012-11-20 18:06:51 -0800950 rc = -ENOMEM;
951 goto fail;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700952 }
953
954 vadc->adc = adc_qpnp;
955
956 rc = qpnp_adc_get_devicetree_data(spmi, vadc->adc);
957 if (rc) {
958 dev_err(&spmi->dev, "failed to read device tree\n");
Siddartha Mohanadossb60f6462012-11-20 18:06:51 -0800959 goto fail;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700960 }
961
Siddartha Mohanadoss12109952012-11-20 14:57:51 -0800962 rc = devm_request_irq(&spmi->dev, vadc->adc->adc_irq_eoc,
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700963 qpnp_vadc_isr, IRQF_TRIGGER_RISING,
964 "qpnp_vadc_interrupt", vadc);
965 if (rc) {
966 dev_err(&spmi->dev,
967 "failed to request adc irq with error %d\n", rc);
Siddartha Mohanadossb60f6462012-11-20 18:06:51 -0800968 goto fail;
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700969 } else {
Siddartha Mohanadoss12109952012-11-20 14:57:51 -0800970 enable_irq_wake(vadc->adc->adc_irq_eoc);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700971 }
972
973 qpnp_vadc = vadc;
974 dev_set_drvdata(&spmi->dev, vadc);
975 rc = qpnp_vadc_init_hwmon(spmi);
976 if (rc) {
977 dev_err(&spmi->dev, "failed to initialize qpnp hwmon adc\n");
Siddartha Mohanadossb60f6462012-11-20 18:06:51 -0800978 goto fail;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700979 }
980 vadc->vadc_hwmon = hwmon_device_register(&vadc->adc->spmi->dev);
981 vadc->vadc_init_calib = false;
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700982 vadc->max_channels_available = count_adc_channel_list;
Siddartha Mohanadoss0ee28122012-11-01 10:35:01 -0700983 vadc->vadc_initialized = true;
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -0800984 vadc->vadc_iadc_sync_lock = false;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700985
986 return 0;
Siddartha Mohanadossb60f6462012-11-20 18:06:51 -0800987fail:
988 qpnp_vadc = NULL;
989 return rc;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700990}
991
992static int __devexit qpnp_vadc_remove(struct spmi_device *spmi)
993{
994 struct qpnp_vadc_drv *vadc = dev_get_drvdata(&spmi->dev);
995 struct device_node *node = spmi->dev.of_node;
996 struct device_node *child;
997 int i = 0;
998
999 for_each_child_of_node(node, child) {
1000 device_remove_file(&spmi->dev,
1001 &vadc->sens_attr[i].dev_attr);
1002 i++;
1003 }
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -07001004 vadc->vadc_initialized = false;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001005 dev_set_drvdata(&spmi->dev, NULL);
1006
1007 return 0;
1008}
1009
1010static const struct of_device_id qpnp_vadc_match_table[] = {
1011 { .compatible = "qcom,qpnp-vadc",
1012 },
1013 {}
1014};
1015
1016static struct spmi_driver qpnp_vadc_driver = {
1017 .driver = {
1018 .name = "qcom,qpnp-vadc",
1019 .of_match_table = qpnp_vadc_match_table,
1020 },
1021 .probe = qpnp_vadc_probe,
1022 .remove = qpnp_vadc_remove,
1023};
1024
1025static int __init qpnp_vadc_init(void)
1026{
1027 return spmi_driver_register(&qpnp_vadc_driver);
1028}
1029module_init(qpnp_vadc_init);
1030
1031static void __exit qpnp_vadc_exit(void)
1032{
1033 spmi_driver_unregister(&qpnp_vadc_driver);
1034}
1035module_exit(qpnp_vadc_exit);
1036
1037MODULE_DESCRIPTION("QPNP PMIC Voltage ADC driver");
1038MODULE_LICENSE("GPL v2");