blob: d462fb393a7b6b6fbf574c924350c2979a588f9d [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
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
515
516#define QPNP_VADC_REV_ID_8941_3_1 1
517#define QPNP_VADC_REV_ID_8026_1_0 2
518#define QPNP_VADC_REV_ID_8026_2_0 3
519
520static void qpnp_temp_comp_version_check(struct qpnp_vadc_chip *vadc,
521 int32_t *version)
522{
523 if (vadc->revision_dig_major == 3 &&
524 vadc->revision_ana_minor == 2)
525 *version = QPNP_VADC_REV_ID_8941_3_1;
526 else if (vadc->revision_dig_major == 1 &&
527 vadc->revision_ana_minor == 2)
528 *version = QPNP_VADC_REV_ID_8026_1_0;
529 else if (vadc->revision_dig_major == 2 &&
530 vadc->revision_ana_minor == 2)
531 *version = QPNP_VADC_REV_ID_8026_2_0;
532 else
533 *version = -EINVAL;
534
535 return;
536}
537
538static int32_t qpnp_ocv_comp(int64_t *result,
539 struct qpnp_vadc_chip *vadc, int64_t die_temp)
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -0700540{
541 int64_t temp_var = 0;
Xiaozhe Shi62ad5e12013-05-13 12:37:41 -0700542 int64_t old = *result;
Siddartha Mohanadossf3db6142013-08-09 16:54:47 -0700543 int32_t version;
544
545 qpnp_temp_comp_version_check(vadc, &version);
546 if (version == -EINVAL)
547 return 0;
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -0700548
549 if (die_temp < 25000)
550 return 0;
551
Siddartha Mohanadossf3db6142013-08-09 16:54:47 -0700552 if (die_temp > 60000)
553 die_temp = 60000;
554
555 switch (version) {
556 case QPNP_VADC_REV_ID_8941_3_1:
557 switch (vadc->id) {
558 case COMP_ID_TSMC:
559 temp_var = (((die_temp *
560 (-QPNP_VBAT_COEFF_4))
561 + QPNP_VBAT_COEFF_5));
562 break;
563 default:
564 case COMP_ID_GF:
565 temp_var = (((die_temp *
566 (-QPNP_VBAT_COEFF_1))
567 + QPNP_VBAT_COEFF_2));
568 break;
569 }
570 break;
571 case QPNP_VADC_REV_ID_8026_1_0:
572 switch (vadc->id) {
573 case COMP_ID_TSMC:
574 temp_var = (((die_temp *
575 (-QPNP_VBAT_COEFF_10))
576 - QPNP_VBAT_COEFF_14));
577 break;
578 default:
579 case COMP_ID_GF:
580 temp_var = (((die_temp *
581 (-QPNP_VBAT_COEFF_8))
582 + QPNP_VBAT_COEFF_12));
583 break;
584 }
585 break;
586 case QPNP_VADC_REV_ID_8026_2_0:
587 switch (vadc->id) {
588 case COMP_ID_TSMC:
589 temp_var = ((die_temp - 2500) *
590 (-QPNP_VBAT_COEFF_10));
591 break;
592 default:
593 case COMP_ID_GF:
594 temp_var = ((die_temp - 2500) *
595 (-QPNP_VBAT_COEFF_8));
596 break;
597 }
598 break;
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -0700599 default:
Siddartha Mohanadossf3db6142013-08-09 16:54:47 -0700600 temp_var = 0;
601 break;
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -0700602 }
603
Siddartha Mohanadossf3db6142013-08-09 16:54:47 -0700604 temp_var = div64_s64(temp_var, QPNP_VBAT_COEFF_3);
605
606 temp_var = 1000000 + temp_var;
607
608 *result = *result * temp_var;
609
610 *result = div64_s64(*result, 1000000);
611 pr_debug("%lld compensated into %lld\n", old, *result);
612
613 return 0;
614}
615
616static int32_t qpnp_vbat_sns_comp(int64_t *result,
617 struct qpnp_vadc_chip *vadc, int64_t die_temp)
618{
619 int64_t temp_var = 0;
620 int64_t old = *result;
621 int32_t version;
622
623 qpnp_temp_comp_version_check(vadc, &version);
624 if (version == -EINVAL)
625 return 0;
626
627 if (die_temp < 25000)
628 return 0;
629
630 /* min(die_temp_c, 60_degC) */
631 if (die_temp > 60000)
632 die_temp = 60000;
633
634 switch (version) {
635 case QPNP_VADC_REV_ID_8941_3_1:
636 switch (vadc->id) {
637 case COMP_ID_TSMC:
638 temp_var = (die_temp *
639 (-QPNP_VBAT_COEFF_1));
640 break;
641 default:
642 case COMP_ID_GF:
643 temp_var = (((die_temp *
644 (-QPNP_VBAT_COEFF_6))
645 + QPNP_VBAT_COEFF_7));
646 break;
647 }
648 break;
649 case QPNP_VADC_REV_ID_8026_1_0:
650 switch (vadc->id) {
651 case COMP_ID_TSMC:
652 temp_var = (((die_temp *
653 (-QPNP_VBAT_COEFF_11))
654 + QPNP_VBAT_COEFF_15));
655 break;
656 default:
657 case COMP_ID_GF:
658 temp_var = (((die_temp *
659 (-QPNP_VBAT_COEFF_9))
660 + QPNP_VBAT_COEFF_13));
661 break;
662 }
663 break;
664 case QPNP_VADC_REV_ID_8026_2_0:
665 switch (vadc->id) {
666 case COMP_ID_TSMC:
667 temp_var = ((die_temp - 2500) *
668 (-QPNP_VBAT_COEFF_11));
669 break;
670 default:
671 case COMP_ID_GF:
672 temp_var = ((die_temp - 2500) *
673 (-QPNP_VBAT_COEFF_9));
674 break;
675 }
676 break;
677 default:
678 temp_var = 0;
679 break;
680 }
681
682 temp_var = div64_s64(temp_var, QPNP_VBAT_COEFF_3);
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -0700683
684 temp_var = 1000000 + temp_var;
685
686 *result = *result * temp_var;
687
688 *result = div64_s64(*result, 1000000);
Xiaozhe Shi62ad5e12013-05-13 12:37:41 -0700689 pr_debug("%lld compensated into %lld\n", old, *result);
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -0700690
691 return 0;
692}
693
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700694int32_t qpnp_vbat_sns_comp_result(struct qpnp_vadc_chip *vadc,
695 int64_t *result)
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -0700696{
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -0700697 struct qpnp_vadc_result die_temp_result;
698 int rc = 0;
699
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700700 rc = qpnp_vadc_is_valid(vadc);
701 if (rc < 0)
702 return rc;
703
704 rc = qpnp_vadc_conv_seq_request(vadc, ADC_SEQ_NONE,
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -0700705 DIE_TEMP, &die_temp_result);
706 if (rc < 0) {
707 pr_err("Error reading die_temp\n");
708 return rc;
709 }
710
Siddartha Mohanadossf3db6142013-08-09 16:54:47 -0700711 rc = qpnp_ocv_comp(result, vadc, die_temp_result.physical);
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -0700712 if (rc < 0)
713 pr_err("Error with vbat compensation\n");
714
715 return rc;
716}
717EXPORT_SYMBOL(qpnp_vbat_sns_comp_result);
718
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700719static void qpnp_vadc_625mv_channel_sel(struct qpnp_vadc_chip *vadc,
720 uint32_t *ref_channel_sel)
Siddartha Mohanadoss9edb61e2013-04-29 13:52:52 -0700721{
Siddartha Mohanadoss9edb61e2013-04-29 13:52:52 -0700722 uint32_t dt_index = 0;
723
724 /* Check if the buffered 625mV channel exists */
725 while ((vadc->adc->adc_channels[dt_index].channel_num
726 != SPARE1) && (dt_index < vadc->max_channels_available))
727 dt_index++;
728
729 if (dt_index >= vadc->max_channels_available) {
730 pr_debug("Use default 625mV ref channel\n");
731 *ref_channel_sel = REF_625MV;
732 } else {
733 pr_debug("Use buffered 625mV ref channel\n");
734 *ref_channel_sel = SPARE1;
735 }
736}
737
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700738static int32_t qpnp_vadc_calib_device(struct qpnp_vadc_chip *vadc)
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700739{
Siddartha Mohanadossc4a6af12012-07-13 18:50:12 -0700740 struct qpnp_adc_amux_properties conv;
Siddartha Mohanadoss73ae69b2013-04-03 17:34:03 -0700741 int rc, calib_read_1, calib_read_2, count = 0;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700742 u8 status1 = 0;
Siddartha Mohanadoss9edb61e2013-04-29 13:52:52 -0700743 uint32_t ref_channel_sel = 0;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700744
745 conv.amux_channel = REF_125V;
746 conv.decimation = DECIMATION_TYPE2;
747 conv.mode_sel = ADC_OP_NORMAL_MODE << QPNP_VADC_OP_MODE_SHIFT;
748 conv.hw_settle_time = ADC_CHANNEL_HW_SETTLE_DELAY_0US;
749 conv.fast_avg_setup = ADC_FAST_AVG_SAMPLE_1;
750
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700751 rc = qpnp_vadc_configure(vadc, &conv);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700752 if (rc) {
753 pr_err("qpnp_vadc configure failed with %d\n", rc);
754 goto calib_fail;
755 }
756
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700757 while (status1 != QPNP_VADC_STATUS1_EOC) {
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700758 rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_STATUS1, &status1);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700759 if (rc < 0)
760 return rc;
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700761 status1 &= QPNP_VADC_STATUS1_REQ_STS_EOC_MASK;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700762 usleep_range(QPNP_VADC_CONV_TIME_MIN,
763 QPNP_VADC_CONV_TIME_MAX);
Siddartha Mohanadoss73ae69b2013-04-03 17:34:03 -0700764 count++;
765 if (count > QPNP_VADC_ERR_COUNT) {
766 rc = -ENODEV;
767 goto calib_fail;
768 }
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700769 }
770
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700771 rc = qpnp_vadc_read_conversion_result(vadc, &calib_read_1);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700772 if (rc) {
773 pr_err("qpnp adc read adc failed with %d\n", rc);
774 goto calib_fail;
775 }
776
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700777 qpnp_vadc_625mv_channel_sel(vadc, &ref_channel_sel);
Siddartha Mohanadoss9edb61e2013-04-29 13:52:52 -0700778 conv.amux_channel = ref_channel_sel;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700779 conv.decimation = DECIMATION_TYPE2;
780 conv.mode_sel = ADC_OP_NORMAL_MODE << QPNP_VADC_OP_MODE_SHIFT;
781 conv.hw_settle_time = ADC_CHANNEL_HW_SETTLE_DELAY_0US;
782 conv.fast_avg_setup = ADC_FAST_AVG_SAMPLE_1;
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700783 rc = qpnp_vadc_configure(vadc, &conv);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700784 if (rc) {
785 pr_err("qpnp adc configure failed with %d\n", rc);
786 goto calib_fail;
787 }
788
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700789 status1 = 0;
Siddartha Mohanadoss73ae69b2013-04-03 17:34:03 -0700790 count = 0;
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700791 while (status1 != QPNP_VADC_STATUS1_EOC) {
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700792 rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_STATUS1, &status1);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700793 if (rc < 0)
794 return rc;
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700795 status1 &= QPNP_VADC_STATUS1_REQ_STS_EOC_MASK;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700796 usleep_range(QPNP_VADC_CONV_TIME_MIN,
797 QPNP_VADC_CONV_TIME_MAX);
Siddartha Mohanadoss73ae69b2013-04-03 17:34:03 -0700798 count++;
799 if (count > QPNP_VADC_ERR_COUNT) {
800 rc = -ENODEV;
801 goto calib_fail;
802 }
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700803 }
804
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700805 rc = qpnp_vadc_read_conversion_result(vadc, &calib_read_2);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700806 if (rc) {
807 pr_err("qpnp adc read adc failed with %d\n", rc);
808 goto calib_fail;
809 }
810
Siddartha Mohanadossb2a42372013-03-26 15:53:41 -0700811 pr_debug("absolute reference raw: 625mV:0x%x 1.25V:0x%x\n",
Dipen Parmar454c4b12013-11-25 14:40:47 +0530812 calib_read_2, calib_read_1);
813
814 if (calib_read_1 == calib_read_2) {
815 pr_err("absolute reference raw: 625mV:0x%x 1.25V:0x%x\n",
816 calib_read_2, calib_read_1);
817 rc = -EINVAL;
818 goto calib_fail;
819 }
Siddartha Mohanadossb2a42372013-03-26 15:53:41 -0700820
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700821 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_ABSOLUTE].dy =
822 (calib_read_1 - calib_read_2);
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700823
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700824 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_ABSOLUTE].dx
825 = QPNP_ADC_625_UV;
826 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_ABSOLUTE].adc_vref =
827 calib_read_1;
828 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_ABSOLUTE].adc_gnd =
829 calib_read_2;
830 /* Ratiometric Calibration */
831 conv.amux_channel = VDD_VADC;
832 conv.decimation = DECIMATION_TYPE2;
833 conv.mode_sel = ADC_OP_NORMAL_MODE << QPNP_VADC_OP_MODE_SHIFT;
834 conv.hw_settle_time = ADC_CHANNEL_HW_SETTLE_DELAY_0US;
835 conv.fast_avg_setup = ADC_FAST_AVG_SAMPLE_1;
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700836 rc = qpnp_vadc_configure(vadc, &conv);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700837 if (rc) {
838 pr_err("qpnp adc configure failed with %d\n", rc);
839 goto calib_fail;
840 }
841
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700842 status1 = 0;
Siddartha Mohanadoss73ae69b2013-04-03 17:34:03 -0700843 count = 0;
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700844 while (status1 != QPNP_VADC_STATUS1_EOC) {
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700845 rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_STATUS1, &status1);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700846 if (rc < 0)
847 return rc;
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700848 status1 &= QPNP_VADC_STATUS1_REQ_STS_EOC_MASK;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700849 usleep_range(QPNP_VADC_CONV_TIME_MIN,
850 QPNP_VADC_CONV_TIME_MAX);
Siddartha Mohanadoss73ae69b2013-04-03 17:34:03 -0700851 count++;
852 if (count > QPNP_VADC_ERR_COUNT) {
853 rc = -ENODEV;
854 goto calib_fail;
855 }
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700856 }
857
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700858 rc = qpnp_vadc_read_conversion_result(vadc, &calib_read_1);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700859 if (rc) {
860 pr_err("qpnp adc read adc failed with %d\n", rc);
861 goto calib_fail;
862 }
863
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700864 conv.amux_channel = GND_REF;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700865 conv.decimation = DECIMATION_TYPE2;
866 conv.mode_sel = ADC_OP_NORMAL_MODE << QPNP_VADC_OP_MODE_SHIFT;
867 conv.hw_settle_time = ADC_CHANNEL_HW_SETTLE_DELAY_0US;
868 conv.fast_avg_setup = ADC_FAST_AVG_SAMPLE_1;
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700869 rc = qpnp_vadc_configure(vadc, &conv);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700870 if (rc) {
871 pr_err("qpnp adc configure failed with %d\n", rc);
872 goto calib_fail;
873 }
874
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700875 status1 = 0;
Siddartha Mohanadoss73ae69b2013-04-03 17:34:03 -0700876 count = 0;
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700877 while (status1 != QPNP_VADC_STATUS1_EOC) {
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700878 rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_STATUS1, &status1);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700879 if (rc < 0)
880 return rc;
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700881 status1 &= QPNP_VADC_STATUS1_REQ_STS_EOC_MASK;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700882 usleep_range(QPNP_VADC_CONV_TIME_MIN,
883 QPNP_VADC_CONV_TIME_MAX);
Siddartha Mohanadoss73ae69b2013-04-03 17:34:03 -0700884 count++;
885 if (count > QPNP_VADC_ERR_COUNT) {
886 rc = -ENODEV;
887 goto calib_fail;
888 }
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700889 }
890
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700891 rc = qpnp_vadc_read_conversion_result(vadc, &calib_read_2);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700892 if (rc) {
893 pr_err("qpnp adc read adc failed with %d\n", rc);
894 goto calib_fail;
895 }
896
Siddartha Mohanadossb2a42372013-03-26 15:53:41 -0700897 pr_debug("ratiometric reference raw: VDD:0x%x GND:0x%x\n",
898 calib_read_1, calib_read_2);
Dipen Parmar454c4b12013-11-25 14:40:47 +0530899
900 if (calib_read_1 == calib_read_2) {
901 pr_err("ratiometric reference raw: VDD:0x%x GND:0x%x\n",
902 calib_read_1, calib_read_2);
903 rc = -EINVAL;
904 goto calib_fail;
905 }
906
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700907 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_RATIOMETRIC].dy =
908 (calib_read_1 - calib_read_2);
909 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_RATIOMETRIC].dx =
910 vadc->adc->adc_prop->adc_vdd_reference;
911 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_RATIOMETRIC].adc_vref =
912 calib_read_1;
913 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_RATIOMETRIC].adc_gnd =
914 calib_read_2;
915
916calib_fail:
917 return rc;
918}
919
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700920int32_t qpnp_get_vadc_gain_and_offset(struct qpnp_vadc_chip *vadc,
921 struct qpnp_vadc_linear_graph *param,
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800922 enum qpnp_adc_calib_type calib_type)
923{
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700924 int rc = 0;
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800925
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700926 rc = qpnp_vadc_is_valid(vadc);
927 if (rc < 0)
928 return rc;
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800929
930 switch (calib_type) {
931 case CALIB_RATIOMETRIC:
932 param->dy =
933 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_RATIOMETRIC].dy;
934 param->dx =
935 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_RATIOMETRIC].dx;
936 param->adc_vref = vadc->adc->adc_prop->adc_vdd_reference;
937 param->adc_gnd =
938 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_RATIOMETRIC].adc_gnd;
939 break;
940 case CALIB_ABSOLUTE:
941 param->dy =
942 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_ABSOLUTE].dy;
943 param->dx =
944 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_ABSOLUTE].dx;
945 param->adc_vref = vadc->adc->adc_prop->adc_vdd_reference;
946 param->adc_gnd =
947 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_ABSOLUTE].adc_gnd;
948 break;
949 default:
950 return -EINVAL;
951 }
952
953 return 0;
954}
955EXPORT_SYMBOL(qpnp_get_vadc_gain_and_offset);
956
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700957struct qpnp_vadc_chip *qpnp_get_vadc(struct device *dev, const char *name)
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700958{
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700959 struct qpnp_vadc_chip *vadc;
960 struct device_node *node = NULL;
961 char prop_name[QPNP_MAX_PROP_NAME_LEN];
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700962
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700963 snprintf(prop_name, QPNP_MAX_PROP_NAME_LEN, "qcom,%s-vadc", name);
964
965 node = of_parse_phandle(dev->of_node, prop_name, 0);
966 if (node == NULL)
967 return ERR_PTR(-ENODEV);
968
969 list_for_each_entry(vadc, &qpnp_vadc_device_list, list)
970 if (vadc->adc->spmi->dev.of_node == node)
971 return vadc;
972 return ERR_PTR(-EPROBE_DEFER);
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700973}
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700974EXPORT_SYMBOL(qpnp_get_vadc);
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700975
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700976int32_t qpnp_vadc_conv_seq_request(struct qpnp_vadc_chip *vadc,
977 enum qpnp_vadc_trigger trigger_channel,
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700978 enum qpnp_vadc_channels channel,
979 struct qpnp_vadc_result *result)
980{
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700981 int rc = 0, scale_type, amux_prescaling, dt_index = 0;
Siddartha Mohanadoss462088b2013-07-27 19:58:09 -0700982 uint32_t ref_channel, count = 0;
983 u8 status1 = 0;
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700984
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700985 if (qpnp_vadc_is_valid(vadc))
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700986 return -EPROBE_DEFER;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700987
Siddartha Mohanadoss64bc4f52012-12-19 20:26:32 -0800988 mutex_lock(&vadc->adc->adc_lock);
989
Siddartha Mohanadoss462088b2013-07-27 19:58:09 -0700990 if (vadc->vadc_poll_eoc) {
991 pr_debug("requesting vadc eoc stay awake\n");
992 pm_stay_awake(vadc->dev);
993 }
994
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700995 if (!vadc->vadc_init_calib) {
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700996 rc = qpnp_vadc_version_check(vadc);
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700997 if (rc)
Siddartha Mohanadoss64bc4f52012-12-19 20:26:32 -0800998 goto fail_unlock;
999
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001000 rc = qpnp_vadc_calib_device(vadc);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001001 if (rc) {
1002 pr_err("Calibration failed\n");
Siddartha Mohanadoss64bc4f52012-12-19 20:26:32 -08001003 goto fail_unlock;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001004 } else
1005 vadc->vadc_init_calib = true;
1006 }
1007
Siddartha Mohanadoss9edb61e2013-04-29 13:52:52 -07001008 if (channel == REF_625MV) {
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001009 qpnp_vadc_625mv_channel_sel(vadc, &ref_channel);
Siddartha Mohanadoss9edb61e2013-04-29 13:52:52 -07001010 channel = ref_channel;
1011 }
1012
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001013 vadc->adc->amux_prop->amux_channel = channel;
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -07001014
Siddartha Mohanadoss7126ce82012-12-11 14:33:11 -08001015 while ((vadc->adc->adc_channels[dt_index].channel_num
1016 != channel) && (dt_index < vadc->max_channels_available))
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -07001017 dt_index++;
1018
Siddartha Mohanadoss7126ce82012-12-11 14:33:11 -08001019 if (dt_index >= vadc->max_channels_available) {
Siddartha Mohanadoss1a0d2032012-11-01 11:22:29 -07001020 pr_err("not a valid VADC channel\n");
1021 rc = -EINVAL;
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -07001022 goto fail_unlock;
Siddartha Mohanadoss1a0d2032012-11-01 11:22:29 -07001023 }
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -07001024
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001025 vadc->adc->amux_prop->decimation =
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -07001026 vadc->adc->adc_channels[dt_index].adc_decimation;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001027 vadc->adc->amux_prop->hw_settle_time =
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -07001028 vadc->adc->adc_channels[dt_index].hw_settle_time;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001029 vadc->adc->amux_prop->fast_avg_setup =
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -07001030 vadc->adc->adc_channels[dt_index].fast_avg_setup;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001031
1032 if (trigger_channel < ADC_SEQ_NONE)
1033 vadc->adc->amux_prop->mode_sel = (ADC_OP_CONVERSION_SEQUENCER
1034 << QPNP_VADC_OP_MODE_SHIFT);
1035 else if (trigger_channel == ADC_SEQ_NONE)
1036 vadc->adc->amux_prop->mode_sel = (ADC_OP_NORMAL_MODE
1037 << QPNP_VADC_OP_MODE_SHIFT);
1038 else {
1039 pr_err("Invalid trigger channel:%d\n", trigger_channel);
Siddartha Mohanadossae1da732012-08-08 16:39:02 -07001040 goto fail_unlock;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001041 }
1042
1043 vadc->adc->amux_prop->trigger_channel = trigger_channel;
1044
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001045 rc = qpnp_vadc_configure(vadc, vadc->adc->amux_prop);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001046 if (rc) {
Siddartha Mohanadossae1da732012-08-08 16:39:02 -07001047 pr_err("qpnp vadc configure failed with %d\n", rc);
1048 goto fail_unlock;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001049 }
1050
Siddartha Mohanadoss462088b2013-07-27 19:58:09 -07001051 if (vadc->vadc_poll_eoc) {
1052 while (status1 != QPNP_VADC_STATUS1_EOC) {
1053 rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_STATUS1,
1054 &status1);
Siddartha Mohanadoss9cb2c652012-12-14 19:18:18 -08001055 if (rc < 0)
Siddartha Mohanadoss462088b2013-07-27 19:58:09 -07001056 goto fail_unlock;
1057 status1 &= QPNP_VADC_STATUS1_REQ_STS_EOC_MASK;
1058 usleep_range(QPNP_VADC_CONV_TIME_MIN,
1059 QPNP_VADC_CONV_TIME_MAX);
1060 count++;
1061 if (count > QPNP_VADC_ERR_COUNT) {
1062 pr_err("retry error exceeded\n");
1063 rc = qpnp_vadc_status_debug(vadc);
1064 if (rc < 0)
1065 pr_err("VADC disable failed\n");
1066 rc = -EINVAL;
1067 goto fail_unlock;
1068 }
1069 }
1070 } else {
1071 rc = wait_for_completion_timeout(
1072 &vadc->adc->adc_rslt_completion,
1073 QPNP_ADC_COMPLETION_TIMEOUT);
1074 if (!rc) {
1075 rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_STATUS1,
1076 &status1);
1077 if (rc < 0)
1078 goto fail_unlock;
1079 status1 &= QPNP_VADC_STATUS1_REQ_STS_EOC_MASK;
1080 if (status1 == QPNP_VADC_STATUS1_EOC)
1081 pr_debug("End of conversion status set\n");
1082 else {
1083 rc = qpnp_vadc_status_debug(vadc);
1084 if (rc < 0)
1085 pr_err("VADC disable failed\n");
1086 rc = -EINVAL;
1087 goto fail_unlock;
1088 }
Siddartha Mohanadoss1a0d2032012-11-01 11:22:29 -07001089 }
1090 }
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001091
1092 if (trigger_channel < ADC_SEQ_NONE) {
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001093 rc = qpnp_vadc_read_status(vadc,
1094 vadc->adc->amux_prop->mode_sel);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001095 if (rc)
Siddartha Mohanadossae1da732012-08-08 16:39:02 -07001096 pr_debug("Conversion sequence timed out - %d\n", rc);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001097 }
1098
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001099 rc = qpnp_vadc_read_conversion_result(vadc, &result->adc_code);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001100 if (rc) {
Siddartha Mohanadossae1da732012-08-08 16:39:02 -07001101 pr_err("qpnp vadc read adc code failed with %d\n", rc);
1102 goto fail_unlock;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001103 }
1104
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -07001105 amux_prescaling =
1106 vadc->adc->adc_channels[dt_index].chan_path_prescaling;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001107
Siddartha Mohanadoss630def02013-06-27 14:53:38 -07001108 if (amux_prescaling >= PATH_SCALING_NONE) {
1109 rc = -EINVAL;
1110 goto fail_unlock;
1111 }
1112
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001113 vadc->adc->amux_prop->chan_prop->offset_gain_numerator =
1114 qpnp_vadc_amux_scaling_ratio[amux_prescaling].num;
1115 vadc->adc->amux_prop->chan_prop->offset_gain_denominator =
1116 qpnp_vadc_amux_scaling_ratio[amux_prescaling].den;
1117
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -07001118 scale_type = vadc->adc->adc_channels[dt_index].adc_scale_fn;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001119 if (scale_type >= SCALE_NONE) {
1120 rc = -EBADF;
Siddartha Mohanadossae1da732012-08-08 16:39:02 -07001121 goto fail_unlock;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001122 }
1123
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001124 vadc_scale_fn[scale_type].chan(vadc, result->adc_code,
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001125 vadc->adc->adc_prop, vadc->adc->amux_prop->chan_prop, result);
1126
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001127fail_unlock:
Siddartha Mohanadoss462088b2013-07-27 19:58:09 -07001128 if (vadc->vadc_poll_eoc) {
1129 pr_debug("requesting vadc eoc stay awake\n");
1130 pm_relax(vadc->dev);
1131 }
1132
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001133 mutex_unlock(&vadc->adc->adc_lock);
1134
1135 return rc;
1136}
1137EXPORT_SYMBOL(qpnp_vadc_conv_seq_request);
1138
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001139int32_t qpnp_vadc_read(struct qpnp_vadc_chip *vadc,
1140 enum qpnp_vadc_channels channel,
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001141 struct qpnp_vadc_result *result)
1142{
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -07001143 struct qpnp_vadc_result die_temp_result;
1144 int rc = 0;
1145
1146 if (channel == VBAT_SNS) {
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001147 rc = qpnp_vadc_conv_seq_request(vadc, ADC_SEQ_NONE,
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -07001148 channel, result);
1149 if (rc < 0) {
1150 pr_err("Error reading vbatt\n");
1151 return rc;
1152 }
1153
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001154 rc = qpnp_vadc_conv_seq_request(vadc, ADC_SEQ_NONE,
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -07001155 DIE_TEMP, &die_temp_result);
1156 if (rc < 0) {
1157 pr_err("Error reading die_temp\n");
1158 return rc;
1159 }
1160
Siddartha Mohanadossf3db6142013-08-09 16:54:47 -07001161 rc = qpnp_vbat_sns_comp(&result->physical, vadc,
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -07001162 die_temp_result.physical);
1163 if (rc < 0)
1164 pr_err("Error with vbat compensation\n");
1165
1166 return 0;
1167 } else
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001168 return qpnp_vadc_conv_seq_request(vadc, ADC_SEQ_NONE,
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001169 channel, result);
1170}
Siddartha Mohanadoss271d00f2013-03-26 18:24:14 -07001171EXPORT_SYMBOL(qpnp_vadc_read);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001172
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001173static void qpnp_vadc_lock(struct qpnp_vadc_chip *vadc)
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001174{
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001175 mutex_lock(&vadc->adc->adc_lock);
1176}
1177
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001178static void qpnp_vadc_unlock(struct qpnp_vadc_chip *vadc)
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001179{
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001180 mutex_unlock(&vadc->adc->adc_lock);
1181}
1182
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001183int32_t qpnp_vadc_iadc_sync_request(struct qpnp_vadc_chip *vadc,
1184 enum qpnp_vadc_channels channel)
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001185{
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001186 int rc = 0, dt_index = 0;
1187
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001188 if (qpnp_vadc_is_valid(vadc))
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001189 return -EPROBE_DEFER;
1190
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001191 qpnp_vadc_lock(vadc);
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001192
1193 if (!vadc->vadc_init_calib) {
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001194 rc = qpnp_vadc_version_check(vadc);
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001195 if (rc)
1196 goto fail;
1197
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001198 rc = qpnp_vadc_calib_device(vadc);
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001199 if (rc) {
1200 pr_err("Calibration failed\n");
1201 goto fail;
1202 } else
1203 vadc->vadc_init_calib = true;
1204 }
1205
1206 vadc->adc->amux_prop->amux_channel = channel;
1207
1208 while ((vadc->adc->adc_channels[dt_index].channel_num
1209 != channel) && (dt_index < vadc->max_channels_available))
1210 dt_index++;
1211
1212 if (dt_index >= vadc->max_channels_available) {
1213 pr_err("not a valid VADC channel\n");
1214 rc = -EINVAL;
1215 goto fail;
1216 }
1217
1218 vadc->adc->amux_prop->decimation =
1219 vadc->adc->adc_channels[dt_index].adc_decimation;
1220 vadc->adc->amux_prop->hw_settle_time =
1221 vadc->adc->adc_channels[dt_index].hw_settle_time;
1222 vadc->adc->amux_prop->fast_avg_setup =
1223 vadc->adc->adc_channels[dt_index].fast_avg_setup;
1224 vadc->adc->amux_prop->mode_sel = (ADC_OP_NORMAL_MODE
1225 << QPNP_VADC_OP_MODE_SHIFT);
1226 vadc->vadc_iadc_sync_lock = true;
1227
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001228 rc = qpnp_vadc_configure(vadc, vadc->adc->amux_prop);
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001229 if (rc) {
1230 pr_err("qpnp vadc configure failed with %d\n", rc);
1231 goto fail;
1232 }
1233
1234 return rc;
1235fail:
1236 vadc->vadc_iadc_sync_lock = false;
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001237 qpnp_vadc_unlock(vadc);
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001238 return rc;
1239}
1240EXPORT_SYMBOL(qpnp_vadc_iadc_sync_request);
1241
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001242int32_t qpnp_vadc_iadc_sync_complete_request(struct qpnp_vadc_chip *vadc,
1243 enum qpnp_vadc_channels channel,
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001244 struct qpnp_vadc_result *result)
1245{
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001246 int rc = 0, scale_type, amux_prescaling, dt_index = 0;
1247
1248 vadc->adc->amux_prop->amux_channel = channel;
1249
1250 while ((vadc->adc->adc_channels[dt_index].channel_num
1251 != channel) && (dt_index < vadc->max_channels_available))
1252 dt_index++;
1253
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001254 rc = qpnp_vadc_read_conversion_result(vadc, &result->adc_code);
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001255 if (rc) {
1256 pr_err("qpnp vadc read adc code failed with %d\n", rc);
1257 goto fail;
1258 }
1259
1260 amux_prescaling =
1261 vadc->adc->adc_channels[dt_index].chan_path_prescaling;
1262
Siddartha Mohanadoss630def02013-06-27 14:53:38 -07001263 if (amux_prescaling >= PATH_SCALING_NONE) {
1264 rc = -EINVAL;
1265 goto fail;
1266 }
1267
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001268 vadc->adc->amux_prop->chan_prop->offset_gain_numerator =
1269 qpnp_vadc_amux_scaling_ratio[amux_prescaling].num;
1270 vadc->adc->amux_prop->chan_prop->offset_gain_denominator =
1271 qpnp_vadc_amux_scaling_ratio[amux_prescaling].den;
1272
1273 scale_type = vadc->adc->adc_channels[dt_index].adc_scale_fn;
1274 if (scale_type >= SCALE_NONE) {
1275 rc = -EBADF;
1276 goto fail;
1277 }
1278
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001279 vadc_scale_fn[scale_type].chan(vadc, result->adc_code,
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001280 vadc->adc->adc_prop, vadc->adc->amux_prop->chan_prop, result);
1281
1282fail:
1283 vadc->vadc_iadc_sync_lock = false;
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001284 qpnp_vadc_unlock(vadc);
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001285 return rc;
1286}
1287EXPORT_SYMBOL(qpnp_vadc_iadc_sync_complete_request);
1288
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001289static ssize_t qpnp_adc_show(struct device *dev,
1290 struct device_attribute *devattr, char *buf)
1291{
1292 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001293 struct qpnp_vadc_chip *vadc = dev_get_drvdata(dev);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001294 struct qpnp_vadc_result result;
1295 int rc = -1;
1296
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001297 rc = qpnp_vadc_read(vadc, attr->index, &result);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001298
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -07001299 if (rc) {
1300 pr_err("VADC read error with %d\n", rc);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001301 return 0;
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -07001302 }
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001303
1304 return snprintf(buf, QPNP_ADC_HWMON_NAME_LENGTH,
1305 "Result:%lld Raw:%d\n", result.physical, result.adc_code);
1306}
1307
1308static struct sensor_device_attribute qpnp_adc_attr =
1309 SENSOR_ATTR(NULL, S_IRUGO, qpnp_adc_show, NULL, 0);
1310
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001311static int32_t qpnp_vadc_init_hwmon(struct qpnp_vadc_chip *vadc,
1312 struct spmi_device *spmi)
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001313{
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001314 struct device_node *child;
1315 struct device_node *node = spmi->dev.of_node;
1316 int rc = 0, i = 0, channel;
1317
1318 for_each_child_of_node(node, child) {
1319 channel = vadc->adc->adc_channels[i].channel_num;
1320 qpnp_adc_attr.index = vadc->adc->adc_channels[i].channel_num;
1321 qpnp_adc_attr.dev_attr.attr.name =
1322 vadc->adc->adc_channels[i].name;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001323 memcpy(&vadc->sens_attr[i], &qpnp_adc_attr,
1324 sizeof(qpnp_adc_attr));
Stephen Boydd7337962012-10-30 11:10:46 -07001325 sysfs_attr_init(&vadc->sens_attr[i].dev_attr.attr);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001326 rc = device_create_file(&spmi->dev,
1327 &vadc->sens_attr[i].dev_attr);
1328 if (rc) {
1329 dev_err(&spmi->dev,
1330 "device_create_file failed for dev %s\n",
1331 vadc->adc->adc_channels[i].name);
1332 goto hwmon_err_sens;
1333 }
1334 i++;
1335 }
1336
1337 return 0;
1338hwmon_err_sens:
Siddartha Mohanadossae1da732012-08-08 16:39:02 -07001339 pr_err("Init HWMON failed for qpnp_adc with %d\n", rc);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001340 return rc;
1341}
1342
1343static int __devinit qpnp_vadc_probe(struct spmi_device *spmi)
1344{
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001345 struct qpnp_vadc_chip *vadc;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001346 struct qpnp_adc_drv *adc_qpnp;
1347 struct device_node *node = spmi->dev.of_node;
1348 struct device_node *child;
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001349 int rc, count_adc_channel_list = 0, i = 0;
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -07001350 u8 fab_id = 0;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001351
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001352 for_each_child_of_node(node, child)
1353 count_adc_channel_list++;
1354
1355 if (!count_adc_channel_list) {
1356 pr_err("No channel listing\n");
1357 return -EINVAL;
1358 }
1359
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001360 vadc = devm_kzalloc(&spmi->dev, sizeof(struct qpnp_vadc_chip) +
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001361 (sizeof(struct sensor_device_attribute) *
1362 count_adc_channel_list), GFP_KERNEL);
1363 if (!vadc) {
1364 dev_err(&spmi->dev, "Unable to allocate memory\n");
1365 return -ENOMEM;
1366 }
1367
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001368 vadc->dev = &(spmi->dev);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001369 adc_qpnp = devm_kzalloc(&spmi->dev, sizeof(struct qpnp_adc_drv),
1370 GFP_KERNEL);
1371 if (!adc_qpnp) {
1372 dev_err(&spmi->dev, "Unable to allocate memory\n");
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001373 return -ENOMEM;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001374 }
1375
1376 vadc->adc = adc_qpnp;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001377 rc = qpnp_adc_get_devicetree_data(spmi, vadc->adc);
1378 if (rc) {
1379 dev_err(&spmi->dev, "failed to read device tree\n");
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001380 return rc;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001381 }
Stephen Boydbeab4502013-04-25 10:18:17 -07001382 mutex_init(&vadc->adc->adc_lock);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001383
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001384 rc = qpnp_vadc_init_hwmon(vadc, spmi);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001385 if (rc) {
1386 dev_err(&spmi->dev, "failed to initialize qpnp hwmon adc\n");
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001387 return rc;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001388 }
1389 vadc->vadc_hwmon = hwmon_device_register(&vadc->adc->spmi->dev);
1390 vadc->vadc_init_calib = false;
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -07001391 vadc->max_channels_available = count_adc_channel_list;
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001392 rc = qpnp_vadc_read_reg(vadc, QPNP_INT_TEST_VAL, &fab_id);
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -07001393 if (rc < 0) {
1394 pr_err("qpnp adc comp id failed with %d\n", rc);
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001395 goto err_setup;
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -07001396 }
1397 vadc->id = fab_id;
1398
Siddartha Mohanadossf3db6142013-08-09 16:54:47 -07001399 rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_REVISION2,
1400 &vadc->revision_dig_major);
1401 if (rc < 0) {
1402 pr_err("qpnp adc dig_major rev read failed with %d\n", rc);
1403 goto err_setup;
1404 }
1405
1406 rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_REVISION3,
1407 &vadc->revision_ana_minor);
1408 if (rc < 0) {
1409 pr_err("qpnp adc ana_minor rev read failed with %d\n", rc);
1410 goto err_setup;
1411 }
1412
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001413 rc = qpnp_vadc_warm_rst_configure(vadc);
Siddartha Mohanadoss22559462013-05-15 15:30:28 -07001414 if (rc < 0) {
1415 pr_err("Setting perp reset on warm reset failed %d\n", rc);
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001416 goto err_setup;
Siddartha Mohanadoss22559462013-05-15 15:30:28 -07001417 }
1418
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001419 INIT_WORK(&vadc->trigger_completion_work, qpnp_vadc_work);
Siddartha Mohanadoss73fb1512013-08-08 22:38:13 -07001420
1421 vadc->vadc_poll_eoc = of_property_read_bool(node,
1422 "qcom,vadc-poll-eoc");
1423 if (!vadc->vadc_poll_eoc) {
1424 rc = devm_request_irq(&spmi->dev, vadc->adc->adc_irq_eoc,
1425 qpnp_vadc_isr, IRQF_TRIGGER_RISING,
1426 "qpnp_vadc_interrupt", vadc);
1427 if (rc) {
1428 dev_err(&spmi->dev,
1429 "failed to request adc irq with error %d\n", rc);
1430 goto err_setup;
1431 } else {
1432 enable_irq_wake(vadc->adc->adc_irq_eoc);
1433 }
1434 } else
Siddartha Mohanadoss462088b2013-07-27 19:58:09 -07001435 device_init_wakeup(vadc->dev, 1);
1436
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001437 vadc->vadc_iadc_sync_lock = false;
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001438 dev_set_drvdata(&spmi->dev, vadc);
1439 list_add(&vadc->list, &qpnp_vadc_device_list);
1440
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001441 return 0;
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001442
1443err_setup:
1444 for_each_child_of_node(node, child) {
1445 device_remove_file(&spmi->dev,
1446 &vadc->sens_attr[i].dev_attr);
1447 i++;
1448 }
1449 hwmon_device_unregister(vadc->vadc_hwmon);
1450
Siddartha Mohanadossb60f6462012-11-20 18:06:51 -08001451 return rc;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001452}
1453
1454static int __devexit qpnp_vadc_remove(struct spmi_device *spmi)
1455{
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001456 struct qpnp_vadc_chip *vadc = dev_get_drvdata(&spmi->dev);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001457 struct device_node *node = spmi->dev.of_node;
1458 struct device_node *child;
1459 int i = 0;
1460
1461 for_each_child_of_node(node, child) {
1462 device_remove_file(&spmi->dev,
1463 &vadc->sens_attr[i].dev_attr);
1464 i++;
1465 }
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001466 hwmon_device_unregister(vadc->vadc_hwmon);
1467 list_del(&vadc->list);
Siddartha Mohanadoss462088b2013-07-27 19:58:09 -07001468 if (vadc->vadc_poll_eoc)
1469 pm_relax(vadc->dev);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001470 dev_set_drvdata(&spmi->dev, NULL);
1471
1472 return 0;
1473}
1474
1475static const struct of_device_id qpnp_vadc_match_table[] = {
1476 { .compatible = "qcom,qpnp-vadc",
1477 },
1478 {}
1479};
1480
1481static struct spmi_driver qpnp_vadc_driver = {
1482 .driver = {
1483 .name = "qcom,qpnp-vadc",
1484 .of_match_table = qpnp_vadc_match_table,
1485 },
1486 .probe = qpnp_vadc_probe,
1487 .remove = qpnp_vadc_remove,
1488};
1489
1490static int __init qpnp_vadc_init(void)
1491{
1492 return spmi_driver_register(&qpnp_vadc_driver);
1493}
1494module_init(qpnp_vadc_init);
1495
1496static void __exit qpnp_vadc_exit(void)
1497{
1498 spmi_driver_unregister(&qpnp_vadc_driver);
1499}
1500module_exit(qpnp_vadc_exit);
1501
1502MODULE_DESCRIPTION("QPNP PMIC Voltage ADC driver");
1503MODULE_LICENSE("GPL v2");