blob: 346a72d5784f8cf2f23d22b40f1e1eb3e9154b48 [file] [log] [blame]
Siddartha Mohanadoss03d8c6c2014-02-03 17:12:19 -08001/* Copyright (c) 2012-2014, 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
Siddartha Mohanadoss22559462013-05-15 15:30:28 -070086#define QPNP_VADC_ACCESS 0xd0
87#define QPNP_VADC_ACCESS_DATA 0xa5
88#define QPNP_VADC_PERH_RESET_CTL3 0xda
89#define QPNP_FOLLOW_OTST2_RB BIT(3)
90#define QPNP_FOLLOW_WARM_RB BIT(2)
91#define QPNP_FOLLOW_SHUTDOWN1_RB BIT(1)
92#define QPNP_FOLLOW_SHUTDOWN2_RB BIT(0)
93
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -070094#define QPNP_INT_TEST_VAL 0xE1
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -070095
96#define QPNP_VADC_DATA0 0x60
97#define QPNP_VADC_DATA1 0x61
98#define QPNP_VADC_CONV_TIMEOUT_ERR 2
99#define QPNP_VADC_CONV_TIME_MIN 2000
100#define QPNP_VADC_CONV_TIME_MAX 2100
Siddartha Mohanadoss1a0d2032012-11-01 11:22:29 -0700101#define QPNP_ADC_COMPLETION_TIMEOUT HZ
Siddartha Mohanadoss462088b2013-07-27 19:58:09 -0700102#define QPNP_VADC_ERR_COUNT 20
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700103
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700104struct qpnp_vadc_chip {
105 struct device *dev;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700106 struct qpnp_adc_drv *adc;
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700107 struct list_head list;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700108 struct dentry *dent;
109 struct device *vadc_hwmon;
110 bool vadc_init_calib;
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700111 int max_channels_available;
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -0800112 bool vadc_iadc_sync_lock;
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -0700113 u8 id;
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700114 struct work_struct trigger_completion_work;
Siddartha Mohanadoss462088b2013-07-27 19:58:09 -0700115 bool vadc_poll_eoc;
Siddartha Mohanadossf3db6142013-08-09 16:54:47 -0700116 u8 revision_ana_minor;
117 u8 revision_dig_major;
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -0700118 struct sensor_device_attribute sens_attr[0];
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700119};
120
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700121LIST_HEAD(qpnp_vadc_device_list);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700122
123static struct qpnp_vadc_scale_fn vadc_scale_fn[] = {
124 [SCALE_DEFAULT] = {qpnp_adc_scale_default},
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700125 [SCALE_BATT_THERM] = {qpnp_adc_scale_batt_therm},
126 [SCALE_PMIC_THERM] = {qpnp_adc_scale_pmic_therm},
127 [SCALE_XOTHERM] = {qpnp_adc_tdkntcg_therm},
Siddartha Mohanadosse77edf12012-09-13 14:26:32 -0700128 [SCALE_THERM_100K_PULLUP] = {qpnp_adc_scale_therm_pu2},
129 [SCALE_THERM_150K_PULLUP] = {qpnp_adc_scale_therm_pu1},
Siddartha Mohanadossb99cfa92013-05-01 20:19:58 -0700130 [SCALE_QRD_BATT_THERM] = {qpnp_adc_scale_qrd_batt_therm},
Xu Kai81c60522013-07-27 14:26:04 +0800131 [SCALE_QRD_SKUAA_BATT_THERM] = {qpnp_adc_scale_qrd_skuaa_batt_therm},
Wu Fenglin2c6ef8f2013-12-17 11:33:33 +0800132 [SCALE_QRD_SKUG_BATT_THERM] = {qpnp_adc_scale_qrd_skug_batt_therm},
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700133};
134
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700135static int32_t qpnp_vadc_read_reg(struct qpnp_vadc_chip *vadc, int16_t reg,
136 u8 *data)
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700137{
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700138 int rc;
139
140 rc = spmi_ext_register_readl(vadc->adc->spmi->ctrl, vadc->adc->slave,
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700141 (vadc->adc->offset + reg), data, 1);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700142 if (rc < 0) {
143 pr_err("qpnp adc read reg %d failed with %d\n", reg, rc);
144 return rc;
145 }
146
147 return 0;
148}
149
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700150static int32_t qpnp_vadc_write_reg(struct qpnp_vadc_chip *vadc, int16_t reg,
151 u8 data)
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700152{
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700153 int rc;
154 u8 *buf;
155
156 buf = &data;
157
158 rc = spmi_ext_register_writel(vadc->adc->spmi->ctrl, vadc->adc->slave,
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700159 (vadc->adc->offset + reg), buf, 1);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700160 if (rc < 0) {
161 pr_err("qpnp adc write reg %d failed with %d\n", reg, rc);
162 return rc;
163 }
164
165 return 0;
166}
167
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700168static int32_t qpnp_vadc_warm_rst_configure(struct qpnp_vadc_chip *vadc)
Siddartha Mohanadoss22559462013-05-15 15:30:28 -0700169{
170 int rc = 0;
171 u8 data = 0;
172
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700173 rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_ACCESS, QPNP_VADC_ACCESS_DATA);
Siddartha Mohanadoss22559462013-05-15 15:30:28 -0700174 if (rc < 0) {
175 pr_err("VADC write access failed\n");
176 return rc;
177 }
178
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700179 rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_PERH_RESET_CTL3, &data);
Siddartha Mohanadoss22559462013-05-15 15:30:28 -0700180 if (rc < 0) {
181 pr_err("VADC perh reset ctl3 read failed\n");
182 return rc;
183 }
184
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700185 rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_ACCESS, QPNP_VADC_ACCESS_DATA);
Siddartha Mohanadoss22559462013-05-15 15:30:28 -0700186 if (rc < 0) {
187 pr_err("VADC write access failed\n");
188 return rc;
189 }
190
191 data |= QPNP_FOLLOW_WARM_RB;
192
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700193 rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_PERH_RESET_CTL3, data);
Siddartha Mohanadoss22559462013-05-15 15:30:28 -0700194 if (rc < 0) {
195 pr_err("VADC perh reset ctl3 write failed\n");
196 return rc;
197 }
198
199 return 0;
200}
201
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700202static int32_t qpnp_vadc_enable(struct qpnp_vadc_chip *vadc, bool state)
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700203{
204 int rc = 0;
205 u8 data = 0;
206
207 data = QPNP_VADC_ADC_EN;
208 if (state) {
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700209 rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_EN_CTL1,
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700210 data);
211 if (rc < 0) {
212 pr_err("VADC enable failed\n");
213 return rc;
214 }
215 } else {
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700216 rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_EN_CTL1,
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700217 (~data & QPNP_VADC_ADC_EN));
218 if (rc < 0) {
219 pr_err("VADC disable failed\n");
220 return rc;
221 }
222 }
223
224 return 0;
225}
226
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700227static int32_t qpnp_vadc_status_debug(struct qpnp_vadc_chip *vadc)
Siddartha Mohanadoss9cb2c652012-12-14 19:18:18 -0800228{
229 int rc = 0;
230 u8 mode = 0, status1 = 0, chan = 0, dig = 0, en = 0, status2 = 0;
231
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700232 rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_MODE_CTL, &mode);
Siddartha Mohanadoss9cb2c652012-12-14 19:18:18 -0800233 if (rc < 0) {
234 pr_err("mode ctl register read failed with %d\n", rc);
235 return rc;
236 }
237
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700238 rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_ADC_DIG_PARAM, &dig);
Siddartha Mohanadoss9cb2c652012-12-14 19:18:18 -0800239 if (rc < 0) {
240 pr_err("digital param read failed with %d\n", rc);
241 return rc;
242 }
243
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700244 rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_ADC_CH_SEL_CTL, &chan);
Siddartha Mohanadoss9cb2c652012-12-14 19:18:18 -0800245 if (rc < 0) {
246 pr_err("channel read failed with %d\n", rc);
247 return rc;
248 }
249
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700250 rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_STATUS1, &status1);
Siddartha Mohanadoss9cb2c652012-12-14 19:18:18 -0800251 if (rc < 0) {
252 pr_err("status1 read failed with %d\n", rc);
253 return rc;
254 }
255
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700256 rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_STATUS2, &status2);
Siddartha Mohanadoss9cb2c652012-12-14 19:18:18 -0800257 if (rc < 0) {
258 pr_err("status2 read failed with %d\n", rc);
259 return rc;
260 }
261
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700262 rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_EN_CTL1, &en);
Siddartha Mohanadoss9cb2c652012-12-14 19:18:18 -0800263 if (rc < 0) {
264 pr_err("en read failed with %d\n", rc);
265 return rc;
266 }
267
268 pr_err("EOC not set - status1/2:%x/%x, dig:%x, ch:%x, mode:%x, en:%x\n",
269 status1, status2, dig, chan, mode, en);
270
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700271 rc = qpnp_vadc_enable(vadc, false);
Siddartha Mohanadoss9cb2c652012-12-14 19:18:18 -0800272 if (rc < 0) {
273 pr_err("VADC disable failed with %d\n", rc);
274 return rc;
275 }
276
277 return 0;
278}
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700279static int32_t qpnp_vadc_configure(struct qpnp_vadc_chip *vadc,
Siddartha Mohanadossc4a6af12012-07-13 18:50:12 -0700280 struct qpnp_adc_amux_properties *chan_prop)
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700281{
282 u8 decimation = 0, conv_sequence = 0, conv_sequence_trig = 0;
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700283 u8 mode_ctrl = 0;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700284 int rc = 0;
285
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700286 /* Mode selection */
Siddartha Mohanadoss429b4492012-12-11 13:29:58 -0800287 mode_ctrl |= ((chan_prop->mode_sel << QPNP_VADC_OP_MODE_SHIFT) |
288 (QPNP_VADC_ADC_TRIM_EN | QPNP_VADC_AMUX_TRIM_EN));
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700289 rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_MODE_CTL, mode_ctrl);
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700290 if (rc < 0) {
291 pr_err("Mode configure write error\n");
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700292 return rc;
293 }
294
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700295
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700296 /* Channel selection */
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700297 rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_ADC_CH_SEL_CTL,
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700298 chan_prop->amux_channel);
299 if (rc < 0) {
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700300 pr_err("Channel configure error\n");
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700301 return rc;
302 }
303
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700304 /* Digital parameter setup */
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700305 decimation = chan_prop->decimation <<
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700306 QPNP_VADC_ADC_DIG_DEC_RATIO_SEL_SHIFT;
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700307 rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_ADC_DIG_PARAM, decimation);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700308 if (rc < 0) {
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700309 pr_err("Digital parameter configure write error\n");
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700310 return rc;
311 }
312
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700313 /* HW settling time delay */
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700314 rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_HW_SETTLE_DELAY,
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700315 chan_prop->hw_settle_time);
316 if (rc < 0) {
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700317 pr_err("HW settling time setup error\n");
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700318 return rc;
319 }
320
321 if (chan_prop->mode_sel == (ADC_OP_NORMAL_MODE <<
322 QPNP_VADC_OP_MODE_SHIFT)) {
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700323 /* Normal measurement mode */
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700324 rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_FAST_AVG_CTL,
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700325 chan_prop->fast_avg_setup);
326 if (rc < 0) {
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700327 pr_err("Fast averaging configure error\n");
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700328 return rc;
329 }
330 } else if (chan_prop->mode_sel == (ADC_OP_CONVERSION_SEQUENCER <<
331 QPNP_VADC_OP_MODE_SHIFT)) {
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700332 /* Conversion sequence mode */
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700333 conv_sequence = ((ADC_SEQ_HOLD_100US <<
334 QPNP_VADC_CONV_SEQ_HOLDOFF_SHIFT) |
335 ADC_CONV_SEQ_TIMEOUT_5MS);
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700336 rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_CONV_SEQ_CTL,
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700337 conv_sequence);
338 if (rc < 0) {
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700339 pr_err("Conversion sequence error\n");
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700340 return rc;
341 }
342
343 conv_sequence_trig = ((QPNP_VADC_CONV_SEQ_RISING_EDGE <<
344 QPNP_VADC_CONV_SEQ_EDGE_SHIFT) |
345 chan_prop->trigger_channel);
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700346 rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_CONV_SEQ_TRIG_CTL,
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700347 conv_sequence_trig);
348 if (rc < 0) {
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700349 pr_err("Conversion trigger error\n");
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700350 return rc;
351 }
352 }
353
Siddartha Mohanadoss462088b2013-07-27 19:58:09 -0700354 if (!vadc->vadc_poll_eoc)
355 INIT_COMPLETION(vadc->adc->adc_rslt_completion);
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700356
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700357 rc = qpnp_vadc_enable(vadc, true);
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700358 if (rc)
359 return rc;
360
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -0800361 if (!vadc->vadc_iadc_sync_lock) {
362 /* Request conversion */
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700363 rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_CONV_REQ,
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -0800364 QPNP_VADC_CONV_REQ_SET);
365 if (rc < 0) {
366 pr_err("Request conversion failed\n");
367 return rc;
368 }
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700369 }
370
371 return 0;
372}
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700373
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700374static int32_t qpnp_vadc_read_conversion_result(struct qpnp_vadc_chip *vadc,
375 int32_t *data)
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700376{
377 uint8_t rslt_lsb, rslt_msb;
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700378 int rc = 0, status = 0;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700379
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700380 status = qpnp_vadc_read_reg(vadc, QPNP_VADC_DATA0, &rslt_lsb);
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700381 if (status < 0) {
382 pr_err("qpnp adc result read failed for data0\n");
383 goto fail;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700384 }
385
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700386 status = qpnp_vadc_read_reg(vadc, QPNP_VADC_DATA1, &rslt_msb);
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700387 if (status < 0) {
388 pr_err("qpnp adc result read failed for data1\n");
389 goto fail;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700390 }
391
392 *data = (rslt_msb << 8) | rslt_lsb;
393
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700394 status = qpnp_vadc_check_result(data);
395 if (status < 0) {
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700396 pr_err("VADC data check failed\n");
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700397 goto fail;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700398 }
399
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700400fail:
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700401 rc = qpnp_vadc_enable(vadc, false);
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700402 if (rc)
403 return rc;
404
405 return status;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700406}
407
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700408static int32_t qpnp_vadc_read_status(struct qpnp_vadc_chip *vadc, int mode_sel)
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700409{
410 u8 status1, status2, status2_conv_seq_state;
411 u8 status_err = QPNP_VADC_CONV_TIMEOUT_ERR;
412 int rc;
413
414 switch (mode_sel) {
415 case (ADC_OP_CONVERSION_SEQUENCER << QPNP_VADC_OP_MODE_SHIFT):
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700416 rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_STATUS1, &status1);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700417 if (rc) {
418 pr_err("qpnp_vadc read mask interrupt failed\n");
419 return rc;
420 }
421
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700422 rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_STATUS2, &status2);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700423 if (rc) {
424 pr_err("qpnp_vadc read mask interrupt failed\n");
425 return rc;
426 }
427
428 if (!(status2 & ~QPNP_VADC_STATUS2_CONV_SEQ_TIMEOUT_STS) &&
429 (status1 & (~QPNP_VADC_STATUS1_REQ_STS |
430 QPNP_VADC_STATUS1_EOC))) {
431 rc = status_err;
432 return rc;
433 }
434
435 status2_conv_seq_state = status2 >>
436 QPNP_VADC_STATUS2_CONV_SEQ_STATE_SHIFT;
437 if (status2_conv_seq_state != ADC_CONV_SEQ_IDLE) {
438 pr_err("qpnp vadc seq error with status %d\n",
439 status2);
440 rc = -EINVAL;
441 return rc;
442 }
443 }
444
445 return 0;
446}
447
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700448static int qpnp_vadc_is_valid(struct qpnp_vadc_chip *vadc)
449{
450 struct qpnp_vadc_chip *vadc_chip = NULL;
451
452 list_for_each_entry(vadc_chip, &qpnp_vadc_device_list, list)
453 if (vadc == vadc_chip)
454 return 0;
455
456 return -EINVAL;
457}
458
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700459static void qpnp_vadc_work(struct work_struct *work)
460{
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700461 struct qpnp_vadc_chip *vadc = container_of(work,
462 struct qpnp_vadc_chip, trigger_completion_work);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700463
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700464 if (qpnp_vadc_is_valid(vadc) < 0)
Siddartha Mohanadossb60f6462012-11-20 18:06:51 -0800465 return;
466
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700467 complete(&vadc->adc->adc_rslt_completion);
468
469 return;
470}
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700471
472static irqreturn_t qpnp_vadc_isr(int irq, void *dev_id)
473{
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700474 struct qpnp_vadc_chip *vadc = dev_id;
475
476 schedule_work(&vadc->trigger_completion_work);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700477
478 return IRQ_HANDLED;
479}
480
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700481static int32_t qpnp_vadc_version_check(struct qpnp_vadc_chip *dev)
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700482{
483 uint8_t revision;
484 int rc;
485
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700486 rc = qpnp_vadc_read_reg(dev, QPNP_VADC_REVISION2, &revision);
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700487 if (rc < 0) {
488 pr_err("qpnp adc result read failed with %d\n", rc);
489 return rc;
490 }
491
492 if (revision < QPNP_VADC_SUPPORTED_REVISION2) {
493 pr_err("VADC Version not supported\n");
494 return -EINVAL;
495 }
496
497 return 0;
498}
499
Siddartha Mohanadossf3db6142013-08-09 16:54:47 -0700500#define QPNP_VBAT_COEFF_1 3000
501#define QPNP_VBAT_COEFF_2 45810000
502#define QPNP_VBAT_COEFF_3 100000
503#define QPNP_VBAT_COEFF_4 3500
504#define QPNP_VBAT_COEFF_5 80000000
505#define QPNP_VBAT_COEFF_6 4400
506#define QPNP_VBAT_COEFF_7 32200000
507#define QPNP_VBAT_COEFF_8 3880
508#define QPNP_VBAT_COEFF_9 5770
509#define QPNP_VBAT_COEFF_10 3660
510#define QPNP_VBAT_COEFF_11 5320
511#define QPNP_VBAT_COEFF_12 8060000
512#define QPNP_VBAT_COEFF_13 102640000
513#define QPNP_VBAT_COEFF_14 22220000
514#define QPNP_VBAT_COEFF_15 83060000
Xiaozhe Shi80754222013-10-30 14:11:41 -0700515#define QPNP_VBAT_COEFF_16 2810
516#define QPNP_VBAT_COEFF_17 5260
517#define QPNP_VBAT_COEFF_18 8027
518#define QPNP_VBAT_COEFF_19 2347
519#define QPNP_VBAT_COEFF_20 6043
520#define QPNP_VBAT_COEFF_21 1914
521#define QPNP_VBAT_OFFSET_SMIC 9446
522#define QPNP_VBAT_OFFSET_GF 9441
523#define QPNP_OCV_OFFSET_SMIC 4596
524#define QPNP_OCV_OFFSET_GF 5896
Siddartha Mohanadoss03d8c6c2014-02-03 17:12:19 -0800525#define QPNP_VBAT_COEFF_22 6800
526#define QPNP_VBAT_COEFF_23 3500
527#define QPNP_VBAT_COEFF_24 4360
528#define QPNP_VBAT_COEFF_25 8060
Siddartha Mohanadossf3db6142013-08-09 16:54:47 -0700529
Siddartha Mohanadossf3db6142013-08-09 16:54:47 -0700530static int32_t qpnp_ocv_comp(int64_t *result,
531 struct qpnp_vadc_chip *vadc, int64_t die_temp)
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -0700532{
533 int64_t temp_var = 0;
Xiaozhe Shi62ad5e12013-05-13 12:37:41 -0700534 int64_t old = *result;
Siddartha Mohanadoss93761842013-09-11 17:46:54 -0700535 int version;
Siddartha Mohanadossf3db6142013-08-09 16:54:47 -0700536
Siddartha Mohanadoss93761842013-09-11 17:46:54 -0700537 version = qpnp_adc_get_revid_version(vadc->dev);
Siddartha Mohanadossf3db6142013-08-09 16:54:47 -0700538 if (version == -EINVAL)
539 return 0;
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -0700540
Siddartha Mohanadoss747fb792014-02-14 11:23:16 -0800541 if (version == QPNP_REV_ID_8026_2_2) {
Siddartha Mohanadoss03d8c6c2014-02-03 17:12:19 -0800542 if (die_temp > 25000)
543 return 0;
Xiaozhe Shi80754222013-10-30 14:11:41 -0700544 }
Siddartha Mohanadossf3db6142013-08-09 16:54:47 -0700545
546 switch (version) {
Siddartha Mohanadoss93761842013-09-11 17:46:54 -0700547 case QPNP_REV_ID_8941_3_1:
Siddartha Mohanadossf3db6142013-08-09 16:54:47 -0700548 switch (vadc->id) {
549 case COMP_ID_TSMC:
Siddartha Mohanadoss747fb792014-02-14 11:23:16 -0800550 temp_var = ((die_temp - 25000) *
551 (-QPNP_VBAT_COEFF_4));
Siddartha Mohanadossf3db6142013-08-09 16:54:47 -0700552 break;
553 default:
554 case COMP_ID_GF:
Siddartha Mohanadoss747fb792014-02-14 11:23:16 -0800555 temp_var = ((die_temp - 25000) *
556 (-QPNP_VBAT_COEFF_1));
Siddartha Mohanadossf3db6142013-08-09 16:54:47 -0700557 break;
558 }
559 break;
Siddartha Mohanadoss93761842013-09-11 17:46:54 -0700560 case QPNP_REV_ID_8026_1_0:
Siddartha Mohanadossf3db6142013-08-09 16:54:47 -0700561 switch (vadc->id) {
562 case COMP_ID_TSMC:
563 temp_var = (((die_temp *
564 (-QPNP_VBAT_COEFF_10))
565 - QPNP_VBAT_COEFF_14));
566 break;
567 default:
568 case COMP_ID_GF:
569 temp_var = (((die_temp *
570 (-QPNP_VBAT_COEFF_8))
571 + QPNP_VBAT_COEFF_12));
572 break;
573 }
574 break;
Siddartha Mohanadoss93761842013-09-11 17:46:54 -0700575 case QPNP_REV_ID_8026_2_0:
576 case QPNP_REV_ID_8026_2_1:
Siddartha Mohanadossf3db6142013-08-09 16:54:47 -0700577 switch (vadc->id) {
578 case COMP_ID_TSMC:
Xiaozhe Shi80754222013-10-30 14:11:41 -0700579 temp_var = ((die_temp - 25000) *
Siddartha Mohanadossf3db6142013-08-09 16:54:47 -0700580 (-QPNP_VBAT_COEFF_10));
581 break;
582 default:
583 case COMP_ID_GF:
Xiaozhe Shi80754222013-10-30 14:11:41 -0700584 temp_var = ((die_temp - 25000) *
Siddartha Mohanadossf3db6142013-08-09 16:54:47 -0700585 (-QPNP_VBAT_COEFF_8));
586 break;
587 }
588 break;
Siddartha Mohanadoss03d8c6c2014-02-03 17:12:19 -0800589 case QPNP_REV_ID_8026_2_2:
590 switch (vadc->id) {
591 case COMP_ID_TSMC:
592 *result -= QPNP_VBAT_COEFF_22;
593 temp_var = (die_temp - 25000) *
594 QPNP_VBAT_COEFF_24;
595 break;
596 default:
597 case COMP_ID_GF:
598 *result -= QPNP_VBAT_COEFF_22;
599 temp_var = (die_temp - 25000) *
600 QPNP_VBAT_COEFF_25;
601 break;
602 }
Xiaozhe Shi80754222013-10-30 14:11:41 -0700603 case QPNP_REV_ID_8110_2_0:
604 switch (vadc->id) {
605 case COMP_ID_SMIC:
606 *result -= QPNP_OCV_OFFSET_SMIC;
607 if (die_temp < 25000)
608 temp_var = QPNP_VBAT_COEFF_18;
609 else
610 temp_var = QPNP_VBAT_COEFF_19;
611 temp_var = (die_temp - 25000) * temp_var;
612 break;
Xiaozhe Shi80754222013-10-30 14:11:41 -0700613 default:
614 case COMP_ID_GF:
615 *result -= QPNP_OCV_OFFSET_GF;
616 if (die_temp < 25000)
617 temp_var = QPNP_VBAT_COEFF_20;
618 else
619 temp_var = QPNP_VBAT_COEFF_21;
620 temp_var = (die_temp - 25000) * temp_var;
621 break;
622 }
623 break;
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -0700624 default:
Siddartha Mohanadossf3db6142013-08-09 16:54:47 -0700625 temp_var = 0;
626 break;
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -0700627 }
628
Siddartha Mohanadossf3db6142013-08-09 16:54:47 -0700629 temp_var = div64_s64(temp_var, QPNP_VBAT_COEFF_3);
630
631 temp_var = 1000000 + temp_var;
632
633 *result = *result * temp_var;
634
635 *result = div64_s64(*result, 1000000);
636 pr_debug("%lld compensated into %lld\n", old, *result);
637
638 return 0;
639}
640
641static int32_t qpnp_vbat_sns_comp(int64_t *result,
642 struct qpnp_vadc_chip *vadc, int64_t die_temp)
643{
644 int64_t temp_var = 0;
645 int64_t old = *result;
Siddartha Mohanadoss93761842013-09-11 17:46:54 -0700646 int version;
Siddartha Mohanadossf3db6142013-08-09 16:54:47 -0700647
Siddartha Mohanadoss93761842013-09-11 17:46:54 -0700648 version = qpnp_adc_get_revid_version(vadc->dev);
Siddartha Mohanadossf3db6142013-08-09 16:54:47 -0700649 if (version == -EINVAL)
650 return 0;
651
Siddartha Mohanadoss747fb792014-02-14 11:23:16 -0800652 if (version != QPNP_REV_ID_8941_3_1) {
Xiaozhe Shi80754222013-10-30 14:11:41 -0700653 /* min(die_temp_c, 60_degC) */
654 if (die_temp > 60000)
655 die_temp = 60000;
656 }
Siddartha Mohanadossf3db6142013-08-09 16:54:47 -0700657
658 switch (version) {
Siddartha Mohanadoss93761842013-09-11 17:46:54 -0700659 case QPNP_REV_ID_8941_3_1:
Siddartha Mohanadossf3db6142013-08-09 16:54:47 -0700660 switch (vadc->id) {
661 case COMP_ID_TSMC:
Siddartha Mohanadoss747fb792014-02-14 11:23:16 -0800662 temp_var = ((die_temp - 25000) *
Siddartha Mohanadossf3db6142013-08-09 16:54:47 -0700663 (-QPNP_VBAT_COEFF_1));
664 break;
665 default:
666 case COMP_ID_GF:
Siddartha Mohanadoss747fb792014-02-14 11:23:16 -0800667 /* min(die_temp_c, 60_degC) */
668 if (die_temp > 60000)
669 die_temp = 60000;
670 temp_var = ((die_temp - 25000) *
671 (-QPNP_VBAT_COEFF_1));
Siddartha Mohanadossf3db6142013-08-09 16:54:47 -0700672 break;
673 }
674 break;
Siddartha Mohanadoss93761842013-09-11 17:46:54 -0700675 case QPNP_REV_ID_8026_1_0:
Siddartha Mohanadossf3db6142013-08-09 16:54:47 -0700676 switch (vadc->id) {
677 case COMP_ID_TSMC:
678 temp_var = (((die_temp *
679 (-QPNP_VBAT_COEFF_11))
680 + QPNP_VBAT_COEFF_15));
681 break;
682 default:
683 case COMP_ID_GF:
684 temp_var = (((die_temp *
685 (-QPNP_VBAT_COEFF_9))
686 + QPNP_VBAT_COEFF_13));
687 break;
688 }
689 break;
Siddartha Mohanadoss93761842013-09-11 17:46:54 -0700690 case QPNP_REV_ID_8026_2_0:
691 case QPNP_REV_ID_8026_2_1:
Siddartha Mohanadossf3db6142013-08-09 16:54:47 -0700692 switch (vadc->id) {
693 case COMP_ID_TSMC:
Xiaozhe Shi80754222013-10-30 14:11:41 -0700694 temp_var = ((die_temp - 25000) *
Siddartha Mohanadossf3db6142013-08-09 16:54:47 -0700695 (-QPNP_VBAT_COEFF_11));
696 break;
697 default:
698 case COMP_ID_GF:
Xiaozhe Shi80754222013-10-30 14:11:41 -0700699 temp_var = ((die_temp - 25000) *
Siddartha Mohanadossf3db6142013-08-09 16:54:47 -0700700 (-QPNP_VBAT_COEFF_9));
701 break;
702 }
703 break;
Siddartha Mohanadoss03d8c6c2014-02-03 17:12:19 -0800704 case QPNP_REV_ID_8026_2_2:
705 switch (vadc->id) {
706 case COMP_ID_TSMC:
707 *result -= QPNP_VBAT_COEFF_23;
708 temp_var = 0;
709 break;
710 default:
711 case COMP_ID_GF:
712 *result -= QPNP_VBAT_COEFF_23;
713 temp_var = 0;
714 break;
715 }
Xiaozhe Shi80754222013-10-30 14:11:41 -0700716 case QPNP_REV_ID_8110_2_0:
717 switch (vadc->id) {
718 case COMP_ID_SMIC:
719 *result -= QPNP_VBAT_OFFSET_SMIC;
720 temp_var = ((die_temp - 25000) *
721 (QPNP_VBAT_COEFF_17));
722 break;
Xiaozhe Shi80754222013-10-30 14:11:41 -0700723 default:
724 case COMP_ID_GF:
725 *result -= QPNP_VBAT_OFFSET_GF;
726 temp_var = ((die_temp - 25000) *
727 (QPNP_VBAT_COEFF_16));
728 break;
729 }
730 break;
Siddartha Mohanadossf3db6142013-08-09 16:54:47 -0700731 default:
732 temp_var = 0;
733 break;
734 }
735
736 temp_var = div64_s64(temp_var, QPNP_VBAT_COEFF_3);
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -0700737
738 temp_var = 1000000 + temp_var;
739
740 *result = *result * temp_var;
741
742 *result = div64_s64(*result, 1000000);
Xiaozhe Shi62ad5e12013-05-13 12:37:41 -0700743 pr_debug("%lld compensated into %lld\n", old, *result);
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -0700744
745 return 0;
746}
747
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700748int32_t qpnp_vbat_sns_comp_result(struct qpnp_vadc_chip *vadc,
Xiaozhe Shi80754222013-10-30 14:11:41 -0700749 int64_t *result, bool is_pon_ocv)
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -0700750{
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -0700751 struct qpnp_vadc_result die_temp_result;
752 int rc = 0;
753
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700754 rc = qpnp_vadc_is_valid(vadc);
755 if (rc < 0)
756 return rc;
757
758 rc = qpnp_vadc_conv_seq_request(vadc, ADC_SEQ_NONE,
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -0700759 DIE_TEMP, &die_temp_result);
760 if (rc < 0) {
761 pr_err("Error reading die_temp\n");
762 return rc;
763 }
764
Xiaozhe Shi80754222013-10-30 14:11:41 -0700765 if (is_pon_ocv)
766 rc = qpnp_ocv_comp(result, vadc, die_temp_result.physical);
767 else
768 rc = qpnp_vbat_sns_comp(result, vadc,
769 die_temp_result.physical);
770
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -0700771 if (rc < 0)
772 pr_err("Error with vbat compensation\n");
773
774 return rc;
775}
776EXPORT_SYMBOL(qpnp_vbat_sns_comp_result);
777
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700778static void qpnp_vadc_625mv_channel_sel(struct qpnp_vadc_chip *vadc,
779 uint32_t *ref_channel_sel)
Siddartha Mohanadoss9edb61e2013-04-29 13:52:52 -0700780{
Siddartha Mohanadoss9edb61e2013-04-29 13:52:52 -0700781 uint32_t dt_index = 0;
782
783 /* Check if the buffered 625mV channel exists */
784 while ((vadc->adc->adc_channels[dt_index].channel_num
785 != SPARE1) && (dt_index < vadc->max_channels_available))
786 dt_index++;
787
788 if (dt_index >= vadc->max_channels_available) {
789 pr_debug("Use default 625mV ref channel\n");
790 *ref_channel_sel = REF_625MV;
791 } else {
792 pr_debug("Use buffered 625mV ref channel\n");
793 *ref_channel_sel = SPARE1;
794 }
795}
796
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700797static int32_t qpnp_vadc_calib_device(struct qpnp_vadc_chip *vadc)
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700798{
Siddartha Mohanadossc4a6af12012-07-13 18:50:12 -0700799 struct qpnp_adc_amux_properties conv;
Siddartha Mohanadoss73ae69b2013-04-03 17:34:03 -0700800 int rc, calib_read_1, calib_read_2, count = 0;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700801 u8 status1 = 0;
Siddartha Mohanadoss9edb61e2013-04-29 13:52:52 -0700802 uint32_t ref_channel_sel = 0;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700803
804 conv.amux_channel = REF_125V;
805 conv.decimation = DECIMATION_TYPE2;
806 conv.mode_sel = ADC_OP_NORMAL_MODE << QPNP_VADC_OP_MODE_SHIFT;
807 conv.hw_settle_time = ADC_CHANNEL_HW_SETTLE_DELAY_0US;
808 conv.fast_avg_setup = ADC_FAST_AVG_SAMPLE_1;
809
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700810 rc = qpnp_vadc_configure(vadc, &conv);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700811 if (rc) {
812 pr_err("qpnp_vadc configure failed with %d\n", rc);
813 goto calib_fail;
814 }
815
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700816 while (status1 != QPNP_VADC_STATUS1_EOC) {
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700817 rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_STATUS1, &status1);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700818 if (rc < 0)
819 return rc;
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700820 status1 &= QPNP_VADC_STATUS1_REQ_STS_EOC_MASK;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700821 usleep_range(QPNP_VADC_CONV_TIME_MIN,
822 QPNP_VADC_CONV_TIME_MAX);
Siddartha Mohanadoss73ae69b2013-04-03 17:34:03 -0700823 count++;
824 if (count > QPNP_VADC_ERR_COUNT) {
825 rc = -ENODEV;
826 goto calib_fail;
827 }
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700828 }
829
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700830 rc = qpnp_vadc_read_conversion_result(vadc, &calib_read_1);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700831 if (rc) {
832 pr_err("qpnp adc read adc failed with %d\n", rc);
833 goto calib_fail;
834 }
835
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700836 qpnp_vadc_625mv_channel_sel(vadc, &ref_channel_sel);
Siddartha Mohanadoss9edb61e2013-04-29 13:52:52 -0700837 conv.amux_channel = ref_channel_sel;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700838 conv.decimation = DECIMATION_TYPE2;
839 conv.mode_sel = ADC_OP_NORMAL_MODE << QPNP_VADC_OP_MODE_SHIFT;
840 conv.hw_settle_time = ADC_CHANNEL_HW_SETTLE_DELAY_0US;
841 conv.fast_avg_setup = ADC_FAST_AVG_SAMPLE_1;
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700842 rc = qpnp_vadc_configure(vadc, &conv);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700843 if (rc) {
844 pr_err("qpnp adc configure failed with %d\n", rc);
845 goto calib_fail;
846 }
847
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700848 status1 = 0;
Siddartha Mohanadoss73ae69b2013-04-03 17:34:03 -0700849 count = 0;
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700850 while (status1 != QPNP_VADC_STATUS1_EOC) {
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700851 rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_STATUS1, &status1);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700852 if (rc < 0)
853 return rc;
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700854 status1 &= QPNP_VADC_STATUS1_REQ_STS_EOC_MASK;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700855 usleep_range(QPNP_VADC_CONV_TIME_MIN,
856 QPNP_VADC_CONV_TIME_MAX);
Siddartha Mohanadoss73ae69b2013-04-03 17:34:03 -0700857 count++;
858 if (count > QPNP_VADC_ERR_COUNT) {
859 rc = -ENODEV;
860 goto calib_fail;
861 }
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700862 }
863
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700864 rc = qpnp_vadc_read_conversion_result(vadc, &calib_read_2);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700865 if (rc) {
866 pr_err("qpnp adc read adc failed with %d\n", rc);
867 goto calib_fail;
868 }
869
Siddartha Mohanadossb2a42372013-03-26 15:53:41 -0700870 pr_debug("absolute reference raw: 625mV:0x%x 1.25V:0x%x\n",
Dipen Parmar454c4b12013-11-25 14:40:47 +0530871 calib_read_2, calib_read_1);
872
873 if (calib_read_1 == calib_read_2) {
874 pr_err("absolute reference raw: 625mV:0x%x 1.25V:0x%x\n",
875 calib_read_2, calib_read_1);
876 rc = -EINVAL;
877 goto calib_fail;
878 }
Siddartha Mohanadossb2a42372013-03-26 15:53:41 -0700879
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700880 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_ABSOLUTE].dy =
881 (calib_read_1 - calib_read_2);
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700882
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700883 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_ABSOLUTE].dx
884 = QPNP_ADC_625_UV;
885 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_ABSOLUTE].adc_vref =
886 calib_read_1;
887 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_ABSOLUTE].adc_gnd =
888 calib_read_2;
889 /* Ratiometric Calibration */
890 conv.amux_channel = VDD_VADC;
891 conv.decimation = DECIMATION_TYPE2;
892 conv.mode_sel = ADC_OP_NORMAL_MODE << QPNP_VADC_OP_MODE_SHIFT;
893 conv.hw_settle_time = ADC_CHANNEL_HW_SETTLE_DELAY_0US;
894 conv.fast_avg_setup = ADC_FAST_AVG_SAMPLE_1;
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700895 rc = qpnp_vadc_configure(vadc, &conv);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700896 if (rc) {
897 pr_err("qpnp adc configure failed with %d\n", rc);
898 goto calib_fail;
899 }
900
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700901 status1 = 0;
Siddartha Mohanadoss73ae69b2013-04-03 17:34:03 -0700902 count = 0;
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700903 while (status1 != QPNP_VADC_STATUS1_EOC) {
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700904 rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_STATUS1, &status1);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700905 if (rc < 0)
906 return rc;
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700907 status1 &= QPNP_VADC_STATUS1_REQ_STS_EOC_MASK;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700908 usleep_range(QPNP_VADC_CONV_TIME_MIN,
909 QPNP_VADC_CONV_TIME_MAX);
Siddartha Mohanadoss73ae69b2013-04-03 17:34:03 -0700910 count++;
911 if (count > QPNP_VADC_ERR_COUNT) {
912 rc = -ENODEV;
913 goto calib_fail;
914 }
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700915 }
916
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700917 rc = qpnp_vadc_read_conversion_result(vadc, &calib_read_1);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700918 if (rc) {
919 pr_err("qpnp adc read adc failed with %d\n", rc);
920 goto calib_fail;
921 }
922
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700923 conv.amux_channel = GND_REF;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700924 conv.decimation = DECIMATION_TYPE2;
925 conv.mode_sel = ADC_OP_NORMAL_MODE << QPNP_VADC_OP_MODE_SHIFT;
926 conv.hw_settle_time = ADC_CHANNEL_HW_SETTLE_DELAY_0US;
927 conv.fast_avg_setup = ADC_FAST_AVG_SAMPLE_1;
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700928 rc = qpnp_vadc_configure(vadc, &conv);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700929 if (rc) {
930 pr_err("qpnp adc configure failed with %d\n", rc);
931 goto calib_fail;
932 }
933
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700934 status1 = 0;
Siddartha Mohanadoss73ae69b2013-04-03 17:34:03 -0700935 count = 0;
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700936 while (status1 != QPNP_VADC_STATUS1_EOC) {
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700937 rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_STATUS1, &status1);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700938 if (rc < 0)
939 return rc;
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700940 status1 &= QPNP_VADC_STATUS1_REQ_STS_EOC_MASK;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700941 usleep_range(QPNP_VADC_CONV_TIME_MIN,
942 QPNP_VADC_CONV_TIME_MAX);
Siddartha Mohanadoss73ae69b2013-04-03 17:34:03 -0700943 count++;
944 if (count > QPNP_VADC_ERR_COUNT) {
945 rc = -ENODEV;
946 goto calib_fail;
947 }
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700948 }
949
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700950 rc = qpnp_vadc_read_conversion_result(vadc, &calib_read_2);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700951 if (rc) {
952 pr_err("qpnp adc read adc failed with %d\n", rc);
953 goto calib_fail;
954 }
955
Siddartha Mohanadossb2a42372013-03-26 15:53:41 -0700956 pr_debug("ratiometric reference raw: VDD:0x%x GND:0x%x\n",
957 calib_read_1, calib_read_2);
Dipen Parmar454c4b12013-11-25 14:40:47 +0530958
959 if (calib_read_1 == calib_read_2) {
960 pr_err("ratiometric reference raw: VDD:0x%x GND:0x%x\n",
961 calib_read_1, calib_read_2);
962 rc = -EINVAL;
963 goto calib_fail;
964 }
965
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700966 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_RATIOMETRIC].dy =
967 (calib_read_1 - calib_read_2);
968 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_RATIOMETRIC].dx =
969 vadc->adc->adc_prop->adc_vdd_reference;
970 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_RATIOMETRIC].adc_vref =
971 calib_read_1;
972 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_RATIOMETRIC].adc_gnd =
973 calib_read_2;
974
975calib_fail:
976 return rc;
977}
978
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700979int32_t qpnp_get_vadc_gain_and_offset(struct qpnp_vadc_chip *vadc,
980 struct qpnp_vadc_linear_graph *param,
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800981 enum qpnp_adc_calib_type calib_type)
982{
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700983 int rc = 0;
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800984
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700985 rc = qpnp_vadc_is_valid(vadc);
986 if (rc < 0)
987 return rc;
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800988
989 switch (calib_type) {
990 case CALIB_RATIOMETRIC:
991 param->dy =
992 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_RATIOMETRIC].dy;
993 param->dx =
994 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_RATIOMETRIC].dx;
995 param->adc_vref = vadc->adc->adc_prop->adc_vdd_reference;
996 param->adc_gnd =
997 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_RATIOMETRIC].adc_gnd;
998 break;
999 case CALIB_ABSOLUTE:
1000 param->dy =
1001 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_ABSOLUTE].dy;
1002 param->dx =
1003 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_ABSOLUTE].dx;
1004 param->adc_vref = vadc->adc->adc_prop->adc_vdd_reference;
1005 param->adc_gnd =
1006 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_ABSOLUTE].adc_gnd;
1007 break;
1008 default:
1009 return -EINVAL;
1010 }
1011
1012 return 0;
1013}
1014EXPORT_SYMBOL(qpnp_get_vadc_gain_and_offset);
1015
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001016struct qpnp_vadc_chip *qpnp_get_vadc(struct device *dev, const char *name)
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -07001017{
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001018 struct qpnp_vadc_chip *vadc;
1019 struct device_node *node = NULL;
1020 char prop_name[QPNP_MAX_PROP_NAME_LEN];
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -07001021
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001022 snprintf(prop_name, QPNP_MAX_PROP_NAME_LEN, "qcom,%s-vadc", name);
1023
1024 node = of_parse_phandle(dev->of_node, prop_name, 0);
1025 if (node == NULL)
1026 return ERR_PTR(-ENODEV);
1027
1028 list_for_each_entry(vadc, &qpnp_vadc_device_list, list)
1029 if (vadc->adc->spmi->dev.of_node == node)
1030 return vadc;
1031 return ERR_PTR(-EPROBE_DEFER);
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -07001032}
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001033EXPORT_SYMBOL(qpnp_get_vadc);
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -07001034
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001035int32_t qpnp_vadc_conv_seq_request(struct qpnp_vadc_chip *vadc,
1036 enum qpnp_vadc_trigger trigger_channel,
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001037 enum qpnp_vadc_channels channel,
1038 struct qpnp_vadc_result *result)
1039{
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -07001040 int rc = 0, scale_type, amux_prescaling, dt_index = 0;
Siddartha Mohanadoss462088b2013-07-27 19:58:09 -07001041 uint32_t ref_channel, count = 0;
1042 u8 status1 = 0;
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -07001043
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001044 if (qpnp_vadc_is_valid(vadc))
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -07001045 return -EPROBE_DEFER;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001046
Siddartha Mohanadoss64bc4f52012-12-19 20:26:32 -08001047 mutex_lock(&vadc->adc->adc_lock);
1048
Siddartha Mohanadoss462088b2013-07-27 19:58:09 -07001049 if (vadc->vadc_poll_eoc) {
1050 pr_debug("requesting vadc eoc stay awake\n");
1051 pm_stay_awake(vadc->dev);
1052 }
1053
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001054 if (!vadc->vadc_init_calib) {
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001055 rc = qpnp_vadc_version_check(vadc);
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -07001056 if (rc)
Siddartha Mohanadoss64bc4f52012-12-19 20:26:32 -08001057 goto fail_unlock;
1058
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001059 rc = qpnp_vadc_calib_device(vadc);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001060 if (rc) {
1061 pr_err("Calibration failed\n");
Siddartha Mohanadoss64bc4f52012-12-19 20:26:32 -08001062 goto fail_unlock;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001063 } else
1064 vadc->vadc_init_calib = true;
1065 }
1066
Siddartha Mohanadoss9edb61e2013-04-29 13:52:52 -07001067 if (channel == REF_625MV) {
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001068 qpnp_vadc_625mv_channel_sel(vadc, &ref_channel);
Siddartha Mohanadoss9edb61e2013-04-29 13:52:52 -07001069 channel = ref_channel;
1070 }
1071
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001072 vadc->adc->amux_prop->amux_channel = channel;
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -07001073
Siddartha Mohanadoss7126ce82012-12-11 14:33:11 -08001074 while ((vadc->adc->adc_channels[dt_index].channel_num
1075 != channel) && (dt_index < vadc->max_channels_available))
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -07001076 dt_index++;
1077
Siddartha Mohanadoss7126ce82012-12-11 14:33:11 -08001078 if (dt_index >= vadc->max_channels_available) {
Siddartha Mohanadoss1a0d2032012-11-01 11:22:29 -07001079 pr_err("not a valid VADC channel\n");
1080 rc = -EINVAL;
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -07001081 goto fail_unlock;
Siddartha Mohanadoss1a0d2032012-11-01 11:22:29 -07001082 }
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -07001083
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001084 vadc->adc->amux_prop->decimation =
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -07001085 vadc->adc->adc_channels[dt_index].adc_decimation;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001086 vadc->adc->amux_prop->hw_settle_time =
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -07001087 vadc->adc->adc_channels[dt_index].hw_settle_time;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001088 vadc->adc->amux_prop->fast_avg_setup =
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -07001089 vadc->adc->adc_channels[dt_index].fast_avg_setup;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001090
1091 if (trigger_channel < ADC_SEQ_NONE)
1092 vadc->adc->amux_prop->mode_sel = (ADC_OP_CONVERSION_SEQUENCER
1093 << QPNP_VADC_OP_MODE_SHIFT);
1094 else if (trigger_channel == ADC_SEQ_NONE)
1095 vadc->adc->amux_prop->mode_sel = (ADC_OP_NORMAL_MODE
1096 << QPNP_VADC_OP_MODE_SHIFT);
1097 else {
1098 pr_err("Invalid trigger channel:%d\n", trigger_channel);
Siddartha Mohanadossae1da732012-08-08 16:39:02 -07001099 goto fail_unlock;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001100 }
1101
1102 vadc->adc->amux_prop->trigger_channel = trigger_channel;
1103
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001104 rc = qpnp_vadc_configure(vadc, vadc->adc->amux_prop);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001105 if (rc) {
Siddartha Mohanadossae1da732012-08-08 16:39:02 -07001106 pr_err("qpnp vadc configure failed with %d\n", rc);
1107 goto fail_unlock;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001108 }
1109
Siddartha Mohanadoss462088b2013-07-27 19:58:09 -07001110 if (vadc->vadc_poll_eoc) {
1111 while (status1 != QPNP_VADC_STATUS1_EOC) {
1112 rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_STATUS1,
1113 &status1);
Siddartha Mohanadoss9cb2c652012-12-14 19:18:18 -08001114 if (rc < 0)
Siddartha Mohanadoss462088b2013-07-27 19:58:09 -07001115 goto fail_unlock;
1116 status1 &= QPNP_VADC_STATUS1_REQ_STS_EOC_MASK;
1117 usleep_range(QPNP_VADC_CONV_TIME_MIN,
1118 QPNP_VADC_CONV_TIME_MAX);
1119 count++;
1120 if (count > QPNP_VADC_ERR_COUNT) {
1121 pr_err("retry error exceeded\n");
1122 rc = qpnp_vadc_status_debug(vadc);
1123 if (rc < 0)
1124 pr_err("VADC disable failed\n");
1125 rc = -EINVAL;
1126 goto fail_unlock;
1127 }
1128 }
1129 } else {
1130 rc = wait_for_completion_timeout(
1131 &vadc->adc->adc_rslt_completion,
1132 QPNP_ADC_COMPLETION_TIMEOUT);
1133 if (!rc) {
1134 rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_STATUS1,
1135 &status1);
1136 if (rc < 0)
1137 goto fail_unlock;
1138 status1 &= QPNP_VADC_STATUS1_REQ_STS_EOC_MASK;
1139 if (status1 == QPNP_VADC_STATUS1_EOC)
1140 pr_debug("End of conversion status set\n");
1141 else {
1142 rc = qpnp_vadc_status_debug(vadc);
1143 if (rc < 0)
1144 pr_err("VADC disable failed\n");
1145 rc = -EINVAL;
1146 goto fail_unlock;
1147 }
Siddartha Mohanadoss1a0d2032012-11-01 11:22:29 -07001148 }
1149 }
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001150
1151 if (trigger_channel < ADC_SEQ_NONE) {
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001152 rc = qpnp_vadc_read_status(vadc,
1153 vadc->adc->amux_prop->mode_sel);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001154 if (rc)
Siddartha Mohanadossae1da732012-08-08 16:39:02 -07001155 pr_debug("Conversion sequence timed out - %d\n", rc);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001156 }
1157
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001158 rc = qpnp_vadc_read_conversion_result(vadc, &result->adc_code);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001159 if (rc) {
Siddartha Mohanadossae1da732012-08-08 16:39:02 -07001160 pr_err("qpnp vadc read adc code failed with %d\n", rc);
1161 goto fail_unlock;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001162 }
1163
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -07001164 amux_prescaling =
1165 vadc->adc->adc_channels[dt_index].chan_path_prescaling;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001166
Siddartha Mohanadoss630def02013-06-27 14:53:38 -07001167 if (amux_prescaling >= PATH_SCALING_NONE) {
1168 rc = -EINVAL;
1169 goto fail_unlock;
1170 }
1171
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001172 vadc->adc->amux_prop->chan_prop->offset_gain_numerator =
1173 qpnp_vadc_amux_scaling_ratio[amux_prescaling].num;
1174 vadc->adc->amux_prop->chan_prop->offset_gain_denominator =
1175 qpnp_vadc_amux_scaling_ratio[amux_prescaling].den;
1176
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -07001177 scale_type = vadc->adc->adc_channels[dt_index].adc_scale_fn;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001178 if (scale_type >= SCALE_NONE) {
1179 rc = -EBADF;
Siddartha Mohanadossae1da732012-08-08 16:39:02 -07001180 goto fail_unlock;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001181 }
1182
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001183 vadc_scale_fn[scale_type].chan(vadc, result->adc_code,
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001184 vadc->adc->adc_prop, vadc->adc->amux_prop->chan_prop, result);
1185
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001186fail_unlock:
Siddartha Mohanadoss462088b2013-07-27 19:58:09 -07001187 if (vadc->vadc_poll_eoc) {
1188 pr_debug("requesting vadc eoc stay awake\n");
1189 pm_relax(vadc->dev);
1190 }
1191
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001192 mutex_unlock(&vadc->adc->adc_lock);
1193
1194 return rc;
1195}
1196EXPORT_SYMBOL(qpnp_vadc_conv_seq_request);
1197
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001198int32_t qpnp_vadc_read(struct qpnp_vadc_chip *vadc,
1199 enum qpnp_vadc_channels channel,
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001200 struct qpnp_vadc_result *result)
1201{
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -07001202 struct qpnp_vadc_result die_temp_result;
1203 int rc = 0;
1204
1205 if (channel == VBAT_SNS) {
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001206 rc = qpnp_vadc_conv_seq_request(vadc, ADC_SEQ_NONE,
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -07001207 channel, result);
1208 if (rc < 0) {
1209 pr_err("Error reading vbatt\n");
1210 return rc;
1211 }
1212
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001213 rc = qpnp_vadc_conv_seq_request(vadc, ADC_SEQ_NONE,
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -07001214 DIE_TEMP, &die_temp_result);
1215 if (rc < 0) {
1216 pr_err("Error reading die_temp\n");
1217 return rc;
1218 }
1219
Siddartha Mohanadossf3db6142013-08-09 16:54:47 -07001220 rc = qpnp_vbat_sns_comp(&result->physical, vadc,
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -07001221 die_temp_result.physical);
1222 if (rc < 0)
1223 pr_err("Error with vbat compensation\n");
1224
1225 return 0;
1226 } else
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001227 return qpnp_vadc_conv_seq_request(vadc, ADC_SEQ_NONE,
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001228 channel, result);
1229}
Siddartha Mohanadoss271d00f2013-03-26 18:24:14 -07001230EXPORT_SYMBOL(qpnp_vadc_read);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001231
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001232static void qpnp_vadc_lock(struct qpnp_vadc_chip *vadc)
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001233{
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001234 mutex_lock(&vadc->adc->adc_lock);
1235}
1236
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001237static void qpnp_vadc_unlock(struct qpnp_vadc_chip *vadc)
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001238{
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001239 mutex_unlock(&vadc->adc->adc_lock);
1240}
1241
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001242int32_t qpnp_vadc_iadc_sync_request(struct qpnp_vadc_chip *vadc,
1243 enum qpnp_vadc_channels channel)
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001244{
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001245 int rc = 0, dt_index = 0;
1246
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001247 if (qpnp_vadc_is_valid(vadc))
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001248 return -EPROBE_DEFER;
1249
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001250 qpnp_vadc_lock(vadc);
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001251
1252 if (!vadc->vadc_init_calib) {
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001253 rc = qpnp_vadc_version_check(vadc);
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001254 if (rc)
1255 goto fail;
1256
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001257 rc = qpnp_vadc_calib_device(vadc);
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001258 if (rc) {
1259 pr_err("Calibration failed\n");
1260 goto fail;
1261 } else
1262 vadc->vadc_init_calib = true;
1263 }
1264
1265 vadc->adc->amux_prop->amux_channel = channel;
1266
1267 while ((vadc->adc->adc_channels[dt_index].channel_num
1268 != channel) && (dt_index < vadc->max_channels_available))
1269 dt_index++;
1270
1271 if (dt_index >= vadc->max_channels_available) {
1272 pr_err("not a valid VADC channel\n");
1273 rc = -EINVAL;
1274 goto fail;
1275 }
1276
1277 vadc->adc->amux_prop->decimation =
1278 vadc->adc->adc_channels[dt_index].adc_decimation;
1279 vadc->adc->amux_prop->hw_settle_time =
1280 vadc->adc->adc_channels[dt_index].hw_settle_time;
1281 vadc->adc->amux_prop->fast_avg_setup =
1282 vadc->adc->adc_channels[dt_index].fast_avg_setup;
1283 vadc->adc->amux_prop->mode_sel = (ADC_OP_NORMAL_MODE
1284 << QPNP_VADC_OP_MODE_SHIFT);
1285 vadc->vadc_iadc_sync_lock = true;
1286
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001287 rc = qpnp_vadc_configure(vadc, vadc->adc->amux_prop);
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001288 if (rc) {
1289 pr_err("qpnp vadc configure failed with %d\n", rc);
1290 goto fail;
1291 }
1292
1293 return rc;
1294fail:
1295 vadc->vadc_iadc_sync_lock = false;
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001296 qpnp_vadc_unlock(vadc);
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001297 return rc;
1298}
1299EXPORT_SYMBOL(qpnp_vadc_iadc_sync_request);
1300
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001301int32_t qpnp_vadc_iadc_sync_complete_request(struct qpnp_vadc_chip *vadc,
1302 enum qpnp_vadc_channels channel,
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001303 struct qpnp_vadc_result *result)
1304{
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001305 int rc = 0, scale_type, amux_prescaling, dt_index = 0;
1306
1307 vadc->adc->amux_prop->amux_channel = channel;
1308
1309 while ((vadc->adc->adc_channels[dt_index].channel_num
1310 != channel) && (dt_index < vadc->max_channels_available))
1311 dt_index++;
1312
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001313 rc = qpnp_vadc_read_conversion_result(vadc, &result->adc_code);
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001314 if (rc) {
1315 pr_err("qpnp vadc read adc code failed with %d\n", rc);
1316 goto fail;
1317 }
1318
1319 amux_prescaling =
1320 vadc->adc->adc_channels[dt_index].chan_path_prescaling;
1321
Siddartha Mohanadoss630def02013-06-27 14:53:38 -07001322 if (amux_prescaling >= PATH_SCALING_NONE) {
1323 rc = -EINVAL;
1324 goto fail;
1325 }
1326
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001327 vadc->adc->amux_prop->chan_prop->offset_gain_numerator =
1328 qpnp_vadc_amux_scaling_ratio[amux_prescaling].num;
1329 vadc->adc->amux_prop->chan_prop->offset_gain_denominator =
1330 qpnp_vadc_amux_scaling_ratio[amux_prescaling].den;
1331
1332 scale_type = vadc->adc->adc_channels[dt_index].adc_scale_fn;
1333 if (scale_type >= SCALE_NONE) {
1334 rc = -EBADF;
1335 goto fail;
1336 }
1337
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001338 vadc_scale_fn[scale_type].chan(vadc, result->adc_code,
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001339 vadc->adc->adc_prop, vadc->adc->amux_prop->chan_prop, result);
1340
1341fail:
1342 vadc->vadc_iadc_sync_lock = false;
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001343 qpnp_vadc_unlock(vadc);
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001344 return rc;
1345}
1346EXPORT_SYMBOL(qpnp_vadc_iadc_sync_complete_request);
1347
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001348static ssize_t qpnp_adc_show(struct device *dev,
1349 struct device_attribute *devattr, char *buf)
1350{
1351 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001352 struct qpnp_vadc_chip *vadc = dev_get_drvdata(dev);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001353 struct qpnp_vadc_result result;
1354 int rc = -1;
1355
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001356 rc = qpnp_vadc_read(vadc, attr->index, &result);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001357
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -07001358 if (rc) {
1359 pr_err("VADC read error with %d\n", rc);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001360 return 0;
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -07001361 }
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001362
1363 return snprintf(buf, QPNP_ADC_HWMON_NAME_LENGTH,
1364 "Result:%lld Raw:%d\n", result.physical, result.adc_code);
1365}
1366
1367static struct sensor_device_attribute qpnp_adc_attr =
1368 SENSOR_ATTR(NULL, S_IRUGO, qpnp_adc_show, NULL, 0);
1369
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001370static int32_t qpnp_vadc_init_hwmon(struct qpnp_vadc_chip *vadc,
1371 struct spmi_device *spmi)
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001372{
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001373 struct device_node *child;
1374 struct device_node *node = spmi->dev.of_node;
1375 int rc = 0, i = 0, channel;
1376
1377 for_each_child_of_node(node, child) {
1378 channel = vadc->adc->adc_channels[i].channel_num;
1379 qpnp_adc_attr.index = vadc->adc->adc_channels[i].channel_num;
1380 qpnp_adc_attr.dev_attr.attr.name =
1381 vadc->adc->adc_channels[i].name;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001382 memcpy(&vadc->sens_attr[i], &qpnp_adc_attr,
1383 sizeof(qpnp_adc_attr));
Stephen Boydd7337962012-10-30 11:10:46 -07001384 sysfs_attr_init(&vadc->sens_attr[i].dev_attr.attr);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001385 rc = device_create_file(&spmi->dev,
1386 &vadc->sens_attr[i].dev_attr);
1387 if (rc) {
1388 dev_err(&spmi->dev,
1389 "device_create_file failed for dev %s\n",
1390 vadc->adc->adc_channels[i].name);
1391 goto hwmon_err_sens;
1392 }
1393 i++;
1394 }
1395
1396 return 0;
1397hwmon_err_sens:
Siddartha Mohanadossae1da732012-08-08 16:39:02 -07001398 pr_err("Init HWMON failed for qpnp_adc with %d\n", rc);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001399 return rc;
1400}
1401
1402static int __devinit qpnp_vadc_probe(struct spmi_device *spmi)
1403{
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001404 struct qpnp_vadc_chip *vadc;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001405 struct qpnp_adc_drv *adc_qpnp;
1406 struct device_node *node = spmi->dev.of_node;
1407 struct device_node *child;
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001408 int rc, count_adc_channel_list = 0, i = 0;
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -07001409 u8 fab_id = 0;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001410
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001411 for_each_child_of_node(node, child)
1412 count_adc_channel_list++;
1413
1414 if (!count_adc_channel_list) {
1415 pr_err("No channel listing\n");
1416 return -EINVAL;
1417 }
1418
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001419 vadc = devm_kzalloc(&spmi->dev, sizeof(struct qpnp_vadc_chip) +
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001420 (sizeof(struct sensor_device_attribute) *
1421 count_adc_channel_list), GFP_KERNEL);
1422 if (!vadc) {
1423 dev_err(&spmi->dev, "Unable to allocate memory\n");
1424 return -ENOMEM;
1425 }
1426
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001427 vadc->dev = &(spmi->dev);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001428 adc_qpnp = devm_kzalloc(&spmi->dev, sizeof(struct qpnp_adc_drv),
1429 GFP_KERNEL);
1430 if (!adc_qpnp) {
1431 dev_err(&spmi->dev, "Unable to allocate memory\n");
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001432 return -ENOMEM;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001433 }
1434
1435 vadc->adc = adc_qpnp;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001436 rc = qpnp_adc_get_devicetree_data(spmi, vadc->adc);
1437 if (rc) {
1438 dev_err(&spmi->dev, "failed to read device tree\n");
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001439 return rc;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001440 }
Stephen Boydbeab4502013-04-25 10:18:17 -07001441 mutex_init(&vadc->adc->adc_lock);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001442
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001443 rc = qpnp_vadc_init_hwmon(vadc, spmi);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001444 if (rc) {
1445 dev_err(&spmi->dev, "failed to initialize qpnp hwmon adc\n");
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001446 return rc;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001447 }
1448 vadc->vadc_hwmon = hwmon_device_register(&vadc->adc->spmi->dev);
1449 vadc->vadc_init_calib = false;
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -07001450 vadc->max_channels_available = count_adc_channel_list;
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001451 rc = qpnp_vadc_read_reg(vadc, QPNP_INT_TEST_VAL, &fab_id);
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -07001452 if (rc < 0) {
1453 pr_err("qpnp adc comp id failed with %d\n", rc);
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001454 goto err_setup;
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -07001455 }
1456 vadc->id = fab_id;
1457
Siddartha Mohanadossf3db6142013-08-09 16:54:47 -07001458 rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_REVISION2,
1459 &vadc->revision_dig_major);
1460 if (rc < 0) {
1461 pr_err("qpnp adc dig_major rev read failed with %d\n", rc);
1462 goto err_setup;
1463 }
1464
1465 rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_REVISION3,
1466 &vadc->revision_ana_minor);
1467 if (rc < 0) {
1468 pr_err("qpnp adc ana_minor rev read failed with %d\n", rc);
1469 goto err_setup;
1470 }
1471
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001472 rc = qpnp_vadc_warm_rst_configure(vadc);
Siddartha Mohanadoss22559462013-05-15 15:30:28 -07001473 if (rc < 0) {
1474 pr_err("Setting perp reset on warm reset failed %d\n", rc);
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001475 goto err_setup;
Siddartha Mohanadoss22559462013-05-15 15:30:28 -07001476 }
1477
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001478 INIT_WORK(&vadc->trigger_completion_work, qpnp_vadc_work);
Siddartha Mohanadoss73fb1512013-08-08 22:38:13 -07001479
1480 vadc->vadc_poll_eoc = of_property_read_bool(node,
1481 "qcom,vadc-poll-eoc");
1482 if (!vadc->vadc_poll_eoc) {
1483 rc = devm_request_irq(&spmi->dev, vadc->adc->adc_irq_eoc,
1484 qpnp_vadc_isr, IRQF_TRIGGER_RISING,
1485 "qpnp_vadc_interrupt", vadc);
1486 if (rc) {
1487 dev_err(&spmi->dev,
1488 "failed to request adc irq with error %d\n", rc);
1489 goto err_setup;
1490 } else {
1491 enable_irq_wake(vadc->adc->adc_irq_eoc);
1492 }
1493 } else
Siddartha Mohanadoss462088b2013-07-27 19:58:09 -07001494 device_init_wakeup(vadc->dev, 1);
1495
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001496 vadc->vadc_iadc_sync_lock = false;
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001497 dev_set_drvdata(&spmi->dev, vadc);
1498 list_add(&vadc->list, &qpnp_vadc_device_list);
1499
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001500 return 0;
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001501
1502err_setup:
1503 for_each_child_of_node(node, child) {
1504 device_remove_file(&spmi->dev,
1505 &vadc->sens_attr[i].dev_attr);
1506 i++;
1507 }
1508 hwmon_device_unregister(vadc->vadc_hwmon);
1509
Siddartha Mohanadossb60f6462012-11-20 18:06:51 -08001510 return rc;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001511}
1512
1513static int __devexit qpnp_vadc_remove(struct spmi_device *spmi)
1514{
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001515 struct qpnp_vadc_chip *vadc = dev_get_drvdata(&spmi->dev);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001516 struct device_node *node = spmi->dev.of_node;
1517 struct device_node *child;
1518 int i = 0;
1519
1520 for_each_child_of_node(node, child) {
1521 device_remove_file(&spmi->dev,
1522 &vadc->sens_attr[i].dev_attr);
1523 i++;
1524 }
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001525 hwmon_device_unregister(vadc->vadc_hwmon);
1526 list_del(&vadc->list);
Siddartha Mohanadoss462088b2013-07-27 19:58:09 -07001527 if (vadc->vadc_poll_eoc)
1528 pm_relax(vadc->dev);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001529 dev_set_drvdata(&spmi->dev, NULL);
1530
1531 return 0;
1532}
1533
1534static const struct of_device_id qpnp_vadc_match_table[] = {
1535 { .compatible = "qcom,qpnp-vadc",
1536 },
1537 {}
1538};
1539
1540static struct spmi_driver qpnp_vadc_driver = {
1541 .driver = {
1542 .name = "qcom,qpnp-vadc",
1543 .of_match_table = qpnp_vadc_match_table,
1544 },
1545 .probe = qpnp_vadc_probe,
1546 .remove = qpnp_vadc_remove,
1547};
1548
1549static int __init qpnp_vadc_init(void)
1550{
1551 return spmi_driver_register(&qpnp_vadc_driver);
1552}
1553module_init(qpnp_vadc_init);
1554
1555static void __exit qpnp_vadc_exit(void)
1556{
1557 spmi_driver_unregister(&qpnp_vadc_driver);
1558}
1559module_exit(qpnp_vadc_exit);
1560
1561MODULE_DESCRIPTION("QPNP PMIC Voltage ADC driver");
1562MODULE_LICENSE("GPL v2");