blob: 2fe69fb016ea01947247d41a31e94a6aead01648 [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 Mohanadoss73ae69b2013-04-03 17:34:03 -0700102#define QPNP_VADC_ERR_COUNT 5
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 Mohanadoss4e64f8c2013-04-08 15:57:32 -0700115 struct sensor_device_attribute sens_attr[0];
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700116};
117
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700118LIST_HEAD(qpnp_vadc_device_list);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700119
120static struct qpnp_vadc_scale_fn vadc_scale_fn[] = {
121 [SCALE_DEFAULT] = {qpnp_adc_scale_default},
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700122 [SCALE_BATT_THERM] = {qpnp_adc_scale_batt_therm},
123 [SCALE_PMIC_THERM] = {qpnp_adc_scale_pmic_therm},
124 [SCALE_XOTHERM] = {qpnp_adc_tdkntcg_therm},
Siddartha Mohanadosse77edf12012-09-13 14:26:32 -0700125 [SCALE_THERM_100K_PULLUP] = {qpnp_adc_scale_therm_pu2},
126 [SCALE_THERM_150K_PULLUP] = {qpnp_adc_scale_therm_pu1},
Siddartha Mohanadossb99cfa92013-05-01 20:19:58 -0700127 [SCALE_QRD_BATT_THERM] = {qpnp_adc_scale_qrd_batt_therm},
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700128};
129
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700130static int32_t qpnp_vadc_read_reg(struct qpnp_vadc_chip *vadc, int16_t reg,
131 u8 *data)
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700132{
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700133 int rc;
134
135 rc = spmi_ext_register_readl(vadc->adc->spmi->ctrl, vadc->adc->slave,
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700136 (vadc->adc->offset + reg), data, 1);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700137 if (rc < 0) {
138 pr_err("qpnp adc read reg %d failed with %d\n", reg, rc);
139 return rc;
140 }
141
142 return 0;
143}
144
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700145static int32_t qpnp_vadc_write_reg(struct qpnp_vadc_chip *vadc, int16_t reg,
146 u8 data)
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700147{
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700148 int rc;
149 u8 *buf;
150
151 buf = &data;
152
153 rc = spmi_ext_register_writel(vadc->adc->spmi->ctrl, vadc->adc->slave,
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700154 (vadc->adc->offset + reg), buf, 1);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700155 if (rc < 0) {
156 pr_err("qpnp adc write reg %d failed with %d\n", reg, rc);
157 return rc;
158 }
159
160 return 0;
161}
162
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700163static int32_t qpnp_vadc_warm_rst_configure(struct qpnp_vadc_chip *vadc)
Siddartha Mohanadoss22559462013-05-15 15:30:28 -0700164{
165 int rc = 0;
166 u8 data = 0;
167
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700168 rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_ACCESS, QPNP_VADC_ACCESS_DATA);
Siddartha Mohanadoss22559462013-05-15 15:30:28 -0700169 if (rc < 0) {
170 pr_err("VADC write access failed\n");
171 return rc;
172 }
173
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700174 rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_PERH_RESET_CTL3, &data);
Siddartha Mohanadoss22559462013-05-15 15:30:28 -0700175 if (rc < 0) {
176 pr_err("VADC perh reset ctl3 read failed\n");
177 return rc;
178 }
179
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700180 rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_ACCESS, QPNP_VADC_ACCESS_DATA);
Siddartha Mohanadoss22559462013-05-15 15:30:28 -0700181 if (rc < 0) {
182 pr_err("VADC write access failed\n");
183 return rc;
184 }
185
186 data |= QPNP_FOLLOW_WARM_RB;
187
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700188 rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_PERH_RESET_CTL3, data);
Siddartha Mohanadoss22559462013-05-15 15:30:28 -0700189 if (rc < 0) {
190 pr_err("VADC perh reset ctl3 write failed\n");
191 return rc;
192 }
193
194 return 0;
195}
196
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700197static int32_t qpnp_vadc_enable(struct qpnp_vadc_chip *vadc, bool state)
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700198{
199 int rc = 0;
200 u8 data = 0;
201
202 data = QPNP_VADC_ADC_EN;
203 if (state) {
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700204 rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_EN_CTL1,
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700205 data);
206 if (rc < 0) {
207 pr_err("VADC enable failed\n");
208 return rc;
209 }
210 } else {
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700211 rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_EN_CTL1,
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700212 (~data & QPNP_VADC_ADC_EN));
213 if (rc < 0) {
214 pr_err("VADC disable failed\n");
215 return rc;
216 }
217 }
218
219 return 0;
220}
221
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700222static int32_t qpnp_vadc_status_debug(struct qpnp_vadc_chip *vadc)
Siddartha Mohanadoss9cb2c652012-12-14 19:18:18 -0800223{
224 int rc = 0;
225 u8 mode = 0, status1 = 0, chan = 0, dig = 0, en = 0, status2 = 0;
226
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700227 rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_MODE_CTL, &mode);
Siddartha Mohanadoss9cb2c652012-12-14 19:18:18 -0800228 if (rc < 0) {
229 pr_err("mode ctl register read failed with %d\n", rc);
230 return rc;
231 }
232
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700233 rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_ADC_DIG_PARAM, &dig);
Siddartha Mohanadoss9cb2c652012-12-14 19:18:18 -0800234 if (rc < 0) {
235 pr_err("digital param read failed with %d\n", rc);
236 return rc;
237 }
238
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700239 rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_ADC_CH_SEL_CTL, &chan);
Siddartha Mohanadoss9cb2c652012-12-14 19:18:18 -0800240 if (rc < 0) {
241 pr_err("channel read failed with %d\n", rc);
242 return rc;
243 }
244
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700245 rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_STATUS1, &status1);
Siddartha Mohanadoss9cb2c652012-12-14 19:18:18 -0800246 if (rc < 0) {
247 pr_err("status1 read failed with %d\n", rc);
248 return rc;
249 }
250
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700251 rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_STATUS2, &status2);
Siddartha Mohanadoss9cb2c652012-12-14 19:18:18 -0800252 if (rc < 0) {
253 pr_err("status2 read failed with %d\n", rc);
254 return rc;
255 }
256
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700257 rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_EN_CTL1, &en);
Siddartha Mohanadoss9cb2c652012-12-14 19:18:18 -0800258 if (rc < 0) {
259 pr_err("en read failed with %d\n", rc);
260 return rc;
261 }
262
263 pr_err("EOC not set - status1/2:%x/%x, dig:%x, ch:%x, mode:%x, en:%x\n",
264 status1, status2, dig, chan, mode, en);
265
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700266 rc = qpnp_vadc_enable(vadc, false);
Siddartha Mohanadoss9cb2c652012-12-14 19:18:18 -0800267 if (rc < 0) {
268 pr_err("VADC disable failed with %d\n", rc);
269 return rc;
270 }
271
272 return 0;
273}
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700274static int32_t qpnp_vadc_configure(struct qpnp_vadc_chip *vadc,
Siddartha Mohanadossc4a6af12012-07-13 18:50:12 -0700275 struct qpnp_adc_amux_properties *chan_prop)
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700276{
277 u8 decimation = 0, conv_sequence = 0, conv_sequence_trig = 0;
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700278 u8 mode_ctrl = 0;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700279 int rc = 0;
280
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700281 /* Mode selection */
Siddartha Mohanadoss429b4492012-12-11 13:29:58 -0800282 mode_ctrl |= ((chan_prop->mode_sel << QPNP_VADC_OP_MODE_SHIFT) |
283 (QPNP_VADC_ADC_TRIM_EN | QPNP_VADC_AMUX_TRIM_EN));
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700284 rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_MODE_CTL, mode_ctrl);
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700285 if (rc < 0) {
286 pr_err("Mode configure write error\n");
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700287 return rc;
288 }
289
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700290
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700291 /* Channel selection */
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700292 rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_ADC_CH_SEL_CTL,
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700293 chan_prop->amux_channel);
294 if (rc < 0) {
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700295 pr_err("Channel configure error\n");
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700296 return rc;
297 }
298
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700299 /* Digital parameter setup */
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700300 decimation = chan_prop->decimation <<
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700301 QPNP_VADC_ADC_DIG_DEC_RATIO_SEL_SHIFT;
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700302 rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_ADC_DIG_PARAM, decimation);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700303 if (rc < 0) {
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700304 pr_err("Digital parameter configure write error\n");
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700305 return rc;
306 }
307
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700308 /* HW settling time delay */
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700309 rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_HW_SETTLE_DELAY,
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700310 chan_prop->hw_settle_time);
311 if (rc < 0) {
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700312 pr_err("HW settling time setup error\n");
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700313 return rc;
314 }
315
316 if (chan_prop->mode_sel == (ADC_OP_NORMAL_MODE <<
317 QPNP_VADC_OP_MODE_SHIFT)) {
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700318 /* Normal measurement mode */
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700319 rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_FAST_AVG_CTL,
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700320 chan_prop->fast_avg_setup);
321 if (rc < 0) {
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700322 pr_err("Fast averaging configure error\n");
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700323 return rc;
324 }
325 } else if (chan_prop->mode_sel == (ADC_OP_CONVERSION_SEQUENCER <<
326 QPNP_VADC_OP_MODE_SHIFT)) {
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700327 /* Conversion sequence mode */
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700328 conv_sequence = ((ADC_SEQ_HOLD_100US <<
329 QPNP_VADC_CONV_SEQ_HOLDOFF_SHIFT) |
330 ADC_CONV_SEQ_TIMEOUT_5MS);
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700331 rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_CONV_SEQ_CTL,
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700332 conv_sequence);
333 if (rc < 0) {
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700334 pr_err("Conversion sequence error\n");
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700335 return rc;
336 }
337
338 conv_sequence_trig = ((QPNP_VADC_CONV_SEQ_RISING_EDGE <<
339 QPNP_VADC_CONV_SEQ_EDGE_SHIFT) |
340 chan_prop->trigger_channel);
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700341 rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_CONV_SEQ_TRIG_CTL,
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700342 conv_sequence_trig);
343 if (rc < 0) {
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700344 pr_err("Conversion trigger error\n");
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700345 return rc;
346 }
347 }
348
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700349 INIT_COMPLETION(vadc->adc->adc_rslt_completion);
350
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700351 rc = qpnp_vadc_enable(vadc, true);
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700352 if (rc)
353 return rc;
354
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -0800355 if (!vadc->vadc_iadc_sync_lock) {
356 /* Request conversion */
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700357 rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_CONV_REQ,
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -0800358 QPNP_VADC_CONV_REQ_SET);
359 if (rc < 0) {
360 pr_err("Request conversion failed\n");
361 return rc;
362 }
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700363 }
364
365 return 0;
366}
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700367
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700368static int32_t qpnp_vadc_read_conversion_result(struct qpnp_vadc_chip *vadc,
369 int32_t *data)
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700370{
371 uint8_t rslt_lsb, rslt_msb;
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700372 int rc = 0, status = 0;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700373
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700374 status = qpnp_vadc_read_reg(vadc, QPNP_VADC_DATA0, &rslt_lsb);
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700375 if (status < 0) {
376 pr_err("qpnp adc result read failed for data0\n");
377 goto fail;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700378 }
379
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700380 status = qpnp_vadc_read_reg(vadc, QPNP_VADC_DATA1, &rslt_msb);
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700381 if (status < 0) {
382 pr_err("qpnp adc result read failed for data1\n");
383 goto fail;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700384 }
385
386 *data = (rslt_msb << 8) | rslt_lsb;
387
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700388 status = qpnp_vadc_check_result(data);
389 if (status < 0) {
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700390 pr_err("VADC data check failed\n");
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700391 goto fail;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700392 }
393
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700394fail:
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700395 rc = qpnp_vadc_enable(vadc, false);
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700396 if (rc)
397 return rc;
398
399 return status;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700400}
401
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700402static int32_t qpnp_vadc_read_status(struct qpnp_vadc_chip *vadc, int mode_sel)
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700403{
404 u8 status1, status2, status2_conv_seq_state;
405 u8 status_err = QPNP_VADC_CONV_TIMEOUT_ERR;
406 int rc;
407
408 switch (mode_sel) {
409 case (ADC_OP_CONVERSION_SEQUENCER << QPNP_VADC_OP_MODE_SHIFT):
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700410 rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_STATUS1, &status1);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700411 if (rc) {
412 pr_err("qpnp_vadc read mask interrupt failed\n");
413 return rc;
414 }
415
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700416 rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_STATUS2, &status2);
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
422 if (!(status2 & ~QPNP_VADC_STATUS2_CONV_SEQ_TIMEOUT_STS) &&
423 (status1 & (~QPNP_VADC_STATUS1_REQ_STS |
424 QPNP_VADC_STATUS1_EOC))) {
425 rc = status_err;
426 return rc;
427 }
428
429 status2_conv_seq_state = status2 >>
430 QPNP_VADC_STATUS2_CONV_SEQ_STATE_SHIFT;
431 if (status2_conv_seq_state != ADC_CONV_SEQ_IDLE) {
432 pr_err("qpnp vadc seq error with status %d\n",
433 status2);
434 rc = -EINVAL;
435 return rc;
436 }
437 }
438
439 return 0;
440}
441
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700442static int qpnp_vadc_is_valid(struct qpnp_vadc_chip *vadc)
443{
444 struct qpnp_vadc_chip *vadc_chip = NULL;
445
446 list_for_each_entry(vadc_chip, &qpnp_vadc_device_list, list)
447 if (vadc == vadc_chip)
448 return 0;
449
450 return -EINVAL;
451}
452
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700453static void qpnp_vadc_work(struct work_struct *work)
454{
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700455 struct qpnp_vadc_chip *vadc = container_of(work,
456 struct qpnp_vadc_chip, trigger_completion_work);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700457
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700458 if (qpnp_vadc_is_valid(vadc) < 0)
Siddartha Mohanadossb60f6462012-11-20 18:06:51 -0800459 return;
460
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700461 complete(&vadc->adc->adc_rslt_completion);
462
463 return;
464}
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700465
466static irqreturn_t qpnp_vadc_isr(int irq, void *dev_id)
467{
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700468 struct qpnp_vadc_chip *vadc = dev_id;
469
470 schedule_work(&vadc->trigger_completion_work);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700471
472 return IRQ_HANDLED;
473}
474
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700475static int32_t qpnp_vadc_version_check(struct qpnp_vadc_chip *dev)
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700476{
477 uint8_t revision;
478 int rc;
479
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700480 rc = qpnp_vadc_read_reg(dev, QPNP_VADC_REVISION2, &revision);
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700481 if (rc < 0) {
482 pr_err("qpnp adc result read failed with %d\n", rc);
483 return rc;
484 }
485
486 if (revision < QPNP_VADC_SUPPORTED_REVISION2) {
487 pr_err("VADC Version not supported\n");
488 return -EINVAL;
489 }
490
491 return 0;
492}
493
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -0700494static int32_t qpnp_vbat_sns_comp(int64_t *result, u8 id, int64_t die_temp)
495{
496 int64_t temp_var = 0;
Xiaozhe Shi62ad5e12013-05-13 12:37:41 -0700497 int64_t old = *result;
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -0700498
499 if (die_temp < 25000)
500 return 0;
501
502 switch (id) {
503 case COMP_ID_TSMC:
504 temp_var = (((die_temp *
505 (-QPNP_VBAT_SNS_COEFF_1_TYPEB))
506 + QPNP_VBAT_SNS_COEFF_2_TYPEB));
507 break;
508 default:
509 case COMP_ID_GF:
510 temp_var = (((die_temp *
511 (-QPNP_VBAT_SNS_COEFF_1_TYPEA))
512 + QPNP_VBAT_SNS_COEFF_2_TYPEA));
513 break;
514 }
515
516 temp_var = div64_s64(temp_var, QPNP_VBAT_SNS_COEFF_3);
517
518 temp_var = 1000000 + temp_var;
519
520 *result = *result * temp_var;
521
522 *result = div64_s64(*result, 1000000);
Xiaozhe Shi62ad5e12013-05-13 12:37:41 -0700523 pr_debug("%lld compensated into %lld\n", old, *result);
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -0700524
525 return 0;
526}
527
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700528int32_t qpnp_vbat_sns_comp_result(struct qpnp_vadc_chip *vadc,
529 int64_t *result)
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -0700530{
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -0700531 struct qpnp_vadc_result die_temp_result;
532 int rc = 0;
533
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700534 rc = qpnp_vadc_is_valid(vadc);
535 if (rc < 0)
536 return rc;
537
538 rc = qpnp_vadc_conv_seq_request(vadc, ADC_SEQ_NONE,
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -0700539 DIE_TEMP, &die_temp_result);
540 if (rc < 0) {
541 pr_err("Error reading die_temp\n");
542 return rc;
543 }
544
545 rc = qpnp_vbat_sns_comp(result, vadc->id,
546 die_temp_result.physical);
547 if (rc < 0)
548 pr_err("Error with vbat compensation\n");
549
550 return rc;
551}
552EXPORT_SYMBOL(qpnp_vbat_sns_comp_result);
553
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700554static void qpnp_vadc_625mv_channel_sel(struct qpnp_vadc_chip *vadc,
555 uint32_t *ref_channel_sel)
Siddartha Mohanadoss9edb61e2013-04-29 13:52:52 -0700556{
Siddartha Mohanadoss9edb61e2013-04-29 13:52:52 -0700557 uint32_t dt_index = 0;
558
559 /* Check if the buffered 625mV channel exists */
560 while ((vadc->adc->adc_channels[dt_index].channel_num
561 != SPARE1) && (dt_index < vadc->max_channels_available))
562 dt_index++;
563
564 if (dt_index >= vadc->max_channels_available) {
565 pr_debug("Use default 625mV ref channel\n");
566 *ref_channel_sel = REF_625MV;
567 } else {
568 pr_debug("Use buffered 625mV ref channel\n");
569 *ref_channel_sel = SPARE1;
570 }
571}
572
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700573static int32_t qpnp_vadc_calib_device(struct qpnp_vadc_chip *vadc)
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700574{
Siddartha Mohanadossc4a6af12012-07-13 18:50:12 -0700575 struct qpnp_adc_amux_properties conv;
Siddartha Mohanadoss73ae69b2013-04-03 17:34:03 -0700576 int rc, calib_read_1, calib_read_2, count = 0;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700577 u8 status1 = 0;
Siddartha Mohanadoss9edb61e2013-04-29 13:52:52 -0700578 uint32_t ref_channel_sel = 0;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700579
580 conv.amux_channel = REF_125V;
581 conv.decimation = DECIMATION_TYPE2;
582 conv.mode_sel = ADC_OP_NORMAL_MODE << QPNP_VADC_OP_MODE_SHIFT;
583 conv.hw_settle_time = ADC_CHANNEL_HW_SETTLE_DELAY_0US;
584 conv.fast_avg_setup = ADC_FAST_AVG_SAMPLE_1;
585
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700586 rc = qpnp_vadc_configure(vadc, &conv);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700587 if (rc) {
588 pr_err("qpnp_vadc configure failed with %d\n", rc);
589 goto calib_fail;
590 }
591
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700592 while (status1 != QPNP_VADC_STATUS1_EOC) {
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700593 rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_STATUS1, &status1);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700594 if (rc < 0)
595 return rc;
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700596 status1 &= QPNP_VADC_STATUS1_REQ_STS_EOC_MASK;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700597 usleep_range(QPNP_VADC_CONV_TIME_MIN,
598 QPNP_VADC_CONV_TIME_MAX);
Siddartha Mohanadoss73ae69b2013-04-03 17:34:03 -0700599 count++;
600 if (count > QPNP_VADC_ERR_COUNT) {
601 rc = -ENODEV;
602 goto calib_fail;
603 }
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700604 }
605
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700606 rc = qpnp_vadc_read_conversion_result(vadc, &calib_read_1);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700607 if (rc) {
608 pr_err("qpnp adc read adc failed with %d\n", rc);
609 goto calib_fail;
610 }
611
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700612 qpnp_vadc_625mv_channel_sel(vadc, &ref_channel_sel);
Siddartha Mohanadoss9edb61e2013-04-29 13:52:52 -0700613 conv.amux_channel = ref_channel_sel;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700614 conv.decimation = DECIMATION_TYPE2;
615 conv.mode_sel = ADC_OP_NORMAL_MODE << QPNP_VADC_OP_MODE_SHIFT;
616 conv.hw_settle_time = ADC_CHANNEL_HW_SETTLE_DELAY_0US;
617 conv.fast_avg_setup = ADC_FAST_AVG_SAMPLE_1;
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700618 rc = qpnp_vadc_configure(vadc, &conv);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700619 if (rc) {
620 pr_err("qpnp adc configure failed with %d\n", rc);
621 goto calib_fail;
622 }
623
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700624 status1 = 0;
Siddartha Mohanadoss73ae69b2013-04-03 17:34:03 -0700625 count = 0;
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700626 while (status1 != QPNP_VADC_STATUS1_EOC) {
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700627 rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_STATUS1, &status1);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700628 if (rc < 0)
629 return rc;
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700630 status1 &= QPNP_VADC_STATUS1_REQ_STS_EOC_MASK;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700631 usleep_range(QPNP_VADC_CONV_TIME_MIN,
632 QPNP_VADC_CONV_TIME_MAX);
Siddartha Mohanadoss73ae69b2013-04-03 17:34:03 -0700633 count++;
634 if (count > QPNP_VADC_ERR_COUNT) {
635 rc = -ENODEV;
636 goto calib_fail;
637 }
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700638 }
639
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700640 rc = qpnp_vadc_read_conversion_result(vadc, &calib_read_2);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700641 if (rc) {
642 pr_err("qpnp adc read adc failed with %d\n", rc);
643 goto calib_fail;
644 }
645
Siddartha Mohanadossb2a42372013-03-26 15:53:41 -0700646 pr_debug("absolute reference raw: 625mV:0x%x 1.25V:0x%x\n",
647 calib_read_1, calib_read_2);
648
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700649 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_ABSOLUTE].dy =
650 (calib_read_1 - calib_read_2);
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700651
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700652 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_ABSOLUTE].dx
653 = QPNP_ADC_625_UV;
654 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_ABSOLUTE].adc_vref =
655 calib_read_1;
656 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_ABSOLUTE].adc_gnd =
657 calib_read_2;
658 /* Ratiometric Calibration */
659 conv.amux_channel = VDD_VADC;
660 conv.decimation = DECIMATION_TYPE2;
661 conv.mode_sel = ADC_OP_NORMAL_MODE << QPNP_VADC_OP_MODE_SHIFT;
662 conv.hw_settle_time = ADC_CHANNEL_HW_SETTLE_DELAY_0US;
663 conv.fast_avg_setup = ADC_FAST_AVG_SAMPLE_1;
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700664 rc = qpnp_vadc_configure(vadc, &conv);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700665 if (rc) {
666 pr_err("qpnp adc configure failed with %d\n", rc);
667 goto calib_fail;
668 }
669
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700670 status1 = 0;
Siddartha Mohanadoss73ae69b2013-04-03 17:34:03 -0700671 count = 0;
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700672 while (status1 != QPNP_VADC_STATUS1_EOC) {
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700673 rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_STATUS1, &status1);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700674 if (rc < 0)
675 return rc;
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700676 status1 &= QPNP_VADC_STATUS1_REQ_STS_EOC_MASK;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700677 usleep_range(QPNP_VADC_CONV_TIME_MIN,
678 QPNP_VADC_CONV_TIME_MAX);
Siddartha Mohanadoss73ae69b2013-04-03 17:34:03 -0700679 count++;
680 if (count > QPNP_VADC_ERR_COUNT) {
681 rc = -ENODEV;
682 goto calib_fail;
683 }
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700684 }
685
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700686 rc = qpnp_vadc_read_conversion_result(vadc, &calib_read_1);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700687 if (rc) {
688 pr_err("qpnp adc read adc failed with %d\n", rc);
689 goto calib_fail;
690 }
691
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700692 conv.amux_channel = GND_REF;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700693 conv.decimation = DECIMATION_TYPE2;
694 conv.mode_sel = ADC_OP_NORMAL_MODE << QPNP_VADC_OP_MODE_SHIFT;
695 conv.hw_settle_time = ADC_CHANNEL_HW_SETTLE_DELAY_0US;
696 conv.fast_avg_setup = ADC_FAST_AVG_SAMPLE_1;
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700697 rc = qpnp_vadc_configure(vadc, &conv);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700698 if (rc) {
699 pr_err("qpnp adc configure failed with %d\n", rc);
700 goto calib_fail;
701 }
702
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700703 status1 = 0;
Siddartha Mohanadoss73ae69b2013-04-03 17:34:03 -0700704 count = 0;
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700705 while (status1 != QPNP_VADC_STATUS1_EOC) {
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700706 rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_STATUS1, &status1);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700707 if (rc < 0)
708 return rc;
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700709 status1 &= QPNP_VADC_STATUS1_REQ_STS_EOC_MASK;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700710 usleep_range(QPNP_VADC_CONV_TIME_MIN,
711 QPNP_VADC_CONV_TIME_MAX);
Siddartha Mohanadoss73ae69b2013-04-03 17:34:03 -0700712 count++;
713 if (count > QPNP_VADC_ERR_COUNT) {
714 rc = -ENODEV;
715 goto calib_fail;
716 }
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700717 }
718
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700719 rc = qpnp_vadc_read_conversion_result(vadc, &calib_read_2);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700720 if (rc) {
721 pr_err("qpnp adc read adc failed with %d\n", rc);
722 goto calib_fail;
723 }
724
Siddartha Mohanadossb2a42372013-03-26 15:53:41 -0700725 pr_debug("ratiometric reference raw: VDD:0x%x GND:0x%x\n",
726 calib_read_1, calib_read_2);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700727 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_RATIOMETRIC].dy =
728 (calib_read_1 - calib_read_2);
729 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_RATIOMETRIC].dx =
730 vadc->adc->adc_prop->adc_vdd_reference;
731 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_RATIOMETRIC].adc_vref =
732 calib_read_1;
733 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_RATIOMETRIC].adc_gnd =
734 calib_read_2;
735
736calib_fail:
737 return rc;
738}
739
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700740int32_t qpnp_get_vadc_gain_and_offset(struct qpnp_vadc_chip *vadc,
741 struct qpnp_vadc_linear_graph *param,
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800742 enum qpnp_adc_calib_type calib_type)
743{
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700744 int rc = 0;
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800745
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700746 rc = qpnp_vadc_is_valid(vadc);
747 if (rc < 0)
748 return rc;
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800749
750 switch (calib_type) {
751 case CALIB_RATIOMETRIC:
752 param->dy =
753 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_RATIOMETRIC].dy;
754 param->dx =
755 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_RATIOMETRIC].dx;
756 param->adc_vref = vadc->adc->adc_prop->adc_vdd_reference;
757 param->adc_gnd =
758 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_RATIOMETRIC].adc_gnd;
759 break;
760 case CALIB_ABSOLUTE:
761 param->dy =
762 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_ABSOLUTE].dy;
763 param->dx =
764 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_ABSOLUTE].dx;
765 param->adc_vref = vadc->adc->adc_prop->adc_vdd_reference;
766 param->adc_gnd =
767 vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_ABSOLUTE].adc_gnd;
768 break;
769 default:
770 return -EINVAL;
771 }
772
773 return 0;
774}
775EXPORT_SYMBOL(qpnp_get_vadc_gain_and_offset);
776
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700777struct qpnp_vadc_chip *qpnp_get_vadc(struct device *dev, const char *name)
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700778{
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700779 struct qpnp_vadc_chip *vadc;
780 struct device_node *node = NULL;
781 char prop_name[QPNP_MAX_PROP_NAME_LEN];
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700782
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700783 snprintf(prop_name, QPNP_MAX_PROP_NAME_LEN, "qcom,%s-vadc", name);
784
785 node = of_parse_phandle(dev->of_node, prop_name, 0);
786 if (node == NULL)
787 return ERR_PTR(-ENODEV);
788
789 list_for_each_entry(vadc, &qpnp_vadc_device_list, list)
790 if (vadc->adc->spmi->dev.of_node == node)
791 return vadc;
792 return ERR_PTR(-EPROBE_DEFER);
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700793}
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700794EXPORT_SYMBOL(qpnp_get_vadc);
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700795
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700796int32_t qpnp_vadc_conv_seq_request(struct qpnp_vadc_chip *vadc,
797 enum qpnp_vadc_trigger trigger_channel,
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700798 enum qpnp_vadc_channels channel,
799 struct qpnp_vadc_result *result)
800{
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700801 int rc = 0, scale_type, amux_prescaling, dt_index = 0;
Siddartha Mohanadoss9edb61e2013-04-29 13:52:52 -0700802 uint32_t ref_channel;
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700803
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700804 if (qpnp_vadc_is_valid(vadc))
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700805 return -EPROBE_DEFER;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700806
Siddartha Mohanadoss64bc4f52012-12-19 20:26:32 -0800807 mutex_lock(&vadc->adc->adc_lock);
808
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700809 if (!vadc->vadc_init_calib) {
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700810 rc = qpnp_vadc_version_check(vadc);
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700811 if (rc)
Siddartha Mohanadoss64bc4f52012-12-19 20:26:32 -0800812 goto fail_unlock;
813
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700814 rc = qpnp_vadc_calib_device(vadc);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700815 if (rc) {
816 pr_err("Calibration failed\n");
Siddartha Mohanadoss64bc4f52012-12-19 20:26:32 -0800817 goto fail_unlock;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700818 } else
819 vadc->vadc_init_calib = true;
820 }
821
Siddartha Mohanadoss9edb61e2013-04-29 13:52:52 -0700822 if (channel == REF_625MV) {
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700823 qpnp_vadc_625mv_channel_sel(vadc, &ref_channel);
Siddartha Mohanadoss9edb61e2013-04-29 13:52:52 -0700824 channel = ref_channel;
825 }
826
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700827 vadc->adc->amux_prop->amux_channel = channel;
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700828
Siddartha Mohanadoss7126ce82012-12-11 14:33:11 -0800829 while ((vadc->adc->adc_channels[dt_index].channel_num
830 != channel) && (dt_index < vadc->max_channels_available))
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700831 dt_index++;
832
Siddartha Mohanadoss7126ce82012-12-11 14:33:11 -0800833 if (dt_index >= vadc->max_channels_available) {
Siddartha Mohanadoss1a0d2032012-11-01 11:22:29 -0700834 pr_err("not a valid VADC channel\n");
835 rc = -EINVAL;
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700836 goto fail_unlock;
Siddartha Mohanadoss1a0d2032012-11-01 11:22:29 -0700837 }
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700838
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700839 vadc->adc->amux_prop->decimation =
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700840 vadc->adc->adc_channels[dt_index].adc_decimation;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700841 vadc->adc->amux_prop->hw_settle_time =
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700842 vadc->adc->adc_channels[dt_index].hw_settle_time;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700843 vadc->adc->amux_prop->fast_avg_setup =
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700844 vadc->adc->adc_channels[dt_index].fast_avg_setup;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700845
846 if (trigger_channel < ADC_SEQ_NONE)
847 vadc->adc->amux_prop->mode_sel = (ADC_OP_CONVERSION_SEQUENCER
848 << QPNP_VADC_OP_MODE_SHIFT);
849 else if (trigger_channel == ADC_SEQ_NONE)
850 vadc->adc->amux_prop->mode_sel = (ADC_OP_NORMAL_MODE
851 << QPNP_VADC_OP_MODE_SHIFT);
852 else {
853 pr_err("Invalid trigger channel:%d\n", trigger_channel);
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700854 goto fail_unlock;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700855 }
856
857 vadc->adc->amux_prop->trigger_channel = trigger_channel;
858
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700859 rc = qpnp_vadc_configure(vadc, vadc->adc->amux_prop);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700860 if (rc) {
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700861 pr_err("qpnp vadc configure failed with %d\n", rc);
862 goto fail_unlock;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700863 }
864
Siddartha Mohanadoss1a0d2032012-11-01 11:22:29 -0700865 rc = wait_for_completion_timeout(&vadc->adc->adc_rslt_completion,
866 QPNP_ADC_COMPLETION_TIMEOUT);
867 if (!rc) {
868 u8 status1 = 0;
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700869 rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_STATUS1, &status1);
Siddartha Mohanadoss1a0d2032012-11-01 11:22:29 -0700870 if (rc < 0)
871 goto fail_unlock;
872 status1 &= (QPNP_VADC_STATUS1_REQ_STS | QPNP_VADC_STATUS1_EOC);
873 if (status1 == QPNP_VADC_STATUS1_EOC)
874 pr_debug("End of conversion status set\n");
875 else {
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700876 rc = qpnp_vadc_status_debug(vadc);
Siddartha Mohanadoss9cb2c652012-12-14 19:18:18 -0800877 if (rc < 0)
878 pr_err("VADC disable failed\n");
Siddartha Mohanadoss1a0d2032012-11-01 11:22:29 -0700879 rc = -EINVAL;
880 goto fail_unlock;
881 }
882 }
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700883
884 if (trigger_channel < ADC_SEQ_NONE) {
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700885 rc = qpnp_vadc_read_status(vadc,
886 vadc->adc->amux_prop->mode_sel);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700887 if (rc)
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700888 pr_debug("Conversion sequence timed out - %d\n", rc);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700889 }
890
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700891 rc = qpnp_vadc_read_conversion_result(vadc, &result->adc_code);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700892 if (rc) {
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700893 pr_err("qpnp vadc read adc code failed with %d\n", rc);
894 goto fail_unlock;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700895 }
896
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700897 amux_prescaling =
898 vadc->adc->adc_channels[dt_index].chan_path_prescaling;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700899
Siddartha Mohanadoss630def02013-06-27 14:53:38 -0700900 if (amux_prescaling >= PATH_SCALING_NONE) {
901 rc = -EINVAL;
902 goto fail_unlock;
903 }
904
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700905 vadc->adc->amux_prop->chan_prop->offset_gain_numerator =
906 qpnp_vadc_amux_scaling_ratio[amux_prescaling].num;
907 vadc->adc->amux_prop->chan_prop->offset_gain_denominator =
908 qpnp_vadc_amux_scaling_ratio[amux_prescaling].den;
909
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700910 scale_type = vadc->adc->adc_channels[dt_index].adc_scale_fn;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700911 if (scale_type >= SCALE_NONE) {
912 rc = -EBADF;
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700913 goto fail_unlock;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700914 }
915
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700916 vadc_scale_fn[scale_type].chan(vadc, result->adc_code,
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700917 vadc->adc->adc_prop, vadc->adc->amux_prop->chan_prop, result);
918
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700919fail_unlock:
920 mutex_unlock(&vadc->adc->adc_lock);
921
922 return rc;
923}
924EXPORT_SYMBOL(qpnp_vadc_conv_seq_request);
925
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700926int32_t qpnp_vadc_read(struct qpnp_vadc_chip *vadc,
927 enum qpnp_vadc_channels channel,
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700928 struct qpnp_vadc_result *result)
929{
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -0700930 struct qpnp_vadc_result die_temp_result;
931 int rc = 0;
932
933 if (channel == VBAT_SNS) {
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700934 rc = qpnp_vadc_conv_seq_request(vadc, ADC_SEQ_NONE,
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -0700935 channel, result);
936 if (rc < 0) {
937 pr_err("Error reading vbatt\n");
938 return rc;
939 }
940
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700941 rc = qpnp_vadc_conv_seq_request(vadc, ADC_SEQ_NONE,
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -0700942 DIE_TEMP, &die_temp_result);
943 if (rc < 0) {
944 pr_err("Error reading die_temp\n");
945 return rc;
946 }
947
948 rc = qpnp_vbat_sns_comp(&result->physical, vadc->id,
949 die_temp_result.physical);
950 if (rc < 0)
951 pr_err("Error with vbat compensation\n");
952
953 return 0;
954 } else
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700955 return qpnp_vadc_conv_seq_request(vadc, ADC_SEQ_NONE,
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700956 channel, result);
957}
Siddartha Mohanadoss271d00f2013-03-26 18:24:14 -0700958EXPORT_SYMBOL(qpnp_vadc_read);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700959
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700960static void qpnp_vadc_lock(struct qpnp_vadc_chip *vadc)
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -0800961{
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -0800962 mutex_lock(&vadc->adc->adc_lock);
963}
964
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700965static void qpnp_vadc_unlock(struct qpnp_vadc_chip *vadc)
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -0800966{
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -0800967 mutex_unlock(&vadc->adc->adc_lock);
968}
969
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700970int32_t qpnp_vadc_iadc_sync_request(struct qpnp_vadc_chip *vadc,
971 enum qpnp_vadc_channels channel)
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -0800972{
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -0800973 int rc = 0, dt_index = 0;
974
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700975 if (qpnp_vadc_is_valid(vadc))
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -0800976 return -EPROBE_DEFER;
977
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700978 qpnp_vadc_lock(vadc);
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -0800979
980 if (!vadc->vadc_init_calib) {
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700981 rc = qpnp_vadc_version_check(vadc);
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -0800982 if (rc)
983 goto fail;
984
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700985 rc = qpnp_vadc_calib_device(vadc);
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -0800986 if (rc) {
987 pr_err("Calibration failed\n");
988 goto fail;
989 } else
990 vadc->vadc_init_calib = true;
991 }
992
993 vadc->adc->amux_prop->amux_channel = channel;
994
995 while ((vadc->adc->adc_channels[dt_index].channel_num
996 != channel) && (dt_index < vadc->max_channels_available))
997 dt_index++;
998
999 if (dt_index >= vadc->max_channels_available) {
1000 pr_err("not a valid VADC channel\n");
1001 rc = -EINVAL;
1002 goto fail;
1003 }
1004
1005 vadc->adc->amux_prop->decimation =
1006 vadc->adc->adc_channels[dt_index].adc_decimation;
1007 vadc->adc->amux_prop->hw_settle_time =
1008 vadc->adc->adc_channels[dt_index].hw_settle_time;
1009 vadc->adc->amux_prop->fast_avg_setup =
1010 vadc->adc->adc_channels[dt_index].fast_avg_setup;
1011 vadc->adc->amux_prop->mode_sel = (ADC_OP_NORMAL_MODE
1012 << QPNP_VADC_OP_MODE_SHIFT);
1013 vadc->vadc_iadc_sync_lock = true;
1014
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001015 rc = qpnp_vadc_configure(vadc, vadc->adc->amux_prop);
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001016 if (rc) {
1017 pr_err("qpnp vadc configure failed with %d\n", rc);
1018 goto fail;
1019 }
1020
1021 return rc;
1022fail:
1023 vadc->vadc_iadc_sync_lock = false;
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001024 qpnp_vadc_unlock(vadc);
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001025 return rc;
1026}
1027EXPORT_SYMBOL(qpnp_vadc_iadc_sync_request);
1028
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001029int32_t qpnp_vadc_iadc_sync_complete_request(struct qpnp_vadc_chip *vadc,
1030 enum qpnp_vadc_channels channel,
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001031 struct qpnp_vadc_result *result)
1032{
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001033 int rc = 0, scale_type, amux_prescaling, dt_index = 0;
1034
1035 vadc->adc->amux_prop->amux_channel = channel;
1036
1037 while ((vadc->adc->adc_channels[dt_index].channel_num
1038 != channel) && (dt_index < vadc->max_channels_available))
1039 dt_index++;
1040
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001041 rc = qpnp_vadc_read_conversion_result(vadc, &result->adc_code);
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001042 if (rc) {
1043 pr_err("qpnp vadc read adc code failed with %d\n", rc);
1044 goto fail;
1045 }
1046
1047 amux_prescaling =
1048 vadc->adc->adc_channels[dt_index].chan_path_prescaling;
1049
Siddartha Mohanadoss630def02013-06-27 14:53:38 -07001050 if (amux_prescaling >= PATH_SCALING_NONE) {
1051 rc = -EINVAL;
1052 goto fail;
1053 }
1054
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001055 vadc->adc->amux_prop->chan_prop->offset_gain_numerator =
1056 qpnp_vadc_amux_scaling_ratio[amux_prescaling].num;
1057 vadc->adc->amux_prop->chan_prop->offset_gain_denominator =
1058 qpnp_vadc_amux_scaling_ratio[amux_prescaling].den;
1059
1060 scale_type = vadc->adc->adc_channels[dt_index].adc_scale_fn;
1061 if (scale_type >= SCALE_NONE) {
1062 rc = -EBADF;
1063 goto fail;
1064 }
1065
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001066 vadc_scale_fn[scale_type].chan(vadc, result->adc_code,
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001067 vadc->adc->adc_prop, vadc->adc->amux_prop->chan_prop, result);
1068
1069fail:
1070 vadc->vadc_iadc_sync_lock = false;
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001071 qpnp_vadc_unlock(vadc);
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001072 return rc;
1073}
1074EXPORT_SYMBOL(qpnp_vadc_iadc_sync_complete_request);
1075
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001076static ssize_t qpnp_adc_show(struct device *dev,
1077 struct device_attribute *devattr, char *buf)
1078{
1079 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001080 struct qpnp_vadc_chip *vadc = dev_get_drvdata(dev);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001081 struct qpnp_vadc_result result;
1082 int rc = -1;
1083
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001084 rc = qpnp_vadc_read(vadc, attr->index, &result);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001085
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -07001086 if (rc) {
1087 pr_err("VADC read error with %d\n", rc);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001088 return 0;
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -07001089 }
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001090
1091 return snprintf(buf, QPNP_ADC_HWMON_NAME_LENGTH,
1092 "Result:%lld Raw:%d\n", result.physical, result.adc_code);
1093}
1094
1095static struct sensor_device_attribute qpnp_adc_attr =
1096 SENSOR_ATTR(NULL, S_IRUGO, qpnp_adc_show, NULL, 0);
1097
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001098static int32_t qpnp_vadc_init_hwmon(struct qpnp_vadc_chip *vadc,
1099 struct spmi_device *spmi)
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001100{
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001101 struct device_node *child;
1102 struct device_node *node = spmi->dev.of_node;
1103 int rc = 0, i = 0, channel;
1104
1105 for_each_child_of_node(node, child) {
1106 channel = vadc->adc->adc_channels[i].channel_num;
1107 qpnp_adc_attr.index = vadc->adc->adc_channels[i].channel_num;
1108 qpnp_adc_attr.dev_attr.attr.name =
1109 vadc->adc->adc_channels[i].name;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001110 memcpy(&vadc->sens_attr[i], &qpnp_adc_attr,
1111 sizeof(qpnp_adc_attr));
Stephen Boydd7337962012-10-30 11:10:46 -07001112 sysfs_attr_init(&vadc->sens_attr[i].dev_attr.attr);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001113 rc = device_create_file(&spmi->dev,
1114 &vadc->sens_attr[i].dev_attr);
1115 if (rc) {
1116 dev_err(&spmi->dev,
1117 "device_create_file failed for dev %s\n",
1118 vadc->adc->adc_channels[i].name);
1119 goto hwmon_err_sens;
1120 }
1121 i++;
1122 }
1123
1124 return 0;
1125hwmon_err_sens:
Siddartha Mohanadossae1da732012-08-08 16:39:02 -07001126 pr_err("Init HWMON failed for qpnp_adc with %d\n", rc);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001127 return rc;
1128}
1129
1130static int __devinit qpnp_vadc_probe(struct spmi_device *spmi)
1131{
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001132 struct qpnp_vadc_chip *vadc;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001133 struct qpnp_adc_drv *adc_qpnp;
1134 struct device_node *node = spmi->dev.of_node;
1135 struct device_node *child;
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001136 int rc, count_adc_channel_list = 0, i = 0;
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -07001137 u8 fab_id = 0;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001138
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001139 for_each_child_of_node(node, child)
1140 count_adc_channel_list++;
1141
1142 if (!count_adc_channel_list) {
1143 pr_err("No channel listing\n");
1144 return -EINVAL;
1145 }
1146
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001147 vadc = devm_kzalloc(&spmi->dev, sizeof(struct qpnp_vadc_chip) +
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001148 (sizeof(struct sensor_device_attribute) *
1149 count_adc_channel_list), GFP_KERNEL);
1150 if (!vadc) {
1151 dev_err(&spmi->dev, "Unable to allocate memory\n");
1152 return -ENOMEM;
1153 }
1154
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001155 vadc->dev = &(spmi->dev);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001156 adc_qpnp = devm_kzalloc(&spmi->dev, sizeof(struct qpnp_adc_drv),
1157 GFP_KERNEL);
1158 if (!adc_qpnp) {
1159 dev_err(&spmi->dev, "Unable to allocate memory\n");
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001160 return -ENOMEM;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001161 }
1162
1163 vadc->adc = adc_qpnp;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001164 rc = qpnp_adc_get_devicetree_data(spmi, vadc->adc);
1165 if (rc) {
1166 dev_err(&spmi->dev, "failed to read device tree\n");
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001167 return rc;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001168 }
Stephen Boydbeab4502013-04-25 10:18:17 -07001169 mutex_init(&vadc->adc->adc_lock);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001170
Siddartha Mohanadoss12109952012-11-20 14:57:51 -08001171 rc = devm_request_irq(&spmi->dev, vadc->adc->adc_irq_eoc,
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001172 qpnp_vadc_isr, IRQF_TRIGGER_RISING,
1173 "qpnp_vadc_interrupt", vadc);
1174 if (rc) {
1175 dev_err(&spmi->dev,
1176 "failed to request adc irq with error %d\n", rc);
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001177 return rc;
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -07001178 } else {
Siddartha Mohanadoss12109952012-11-20 14:57:51 -08001179 enable_irq_wake(vadc->adc->adc_irq_eoc);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001180 }
1181
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001182 rc = qpnp_vadc_init_hwmon(vadc, spmi);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001183 if (rc) {
1184 dev_err(&spmi->dev, "failed to initialize qpnp hwmon adc\n");
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001185 return rc;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001186 }
1187 vadc->vadc_hwmon = hwmon_device_register(&vadc->adc->spmi->dev);
1188 vadc->vadc_init_calib = false;
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -07001189 vadc->max_channels_available = count_adc_channel_list;
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001190 rc = qpnp_vadc_read_reg(vadc, QPNP_INT_TEST_VAL, &fab_id);
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -07001191 if (rc < 0) {
1192 pr_err("qpnp adc comp id failed with %d\n", rc);
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001193 goto err_setup;
Siddartha Mohanadoss4e64f8c2013-04-08 15:57:32 -07001194 }
1195 vadc->id = fab_id;
1196
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001197 rc = qpnp_vadc_warm_rst_configure(vadc);
Siddartha Mohanadoss22559462013-05-15 15:30:28 -07001198 if (rc < 0) {
1199 pr_err("Setting perp reset on warm reset failed %d\n", rc);
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001200 goto err_setup;
Siddartha Mohanadoss22559462013-05-15 15:30:28 -07001201 }
1202
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001203 INIT_WORK(&vadc->trigger_completion_work, qpnp_vadc_work);
Siddartha Mohanadossa32ea2a2013-02-12 09:58:31 -08001204 vadc->vadc_iadc_sync_lock = false;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001205
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001206 dev_set_drvdata(&spmi->dev, vadc);
1207 list_add(&vadc->list, &qpnp_vadc_device_list);
1208
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001209 return 0;
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001210
1211err_setup:
1212 for_each_child_of_node(node, child) {
1213 device_remove_file(&spmi->dev,
1214 &vadc->sens_attr[i].dev_attr);
1215 i++;
1216 }
1217 hwmon_device_unregister(vadc->vadc_hwmon);
1218
Siddartha Mohanadossb60f6462012-11-20 18:06:51 -08001219 return rc;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001220}
1221
1222static int __devexit qpnp_vadc_remove(struct spmi_device *spmi)
1223{
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001224 struct qpnp_vadc_chip *vadc = dev_get_drvdata(&spmi->dev);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001225 struct device_node *node = spmi->dev.of_node;
1226 struct device_node *child;
1227 int i = 0;
1228
1229 for_each_child_of_node(node, child) {
1230 device_remove_file(&spmi->dev,
1231 &vadc->sens_attr[i].dev_attr);
1232 i++;
1233 }
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -07001234 hwmon_device_unregister(vadc->vadc_hwmon);
1235 list_del(&vadc->list);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001236 dev_set_drvdata(&spmi->dev, NULL);
1237
1238 return 0;
1239}
1240
1241static const struct of_device_id qpnp_vadc_match_table[] = {
1242 { .compatible = "qcom,qpnp-vadc",
1243 },
1244 {}
1245};
1246
1247static struct spmi_driver qpnp_vadc_driver = {
1248 .driver = {
1249 .name = "qcom,qpnp-vadc",
1250 .of_match_table = qpnp_vadc_match_table,
1251 },
1252 .probe = qpnp_vadc_probe,
1253 .remove = qpnp_vadc_remove,
1254};
1255
1256static int __init qpnp_vadc_init(void)
1257{
1258 return spmi_driver_register(&qpnp_vadc_driver);
1259}
1260module_init(qpnp_vadc_init);
1261
1262static void __exit qpnp_vadc_exit(void)
1263{
1264 spmi_driver_unregister(&qpnp_vadc_driver);
1265}
1266module_exit(qpnp_vadc_exit);
1267
1268MODULE_DESCRIPTION("QPNP PMIC Voltage ADC driver");
1269MODULE_LICENSE("GPL v2");