blob: 6bef3d3ce5b7b42105667e0160c5dcb20b5903b5 [file] [log] [blame]
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -07001/*
Siddartha Mohanadoss402673e2012-01-06 16:31:44 -08002 * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -07003 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * Qualcomm's PM8921/PM8018 ADC Arbiter driver
14 */
15#define pr_fmt(fmt) "%s: " fmt, __func__
16
17#include <linux/kernel.h>
18#include <linux/err.h>
19#include <linux/init.h>
20#include <linux/slab.h>
21#include <linux/delay.h>
22#include <linux/mutex.h>
23#include <linux/hwmon.h>
24#include <linux/module.h>
25#include <linux/debugfs.h>
26#include <linux/wakelock.h>
27#include <linux/interrupt.h>
28#include <linux/completion.h>
29#include <linux/hwmon-sysfs.h>
30#include <linux/mfd/pm8xxx/mpp.h>
31#include <linux/platform_device.h>
32#include <linux/mfd/pm8xxx/core.h>
33#include <linux/regulator/consumer.h>
34#include <linux/mfd/pm8xxx/pm8xxx-adc.h>
35
36/* User Bank register set */
37#define PM8XXX_ADC_ARB_USRP_CNTRL1 0x197
38#define PM8XXX_ADC_ARB_USRP_CNTRL1_EN_ARB BIT(0)
39#define PM8XXX_ADC_ARB_USRP_CNTRL1_RSV1 BIT(1)
40#define PM8XXX_ADC_ARB_USRP_CNTRL1_RSV2 BIT(2)
41#define PM8XXX_ADC_ARB_USRP_CNTRL1_RSV3 BIT(3)
42#define PM8XXX_ADC_ARB_USRP_CNTRL1_RSV4 BIT(4)
43#define PM8XXX_ADC_ARB_USRP_CNTRL1_RSV5 BIT(5)
44#define PM8XXX_ADC_ARB_USRP_CNTRL1_EOC BIT(6)
45#define PM8XXX_ADC_ARB_USRP_CNTRL1_REQ BIT(7)
46
47#define PM8XXX_ADC_ARB_USRP_AMUX_CNTRL 0x198
48#define PM8XXX_ADC_ARB_USRP_AMUX_CNTRL_RSV0 BIT(0)
49#define PM8XXX_ADC_ARB_USRP_AMUX_CNTRL_RSV1 BIT(1)
50#define PM8XXX_ADC_ARB_USRP_AMUX_CNTRL_PREMUX0 BIT(2)
51#define PM8XXX_ADC_ARB_USRP_AMUX_CNTRL_PREMUX1 BIT(3)
52#define PM8XXX_ADC_ARB_USRP_AMUX_CNTRL_SEL0 BIT(4)
53#define PM8XXX_ADC_ARB_USRP_AMUX_CNTRL_SEL1 BIT(5)
54#define PM8XXX_ADC_ARB_USRP_AMUX_CNTRL_SEL2 BIT(6)
55#define PM8XXX_ADC_ARB_USRP_AMUX_CNTRL_SEL3 BIT(7)
56
57#define PM8XXX_ADC_ARB_USRP_ANA_PARAM 0x199
58#define PM8XXX_ADC_ARB_USRP_DIG_PARAM 0x19A
59#define PM8XXX_ADC_ARB_USRP_DIG_PARAM_SEL_SHIFT0 BIT(0)
60#define PM8XXX_ADC_ARB_USRP_DIG_PARAM_SEL_SHIFT1 BIT(1)
61#define PM8XXX_ADC_ARB_USRP_DIG_PARAM_CLK_RATE0 BIT(2)
62#define PM8XXX_ADC_ARB_USRP_DIG_PARAM_CLK_RATE1 BIT(3)
63#define PM8XXX_ADC_ARB_USRP_DIG_PARAM_EOC BIT(4)
64#define PM8XXX_ADC_ARB_USRP_DIG_PARAM_DEC_RATE0 BIT(5)
65#define PM8XXX_ADC_ARB_USRP_DIG_PARAM_DEC_RATE1 BIT(6)
66#define PM8XXX_ADC_ARB_USRP_DIG_PARAM_EN BIT(7)
67
68#define PM8XXX_ADC_ARB_USRP_RSV 0x19B
69#define PM8XXX_ADC_ARB_USRP_RSV_RST BIT(0)
70#define PM8XXX_ADC_ARB_USRP_RSV_DTEST0 BIT(1)
71#define PM8XXX_ADC_ARB_USRP_RSV_DTEST1 BIT(2)
72#define PM8XXX_ADC_ARB_USRP_RSV_OP BIT(3)
73#define PM8XXX_ADC_ARB_USRP_RSV_IP_SEL0 BIT(4)
74#define PM8XXX_ADC_ARB_USRP_RSV_IP_SEL1 BIT(5)
75#define PM8XXX_ADC_ARB_USRP_RSV_IP_SEL2 BIT(6)
76#define PM8XXX_ADC_ARB_USRP_RSV_TRM BIT(7)
77
78#define PM8XXX_ADC_ARB_USRP_DATA0 0x19D
79#define PM8XXX_ADC_ARB_USRP_DATA1 0x19C
80
81#define PM8XXX_ADC_ARB_BTM_CNTRL1 0x17e
82#define PM8XXX_ADC_ARB_BTM_CNTRL1_EN_BTM BIT(0)
83#define PM8XXX_ADC_ARB_BTM_CNTRL1_SEL_OP_MODE BIT(1)
84#define PM8XXX_ADC_ARB_BTM_CNTRL1_MEAS_INTERVAL1 BIT(2)
85#define PM8XXX_ADC_ARB_BTM_CNTRL1_MEAS_INTERVAL2 BIT(3)
86#define PM8XXX_ADC_ARB_BTM_CNTRL1_MEAS_INTERVAL3 BIT(4)
87#define PM8XXX_ADC_ARB_BTM_CNTRL1_MEAS_INTERVAL4 BIT(5)
88#define PM8XXX_ADC_ARB_BTM_CNTRL1_EOC BIT(6)
89#define PM8XXX_ADC_ARB_BTM_CNTRL1_REQ BIT(7)
90
91#define PM8XXX_ADC_ARB_BTM_CNTRL2 0x18c
92#define PM8XXX_ADC_ARB_BTM_AMUX_CNTRL 0x17f
93#define PM8XXX_ADC_ARB_BTM_ANA_PARAM 0x180
94#define PM8XXX_ADC_ARB_BTM_DIG_PARAM 0x181
95#define PM8XXX_ADC_ARB_BTM_RSV 0x182
96#define PM8XXX_ADC_ARB_BTM_DATA1 0x183
97#define PM8XXX_ADC_ARB_BTM_DATA0 0x184
98#define PM8XXX_ADC_ARB_BTM_BAT_COOL_THR1 0x185
99#define PM8XXX_ADC_ARB_BTM_BAT_COOL_THR0 0x186
100#define PM8XXX_ADC_ARB_BTM_BAT_WARM_THR1 0x187
101#define PM8XXX_ADC_ARB_BTM_BAT_WARM_THR0 0x188
102
103#define PM8XXX_ADC_ARB_ANA_DIG 0xa0
104#define PM8XXX_ADC_BTM_RSV 0x10
105#define PM8XXX_ADC_AMUX_MPP_SEL 2
106#define PM8XXX_ADC_AMUX_SEL 4
107#define PM8XXX_ADC_RSV_IP_SEL 4
108#define PM8XXX_ADC_BTM_CHANNEL_SEL 4
109#define PM8XXX_MAX_CHANNEL_PROPERTIES 2
110#define PM8XXX_ADC_IRQ_0 0
111#define PM8XXX_ADC_IRQ_1 1
112#define PM8XXX_ADC_IRQ_2 2
113#define PM8XXX_ADC_BTM_INTERVAL_SEL_MASK 0xF
114#define PM8XXX_ADC_BTM_INTERVAL_SEL_SHIFT 2
115#define PM8XXX_ADC_BTM_DECIMATION_SEL 5
116#define PM8XXX_ADC_MUL 10
117#define PM8XXX_ADC_CONV_TIME_MIN 2000
118#define PM8XXX_ADC_CONV_TIME_MAX 2100
119#define PM8XXX_ADC_MPP_SETTLE_TIME_MIN 200
120#define PM8XXX_ADC_MPP_SETTLE_TIME_MAX 200
121#define PM8XXX_ADC_PA_THERM_VREG_UV_MIN 1800000
122#define PM8XXX_ADC_PA_THERM_VREG_UV_MAX 1800000
123#define PM8XXX_ADC_PA_THERM_VREG_UA_LOAD 100000
Siddartha Mohanadossae39c902011-11-09 17:54:31 -0800124#define PM8XXX_ADC_HWMON_NAME_LENGTH 32
Siddartha Mohanadoss68ceac12011-12-09 16:04:41 -0800125#define PM8XXX_ADC_BTM_INTERVAL_MAX 0x14
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700126
127struct pm8xxx_adc {
128 struct device *dev;
129 struct pm8xxx_adc_properties *adc_prop;
130 int adc_irq;
131 struct mutex adc_lock;
132 struct mutex mpp_adc_lock;
133 spinlock_t btm_lock;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700134 uint32_t adc_num_board_channel;
135 struct completion adc_rslt_completion;
136 struct pm8xxx_adc_amux *adc_channel;
137 int btm_warm_irq;
138 int btm_cool_irq;
139 struct dentry *dent;
140 struct work_struct warm_work;
141 struct work_struct cool_work;
142 uint32_t mpp_base;
143 struct device *hwmon;
144 struct wake_lock adc_wakelock;
145 int msm_suspend_check;
146 struct pm8xxx_adc_amux_properties *conv;
Siddartha Mohanadoss402673e2012-01-06 16:31:44 -0800147 struct pm8xxx_adc_arb_btm_param batt;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700148 struct sensor_device_attribute sens_attr[0];
149};
150
151struct pm8xxx_adc_amux_properties {
152 uint32_t amux_channel;
153 uint32_t decimation;
154 uint32_t amux_ip_rsv;
155 uint32_t amux_mpp_channel;
156 struct pm8xxx_adc_chan_properties chan_prop[0];
157};
158
159static const struct pm8xxx_adc_scaling_ratio pm8xxx_amux_scaling_ratio[] = {
160 {1, 1},
161 {1, 3},
162 {1, 4},
163 {1, 6}
164};
165
166static struct pm8xxx_adc *pmic_adc;
Siddartha Mohanadoss2c546d32012-02-21 23:01:08 -0800167static struct regulator *pa_therm;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700168
169static struct pm8xxx_adc_scale_fn adc_scale_fn[] = {
170 [ADC_SCALE_DEFAULT] = {pm8xxx_adc_scale_default},
171 [ADC_SCALE_BATT_THERM] = {pm8xxx_adc_scale_batt_therm},
172 [ADC_SCALE_PA_THERM] = {pm8xxx_adc_scale_pa_therm},
173 [ADC_SCALE_PMIC_THERM] = {pm8xxx_adc_scale_pmic_therm},
174 [ADC_SCALE_XOTHERM] = {pm8xxx_adc_tdkntcg_therm},
175};
176
177/* On PM8921 ADC the MPP needs to first be configured
178as an analog input to the AMUX pre-mux channel before
179issuing a read request. PM8921 MPP 8 is mapped to AMUX8
180and is common between remote processor's.
181On PM8018 ADC the MPP is directly connected to the AMUX
182pre-mux. Therefore clients of the PM8018 MPP do not need
183to configure the MPP as an analog input to the pre-mux.
184Clients can directly issue request on the pre-mux AMUX
185channel to read the ADC on the MPP */
186static struct pm8xxx_mpp_config_data pm8xxx_adc_mpp_config = {
187 .type = PM8XXX_MPP_TYPE_A_INPUT,
188 /* AMUX6 is dedicated to be used for apps processor */
189 .level = PM8XXX_MPP_AIN_AMUX_CH6,
190 .control = PM8XXX_MPP_AOUT_CTRL_DISABLE,
191};
192
193/* MPP Configuration for default settings */
194static struct pm8xxx_mpp_config_data pm8xxx_adc_mpp_unconfig = {
195 .type = PM8XXX_MPP_TYPE_SINK,
196 .level = PM8XXX_MPP_AIN_AMUX_CH5,
197 .control = PM8XXX_MPP_AOUT_CTRL_DISABLE,
198};
199
200static bool pm8xxx_adc_calib_first_adc;
201static bool pm8xxx_adc_initialized, pm8xxx_adc_calib_device_init;
202
Siddartha Mohanadosscb6d3002012-03-15 10:44:11 -0700203static int32_t pm8xxx_adc_check_channel_valid(uint32_t channel)
204{
205 if (channel < CHANNEL_VCOIN ||
206 (channel > CHANNEL_MUXOFF && channel < ADC_MPP_1_ATEST_8) ||
207 (channel > ADC_MPP_1_ATEST_7 && channel < ADC_MPP_2_ATEST_8)
208 || (channel >= ADC_CHANNEL_MAX_NUM))
209 return -EBADF;
210 else
211 return 0;
212}
213
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700214static int32_t pm8xxx_adc_arb_cntrl(uint32_t arb_cntrl,
215 uint32_t channel)
216{
217 struct pm8xxx_adc *adc_pmic = pmic_adc;
218 int i, rc;
219 u8 data_arb_cntrl = 0;
220
221 if (arb_cntrl) {
222 if (adc_pmic->msm_suspend_check)
223 pr_err("PM8xxx ADC request made after suspend_noirq "
224 "with channel: %d\n", channel);
225 data_arb_cntrl |= PM8XXX_ADC_ARB_USRP_CNTRL1_EN_ARB;
226 wake_lock(&adc_pmic->adc_wakelock);
227 }
228
229 /* Write twice to the CNTRL register for the arbiter settings
230 to take into effect */
231 for (i = 0; i < 2; i++) {
232 rc = pm8xxx_writeb(adc_pmic->dev->parent,
233 PM8XXX_ADC_ARB_USRP_CNTRL1, data_arb_cntrl);
234 if (rc < 0) {
235 pr_err("PM8xxx arb cntrl write failed with %d\n", rc);
236 return rc;
237 }
238 }
239
240 if (arb_cntrl) {
241 data_arb_cntrl |= PM8XXX_ADC_ARB_USRP_CNTRL1_REQ;
Abhijeet Dharmapurikarf5285a22012-04-10 23:42:45 -0700242 INIT_COMPLETION(adc_pmic->adc_rslt_completion);
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700243 rc = pm8xxx_writeb(adc_pmic->dev->parent,
244 PM8XXX_ADC_ARB_USRP_CNTRL1, data_arb_cntrl);
245 } else
246 wake_unlock(&adc_pmic->adc_wakelock);
247
248 return 0;
249}
250
251static int32_t pm8xxx_adc_patherm_power(bool on)
252{
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700253 int rc = 0;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700254
Siddartha Mohanadoss2c546d32012-02-21 23:01:08 -0800255 if (!pa_therm) {
256 pr_err("pm8xxx adc pa_therm not valid\n");
257 return -EINVAL;
258 }
259
260 if (on) {
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700261 rc = regulator_set_voltage(pa_therm,
262 PM8XXX_ADC_PA_THERM_VREG_UV_MIN,
263 PM8XXX_ADC_PA_THERM_VREG_UV_MAX);
264 if (rc < 0) {
265 pr_err("failed to set the voltage for "
266 "pa_therm with error %d\n", rc);
Siddartha Mohanadoss2c546d32012-02-21 23:01:08 -0800267 return rc;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700268 }
269
270 rc = regulator_set_optimum_mode(pa_therm,
271 PM8XXX_ADC_PA_THERM_VREG_UA_LOAD);
272 if (rc < 0) {
273 pr_err("failed to set optimum mode for "
274 "pa_therm with error %d\n", rc);
Siddartha Mohanadoss2c546d32012-02-21 23:01:08 -0800275 return rc;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700276 }
277
Siddartha Mohanadoss2c546d32012-02-21 23:01:08 -0800278 rc = regulator_enable(pa_therm);
279 if (rc < 0) {
280 pr_err("failed to enable pa_therm vreg "
281 "with error %d\n", rc);
282 return rc;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700283 }
284 } else {
Siddartha Mohanadoss2c546d32012-02-21 23:01:08 -0800285 rc = regulator_disable(pa_therm);
286 if (rc < 0) {
287 pr_err("failed to disable pa_therm vreg "
288 "with error %d\n", rc);
289 return rc;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700290 }
291 }
292
293 return rc;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700294}
295
296static int32_t pm8xxx_adc_channel_power_enable(uint32_t channel,
297 bool power_cntrl)
298{
299 int rc = 0;
300
301 switch (channel)
302 case ADC_MPP_1_AMUX8:
Siddartha Mohanadoss2c546d32012-02-21 23:01:08 -0800303 rc = pm8xxx_adc_patherm_power(power_cntrl);
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700304
305 return rc;
306}
307
308
309static uint32_t pm8xxx_adc_read_reg(uint32_t reg, u8 *data)
310{
311 struct pm8xxx_adc *adc_pmic = pmic_adc;
312 int rc;
313
314 rc = pm8xxx_readb(adc_pmic->dev->parent, reg, data);
315 if (rc < 0) {
316 pr_err("PM8xxx adc read reg %d failed with %d\n", reg, rc);
317 return rc;
318 }
319
320 return 0;
321}
322
323static uint32_t pm8xxx_adc_write_reg(uint32_t reg, u8 data)
324{
325 struct pm8xxx_adc *adc_pmic = pmic_adc;
326 int rc;
327
328 rc = pm8xxx_writeb(adc_pmic->dev->parent, reg, data);
329 if (rc < 0) {
330 pr_err("PM8xxx adc write reg %d failed with %d\n", reg, rc);
331 return rc;
332 }
333
334 return 0;
335}
336
337static int32_t pm8xxx_adc_configure(
338 struct pm8xxx_adc_amux_properties *chan_prop)
339{
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700340 u8 data_amux_chan = 0, data_arb_rsv = 0, data_dig_param = 0;
341 int rc;
342
343 data_amux_chan |= chan_prop->amux_channel << PM8XXX_ADC_AMUX_SEL;
344
345 if (chan_prop->amux_mpp_channel)
346 data_amux_chan |= chan_prop->amux_mpp_channel <<
347 PM8XXX_ADC_AMUX_MPP_SEL;
348
349 rc = pm8xxx_adc_write_reg(PM8XXX_ADC_ARB_USRP_AMUX_CNTRL,
350 data_amux_chan);
351 if (rc < 0)
352 return rc;
353
Siddartha Mohanadoss866fe9f2011-12-13 23:01:40 -0800354 rc = pm8xxx_adc_read_reg(PM8XXX_ADC_ARB_USRP_RSV, &data_arb_rsv);
355 if (rc < 0)
356 return rc;
357
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700358 data_arb_rsv &= (PM8XXX_ADC_ARB_USRP_RSV_RST |
359 PM8XXX_ADC_ARB_USRP_RSV_DTEST0 |
360 PM8XXX_ADC_ARB_USRP_RSV_DTEST1 |
Siddartha Mohanadoss866fe9f2011-12-13 23:01:40 -0800361 PM8XXX_ADC_ARB_USRP_RSV_OP);
362 data_arb_rsv |= (chan_prop->amux_ip_rsv << PM8XXX_ADC_RSV_IP_SEL |
363 PM8XXX_ADC_ARB_USRP_RSV_TRM);
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700364
365 rc = pm8xxx_adc_write_reg(PM8XXX_ADC_ARB_USRP_RSV, data_arb_rsv);
366 if (rc < 0)
367 return rc;
368
369 rc = pm8xxx_adc_read_reg(PM8XXX_ADC_ARB_USRP_DIG_PARAM,
370 &data_dig_param);
371 if (rc < 0)
372 return rc;
373
374 /* Default 2.4Mhz clock rate */
375 /* Client chooses the decimation */
376 switch (chan_prop->decimation) {
377 case ADC_DECIMATION_TYPE1:
378 data_dig_param |= PM8XXX_ADC_ARB_USRP_DIG_PARAM_DEC_RATE0;
379 break;
380 case ADC_DECIMATION_TYPE2:
381 data_dig_param |= (PM8XXX_ADC_ARB_USRP_DIG_PARAM_DEC_RATE0
382 | PM8XXX_ADC_ARB_USRP_DIG_PARAM_DEC_RATE1);
383 break;
384 default:
385 data_dig_param |= PM8XXX_ADC_ARB_USRP_DIG_PARAM_DEC_RATE0;
386 break;
387 }
388 rc = pm8xxx_adc_write_reg(PM8XXX_ADC_ARB_USRP_DIG_PARAM,
389 PM8XXX_ADC_ARB_ANA_DIG);
390 if (rc < 0)
391 return rc;
392
393 rc = pm8xxx_adc_write_reg(PM8XXX_ADC_ARB_USRP_ANA_PARAM,
394 PM8XXX_ADC_ARB_ANA_DIG);
395 if (rc < 0)
396 return rc;
397
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700398 rc = pm8xxx_adc_arb_cntrl(1, data_amux_chan);
399 if (rc < 0) {
400 pr_err("Configuring ADC Arbiter"
401 "enable failed with %d\n", rc);
402 return rc;
403 }
404
405 return 0;
406}
407
408static uint32_t pm8xxx_adc_read_adc_code(int32_t *data)
409{
410 struct pm8xxx_adc *adc_pmic = pmic_adc;
411 uint8_t rslt_lsb, rslt_msb;
412 int32_t rc, max_ideal_adc_code = 1 << adc_pmic->adc_prop->bitresolution;
413
414 rc = pm8xxx_readb(adc_pmic->dev->parent,
415 PM8XXX_ADC_ARB_USRP_DATA0, &rslt_lsb);
416 if (rc < 0) {
417 pr_err("PM8xxx adc result read failed with %d\n", rc);
418 return rc;
419 }
420
421 rc = pm8xxx_readb(adc_pmic->dev->parent,
422 PM8XXX_ADC_ARB_USRP_DATA1, &rslt_msb);
423 if (rc < 0) {
424 pr_err("PM8xxx adc result read failed with %d\n", rc);
425 return rc;
426 }
427
428 *data = (rslt_msb << 8) | rslt_lsb;
429
430 /* Use the midpoint to determine underflow or overflow */
431 if (*data > max_ideal_adc_code + (max_ideal_adc_code >> 1))
432 *data |= ((1 << (8 * sizeof(*data) -
433 adc_pmic->adc_prop->bitresolution)) - 1) <<
434 adc_pmic->adc_prop->bitresolution;
435
436 /* Default value for switching off the arbiter after reading
437 the ADC value. Bit 0 set to 0. */
438 rc = pm8xxx_adc_arb_cntrl(0, CHANNEL_NONE);
439 if (rc < 0) {
440 pr_err("%s: Configuring ADC Arbiter disable"
441 "failed\n", __func__);
442 return rc;
443 }
444
445 return 0;
446}
447
448static void pm8xxx_adc_btm_warm_scheduler_fn(struct work_struct *work)
449{
450 struct pm8xxx_adc *adc_pmic = container_of(work, struct pm8xxx_adc,
451 warm_work);
452 unsigned long flags = 0;
453 bool warm_status;
454
455 spin_lock_irqsave(&adc_pmic->btm_lock, flags);
456 warm_status = irq_read_line(adc_pmic->btm_warm_irq);
Siddartha Mohanadoss402673e2012-01-06 16:31:44 -0800457 if (adc_pmic->batt.btm_warm_fn != NULL)
458 adc_pmic->batt.btm_warm_fn(warm_status);
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700459 spin_unlock_irqrestore(&adc_pmic->btm_lock, flags);
460}
461
462static void pm8xxx_adc_btm_cool_scheduler_fn(struct work_struct *work)
463{
464 struct pm8xxx_adc *adc_pmic = container_of(work, struct pm8xxx_adc,
465 cool_work);
466 unsigned long flags = 0;
467 bool cool_status;
468
469 spin_lock_irqsave(&adc_pmic->btm_lock, flags);
470 cool_status = irq_read_line(adc_pmic->btm_cool_irq);
Siddartha Mohanadoss402673e2012-01-06 16:31:44 -0800471 if (adc_pmic->batt.btm_cool_fn != NULL)
472 adc_pmic->batt.btm_cool_fn(cool_status);
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700473 spin_unlock_irqrestore(&adc_pmic->btm_lock, flags);
474}
475
Abhijeet Dharmapurikarf5285a22012-04-10 23:42:45 -0700476void trigger_completion(struct work_struct *work)
477{
478 struct pm8xxx_adc *adc_8xxx = pmic_adc;
479
480 complete(&adc_8xxx->adc_rslt_completion);
481}
482DECLARE_WORK(trigger_completion_work, trigger_completion);
483
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700484static irqreturn_t pm8xxx_adc_isr(int irq, void *dev_id)
485{
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700486
487 if (pm8xxx_adc_calib_first_adc)
488 return IRQ_HANDLED;
Abhijeet Dharmapurikarf5285a22012-04-10 23:42:45 -0700489
490 schedule_work(&trigger_completion_work);
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700491
492 return IRQ_HANDLED;
493}
494
495static irqreturn_t pm8xxx_btm_warm_isr(int irq, void *dev_id)
496{
497 struct pm8xxx_adc *btm_8xxx = dev_id;
498
499 schedule_work(&btm_8xxx->warm_work);
500
501 return IRQ_HANDLED;
502}
503
504static irqreturn_t pm8xxx_btm_cool_isr(int irq, void *dev_id)
505{
506 struct pm8xxx_adc *btm_8xxx = dev_id;
507
508 schedule_work(&btm_8xxx->cool_work);
509
510 return IRQ_HANDLED;
511}
512
513static uint32_t pm8xxx_adc_calib_device(void)
514{
515 struct pm8xxx_adc *adc_pmic = pmic_adc;
516 struct pm8xxx_adc_amux_properties conv;
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800517 int rc, calib_read_1, calib_read_2;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700518 u8 data_arb_usrp_cntrl1 = 0;
519
520 conv.amux_channel = CHANNEL_125V;
521 conv.decimation = ADC_DECIMATION_TYPE2;
522 conv.amux_ip_rsv = AMUX_RSV1;
523 conv.amux_mpp_channel = PREMUX_MPP_SCALE_0;
524 pm8xxx_adc_calib_first_adc = true;
525 rc = pm8xxx_adc_configure(&conv);
526 if (rc) {
527 pr_err("pm8xxx_adc configure failed with %d\n", rc);
528 goto calib_fail;
529 }
530
531 while (data_arb_usrp_cntrl1 != (PM8XXX_ADC_ARB_USRP_CNTRL1_EOC |
532 PM8XXX_ADC_ARB_USRP_CNTRL1_EN_ARB)) {
533 rc = pm8xxx_adc_read_reg(PM8XXX_ADC_ARB_USRP_CNTRL1,
534 &data_arb_usrp_cntrl1);
535 if (rc < 0)
536 return rc;
537 usleep_range(PM8XXX_ADC_CONV_TIME_MIN,
538 PM8XXX_ADC_CONV_TIME_MAX);
539 }
540 data_arb_usrp_cntrl1 = 0;
541
542 rc = pm8xxx_adc_read_adc_code(&calib_read_1);
543 if (rc) {
544 pr_err("pm8xxx_adc read adc failed with %d\n", rc);
545 pm8xxx_adc_calib_first_adc = false;
546 goto calib_fail;
547 }
548 pm8xxx_adc_calib_first_adc = false;
549
550 conv.amux_channel = CHANNEL_625MV;
551 conv.decimation = ADC_DECIMATION_TYPE2;
552 conv.amux_ip_rsv = AMUX_RSV1;
553 conv.amux_mpp_channel = PREMUX_MPP_SCALE_0;
554 pm8xxx_adc_calib_first_adc = true;
555 rc = pm8xxx_adc_configure(&conv);
556 if (rc) {
557 pr_err("pm8xxx_adc configure failed with %d\n", rc);
558 goto calib_fail;
559 }
560
561 while (data_arb_usrp_cntrl1 != (PM8XXX_ADC_ARB_USRP_CNTRL1_EOC |
562 PM8XXX_ADC_ARB_USRP_CNTRL1_EN_ARB)) {
563 rc = pm8xxx_adc_read_reg(PM8XXX_ADC_ARB_USRP_CNTRL1,
564 &data_arb_usrp_cntrl1);
565 if (rc < 0)
566 return rc;
567 usleep_range(PM8XXX_ADC_CONV_TIME_MIN,
568 PM8XXX_ADC_CONV_TIME_MAX);
569 }
570 data_arb_usrp_cntrl1 = 0;
571
572 rc = pm8xxx_adc_read_adc_code(&calib_read_2);
573 if (rc) {
574 pr_err("pm8xxx_adc read adc failed with %d\n", rc);
575 pm8xxx_adc_calib_first_adc = false;
576 goto calib_fail;
577 }
578 pm8xxx_adc_calib_first_adc = false;
579
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700580 adc_pmic->conv->chan_prop->adc_graph[ADC_CALIB_ABSOLUTE].dy =
581 (calib_read_1 - calib_read_2);
582 adc_pmic->conv->chan_prop->adc_graph[ADC_CALIB_ABSOLUTE].dx
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800583 = PM8XXX_CHANNEL_ADC_625_UV;
584 adc_pmic->conv->chan_prop->adc_graph[ADC_CALIB_ABSOLUTE].adc_vref =
585 calib_read_1;
586 adc_pmic->conv->chan_prop->adc_graph[ADC_CALIB_ABSOLUTE].adc_gnd =
587 calib_read_2;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700588 rc = pm8xxx_adc_arb_cntrl(0, CHANNEL_NONE);
589 if (rc < 0) {
590 pr_err("%s: Configuring ADC Arbiter disable"
591 "failed\n", __func__);
592 return rc;
593 }
594 /* Ratiometric Calibration */
595 conv.amux_channel = CHANNEL_MUXOFF;
596 conv.decimation = ADC_DECIMATION_TYPE2;
597 conv.amux_ip_rsv = AMUX_RSV5;
598 conv.amux_mpp_channel = PREMUX_MPP_SCALE_0;
599 pm8xxx_adc_calib_first_adc = true;
600 rc = pm8xxx_adc_configure(&conv);
601 if (rc) {
602 pr_err("pm8xxx_adc configure failed with %d\n", rc);
603 goto calib_fail;
604 }
605
606 while (data_arb_usrp_cntrl1 != (PM8XXX_ADC_ARB_USRP_CNTRL1_EOC |
607 PM8XXX_ADC_ARB_USRP_CNTRL1_EN_ARB)) {
608 rc = pm8xxx_adc_read_reg(PM8XXX_ADC_ARB_USRP_CNTRL1,
609 &data_arb_usrp_cntrl1);
610 if (rc < 0)
611 return rc;
612 usleep_range(PM8XXX_ADC_CONV_TIME_MIN,
613 PM8XXX_ADC_CONV_TIME_MAX);
614 }
615 data_arb_usrp_cntrl1 = 0;
616
617 rc = pm8xxx_adc_read_adc_code(&calib_read_1);
618 if (rc) {
619 pr_err("pm8xxx_adc read adc failed with %d\n", rc);
620 pm8xxx_adc_calib_first_adc = false;
621 goto calib_fail;
622 }
623 pm8xxx_adc_calib_first_adc = false;
624
625 conv.amux_channel = CHANNEL_MUXOFF;
626 conv.decimation = ADC_DECIMATION_TYPE2;
627 conv.amux_ip_rsv = AMUX_RSV4;
628 conv.amux_mpp_channel = PREMUX_MPP_SCALE_0;
629 pm8xxx_adc_calib_first_adc = true;
630 rc = pm8xxx_adc_configure(&conv);
631 if (rc) {
632 pr_err("pm8xxx_adc configure failed with %d\n", rc);
633 goto calib_fail;
634 }
635
636 while (data_arb_usrp_cntrl1 != (PM8XXX_ADC_ARB_USRP_CNTRL1_EOC |
637 PM8XXX_ADC_ARB_USRP_CNTRL1_EN_ARB)) {
638 rc = pm8xxx_adc_read_reg(PM8XXX_ADC_ARB_USRP_CNTRL1,
639 &data_arb_usrp_cntrl1);
640 if (rc < 0)
641 return rc;
642 usleep_range(PM8XXX_ADC_CONV_TIME_MIN,
643 PM8XXX_ADC_CONV_TIME_MAX);
644 }
645 data_arb_usrp_cntrl1 = 0;
646
647 rc = pm8xxx_adc_read_adc_code(&calib_read_2);
648 if (rc) {
649 pr_err("pm8xxx_adc read adc failed with %d\n", rc);
650 pm8xxx_adc_calib_first_adc = false;
651 goto calib_fail;
652 }
653 pm8xxx_adc_calib_first_adc = false;
654
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700655 adc_pmic->conv->chan_prop->adc_graph[ADC_CALIB_RATIOMETRIC].dy =
656 (calib_read_1 - calib_read_2);
657 adc_pmic->conv->chan_prop->adc_graph[ADC_CALIB_RATIOMETRIC].dx =
658 adc_pmic->adc_prop->adc_vdd_reference;
Siddartha Mohanadossae39c902011-11-09 17:54:31 -0800659 adc_pmic->conv->chan_prop->adc_graph[ADC_CALIB_RATIOMETRIC].adc_vref =
660 calib_read_1;
661 adc_pmic->conv->chan_prop->adc_graph[ADC_CALIB_RATIOMETRIC].adc_gnd =
662 calib_read_2;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700663calib_fail:
664 rc = pm8xxx_adc_arb_cntrl(0, CHANNEL_NONE);
665 if (rc < 0) {
666 pr_err("%s: Configuring ADC Arbiter disable"
667 "failed\n", __func__);
668 }
669
670 return rc;
671}
672
673uint32_t pm8xxx_adc_read(enum pm8xxx_adc_channels channel,
674 struct pm8xxx_adc_chan_result *result)
675{
676 struct pm8xxx_adc *adc_pmic = pmic_adc;
677 int i = 0, rc = 0, rc_fail, amux_prescaling, scale_type;
678 enum pm8xxx_adc_premux_mpp_scale_type mpp_scale;
679
680 if (!pm8xxx_adc_initialized)
681 return -ENODEV;
682
683 if (!pm8xxx_adc_calib_device_init) {
684 if (pm8xxx_adc_calib_device() == 0)
685 pm8xxx_adc_calib_device_init = true;
686 }
687
688 mutex_lock(&adc_pmic->adc_lock);
689
Siddartha Mohanadosscb6d3002012-03-15 10:44:11 -0700690 for (i = 0; i < adc_pmic->adc_num_board_channel; i++) {
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700691 if (channel == adc_pmic->adc_channel[i].channel_name)
692 break;
693 }
694
Siddartha Mohanadosscb6d3002012-03-15 10:44:11 -0700695 if (i == adc_pmic->adc_num_board_channel ||
696 (pm8xxx_adc_check_channel_valid(channel) != 0)) {
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700697 rc = -EBADF;
698 goto fail_unlock;
699 }
700
701 if (channel < PM8XXX_CHANNEL_MPP_SCALE1_IDX) {
702 mpp_scale = PREMUX_MPP_SCALE_0;
703 adc_pmic->conv->amux_channel = channel;
Siddartha Mohanadossae39c902011-11-09 17:54:31 -0800704 } else if (channel >= PM8XXX_CHANNEL_MPP_SCALE1_IDX &&
705 channel < PM8XXX_CHANNEL_MPP_SCALE3_IDX) {
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700706 mpp_scale = PREMUX_MPP_SCALE_1;
707 adc_pmic->conv->amux_channel = channel %
708 PM8XXX_CHANNEL_MPP_SCALE1_IDX;
Siddartha Mohanadossae39c902011-11-09 17:54:31 -0800709 } else {
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700710 mpp_scale = PREMUX_MPP_SCALE_1_DIV3;
711 adc_pmic->conv->amux_channel = channel %
712 PM8XXX_CHANNEL_MPP_SCALE3_IDX;
713 }
714
715 adc_pmic->conv->amux_mpp_channel = mpp_scale;
716 adc_pmic->conv->amux_ip_rsv = adc_pmic->adc_channel[i].adc_rsv;
717 adc_pmic->conv->decimation = adc_pmic->adc_channel[i].adc_decimation;
718 amux_prescaling = adc_pmic->adc_channel[i].chan_path_prescaling;
719
720 adc_pmic->conv->chan_prop->offset_gain_numerator =
721 pm8xxx_amux_scaling_ratio[amux_prescaling].num;
722 adc_pmic->conv->chan_prop->offset_gain_denominator =
723 pm8xxx_amux_scaling_ratio[amux_prescaling].den;
724
725 rc = pm8xxx_adc_channel_power_enable(channel, true);
726 if (rc) {
727 rc = -EINVAL;
728 goto fail_unlock;
729 }
730
731 rc = pm8xxx_adc_configure(adc_pmic->conv);
732 if (rc) {
733 rc = -EINVAL;
734 goto fail;
735 }
736
737 wait_for_completion(&adc_pmic->adc_rslt_completion);
738
739 rc = pm8xxx_adc_read_adc_code(&result->adc_code);
740 if (rc) {
741 rc = -EINVAL;
742 goto fail;
743 }
744
745 scale_type = adc_pmic->adc_channel[i].adc_scale_fn;
746 if (scale_type >= ADC_SCALE_NONE) {
747 rc = -EBADF;
748 goto fail;
749 }
750
751 adc_scale_fn[scale_type].chan(result->adc_code,
752 adc_pmic->adc_prop, adc_pmic->conv->chan_prop, result);
753
754 rc = pm8xxx_adc_channel_power_enable(channel, false);
755 if (rc) {
756 rc = -EINVAL;
757 goto fail_unlock;
758 }
759
760 mutex_unlock(&adc_pmic->adc_lock);
761
762 return 0;
763fail:
764 rc_fail = pm8xxx_adc_channel_power_enable(channel, false);
765 if (rc_fail)
766 pr_err("pm8xxx adc power disable failed\n");
767fail_unlock:
768 mutex_unlock(&adc_pmic->adc_lock);
769 pr_err("pm8xxx adc error with %d\n", rc);
770 return rc;
771}
772EXPORT_SYMBOL_GPL(pm8xxx_adc_read);
773
774uint32_t pm8xxx_adc_mpp_config_read(uint32_t mpp_num,
775 enum pm8xxx_adc_channels channel,
776 struct pm8xxx_adc_chan_result *result)
777{
778 struct pm8xxx_adc *adc_pmic = pmic_adc;
779 int rc = 0;
780
Siddartha Mohanadoss2c546d32012-02-21 23:01:08 -0800781 if (!pm8xxx_adc_initialized)
782 return -ENODEV;
783
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700784 if (!adc_pmic->mpp_base) {
785 rc = -EINVAL;
786 pr_info("PM8xxx MPP base invalid with error %d\n", rc);
787 return rc;
788 }
789
790 if (mpp_num == PM8XXX_AMUX_MPP_8) {
791 rc = -EINVAL;
792 pr_info("PM8xxx MPP8 is already configured "
793 "to AMUX8. Use pm8xxx_adc_read() instead.\n");
794 return rc;
795 }
796
797 mutex_lock(&adc_pmic->mpp_adc_lock);
798
799 rc = pm8xxx_mpp_config(((mpp_num - 1) + adc_pmic->mpp_base),
800 &pm8xxx_adc_mpp_config);
801 if (rc < 0) {
802 pr_err("pm8xxx adc mpp config error with %d\n", rc);
803 goto fail;
804 }
805
806 usleep_range(PM8XXX_ADC_MPP_SETTLE_TIME_MIN,
807 PM8XXX_ADC_MPP_SETTLE_TIME_MAX);
808
809 rc = pm8xxx_adc_read(channel, result);
810 if (rc < 0)
811 pr_err("pm8xxx adc read error with %d\n", rc);
812
813 rc = pm8xxx_mpp_config(((mpp_num - 1) + adc_pmic->mpp_base),
814 &pm8xxx_adc_mpp_unconfig);
815 if (rc < 0)
816 pr_err("pm8xxx adc mpp config error with %d\n", rc);
817fail:
818 mutex_unlock(&adc_pmic->mpp_adc_lock);
819
820 return rc;
821}
822EXPORT_SYMBOL_GPL(pm8xxx_adc_mpp_config_read);
823
824uint32_t pm8xxx_adc_btm_configure(struct pm8xxx_adc_arb_btm_param *btm_param)
825{
826 struct pm8xxx_adc *adc_pmic = pmic_adc;
827 u8 data_btm_cool_thr0, data_btm_cool_thr1;
828 u8 data_btm_warm_thr0, data_btm_warm_thr1;
829 u8 arb_btm_cntrl1;
830 unsigned long flags = 0;
831 int rc;
832
833 if (adc_pmic == NULL) {
834 pr_err("PMIC ADC not valid\n");
835 return -EINVAL;
836 }
837
838 if ((btm_param->btm_cool_fn == NULL) &&
839 (btm_param->btm_warm_fn == NULL)) {
840 pr_err("No BTM warm/cool notification??\n");
841 return -EINVAL;
842 }
843
Siddartha Mohanadossae39c902011-11-09 17:54:31 -0800844 rc = pm8xxx_adc_batt_scaler(btm_param, adc_pmic->adc_prop,
845 adc_pmic->conv->chan_prop);
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700846 if (rc < 0) {
847 pr_err("Failed to lookup the BTM thresholds\n");
848 return rc;
849 }
850
Siddartha Mohanadoss68ceac12011-12-09 16:04:41 -0800851 if (btm_param->interval > PM8XXX_ADC_BTM_INTERVAL_MAX) {
852 pr_info("Bug in PMIC BTM interval time and cannot set"
853 " a value greater than 0x14 %x\n", btm_param->interval);
854 btm_param->interval = PM8XXX_ADC_BTM_INTERVAL_MAX;
855 }
856
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700857 spin_lock_irqsave(&adc_pmic->btm_lock, flags);
858
859 data_btm_cool_thr0 = ((btm_param->low_thr_voltage << 24) >> 24);
860 data_btm_cool_thr1 = ((btm_param->low_thr_voltage << 16) >> 24);
861 data_btm_warm_thr0 = ((btm_param->high_thr_voltage << 24) >> 24);
862 data_btm_warm_thr1 = ((btm_param->high_thr_voltage << 16) >> 24);
863
864 if (btm_param->btm_cool_fn != NULL) {
865 rc = pm8xxx_adc_write_reg(PM8XXX_ADC_ARB_BTM_BAT_COOL_THR0,
866 data_btm_cool_thr0);
867 if (rc < 0)
868 goto write_err;
869
870 rc = pm8xxx_adc_write_reg(PM8XXX_ADC_ARB_BTM_BAT_COOL_THR1,
871 data_btm_cool_thr1);
872 if (rc < 0)
873 goto write_err;
874
Siddartha Mohanadoss402673e2012-01-06 16:31:44 -0800875 adc_pmic->batt.btm_cool_fn = btm_param->btm_cool_fn;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700876 }
877
878 if (btm_param->btm_warm_fn != NULL) {
879 rc = pm8xxx_adc_write_reg(PM8XXX_ADC_ARB_BTM_BAT_WARM_THR0,
880 data_btm_warm_thr0);
881 if (rc < 0)
882 goto write_err;
883
884 rc = pm8xxx_adc_write_reg(PM8XXX_ADC_ARB_BTM_BAT_WARM_THR1,
885 data_btm_warm_thr1);
886 if (rc < 0)
887 goto write_err;
888
Siddartha Mohanadoss402673e2012-01-06 16:31:44 -0800889 adc_pmic->batt.btm_warm_fn = btm_param->btm_warm_fn;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700890 }
891
892 rc = pm8xxx_adc_read_reg(PM8XXX_ADC_ARB_BTM_CNTRL1, &arb_btm_cntrl1);
893 if (rc < 0)
894 goto bail_out;
895
896 btm_param->interval &= PM8XXX_ADC_BTM_INTERVAL_SEL_MASK;
897 arb_btm_cntrl1 |=
898 btm_param->interval << PM8XXX_ADC_BTM_INTERVAL_SEL_SHIFT;
899
900 rc = pm8xxx_adc_write_reg(PM8XXX_ADC_ARB_BTM_CNTRL1, arb_btm_cntrl1);
901 if (rc < 0)
902 goto write_err;
903
904 spin_unlock_irqrestore(&adc_pmic->btm_lock, flags);
905
906 return rc;
907bail_out:
908write_err:
909 spin_unlock_irqrestore(&adc_pmic->btm_lock, flags);
910 pr_debug("%s: with error code %d\n", __func__, rc);
911 return rc;
912}
913EXPORT_SYMBOL_GPL(pm8xxx_adc_btm_configure);
914
915static uint32_t pm8xxx_adc_btm_read(uint32_t channel)
916{
917 struct pm8xxx_adc *adc_pmic = pmic_adc;
918 int rc, i;
919 u8 arb_btm_dig_param, arb_btm_ana_param, arb_btm_rsv;
920 u8 arb_btm_amux_cntrl, data_arb_btm_cntrl = 0;
921 unsigned long flags;
922
923 arb_btm_amux_cntrl = channel << PM8XXX_ADC_BTM_CHANNEL_SEL;
924 arb_btm_rsv = adc_pmic->adc_channel[channel].adc_rsv;
925 arb_btm_dig_param = arb_btm_ana_param = PM8XXX_ADC_ARB_ANA_DIG;
926
927 spin_lock_irqsave(&adc_pmic->btm_lock, flags);
928
929 rc = pm8xxx_adc_write_reg(PM8XXX_ADC_ARB_BTM_AMUX_CNTRL,
930 arb_btm_amux_cntrl);
931 if (rc < 0)
932 goto write_err;
933
934 arb_btm_rsv = PM8XXX_ADC_BTM_RSV;
935
936 rc = pm8xxx_adc_write_reg(PM8XXX_ADC_ARB_BTM_RSV, arb_btm_rsv);
937 if (rc < 0)
938 goto write_err;
939
940 rc = pm8xxx_adc_write_reg(PM8XXX_ADC_ARB_BTM_DIG_PARAM,
941 arb_btm_dig_param);
942 if (rc < 0)
943 goto write_err;
944
945 rc = pm8xxx_adc_write_reg(PM8XXX_ADC_ARB_BTM_ANA_PARAM,
946 arb_btm_ana_param);
947 if (rc < 0)
948 goto write_err;
949
950 data_arb_btm_cntrl |= PM8XXX_ADC_ARB_BTM_CNTRL1_EN_BTM;
951
952 for (i = 0; i < 2; i++) {
953 rc = pm8xxx_adc_write_reg(PM8XXX_ADC_ARB_BTM_CNTRL1,
954 data_arb_btm_cntrl);
955 if (rc < 0)
956 goto write_err;
957 }
958
959 data_arb_btm_cntrl |= PM8XXX_ADC_ARB_BTM_CNTRL1_REQ
960 | PM8XXX_ADC_ARB_BTM_CNTRL1_SEL_OP_MODE;
961
962 rc = pm8xxx_adc_write_reg(PM8XXX_ADC_ARB_BTM_CNTRL1,
963 data_arb_btm_cntrl);
964 if (rc < 0)
965 goto write_err;
966
Siddartha Mohanadoss402673e2012-01-06 16:31:44 -0800967 if (pmic_adc->batt.btm_warm_fn != NULL)
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700968 enable_irq(adc_pmic->btm_warm_irq);
969
Siddartha Mohanadoss402673e2012-01-06 16:31:44 -0800970 if (pmic_adc->batt.btm_cool_fn != NULL)
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700971 enable_irq(adc_pmic->btm_cool_irq);
972
973write_err:
974 spin_unlock_irqrestore(&adc_pmic->btm_lock, flags);
975 return rc;
976}
977
978uint32_t pm8xxx_adc_btm_start(void)
979{
980 return pm8xxx_adc_btm_read(CHANNEL_BATT_THERM);
981}
982EXPORT_SYMBOL_GPL(pm8xxx_adc_btm_start);
983
984uint32_t pm8xxx_adc_btm_end(void)
985{
986 struct pm8xxx_adc *adc_pmic = pmic_adc;
987 int i, rc;
Siddartha Mohanadoss6217da02011-12-13 20:23:05 -0800988 u8 data_arb_btm_cntrl = 0;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700989 unsigned long flags;
990
991 disable_irq_nosync(adc_pmic->btm_warm_irq);
992 disable_irq_nosync(adc_pmic->btm_cool_irq);
993
994 spin_lock_irqsave(&adc_pmic->btm_lock, flags);
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700995
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700996 /* Write twice to the CNTRL register for the arbiter settings
997 to take into effect */
998 for (i = 0; i < 2; i++) {
999 rc = pm8xxx_adc_write_reg(PM8XXX_ADC_ARB_BTM_CNTRL1,
1000 data_arb_btm_cntrl);
1001 if (rc < 0) {
1002 spin_unlock_irqrestore(&adc_pmic->btm_lock, flags);
1003 return rc;
1004 }
1005 }
1006
1007 spin_unlock_irqrestore(&adc_pmic->btm_lock, flags);
1008
1009 return rc;
1010}
1011EXPORT_SYMBOL_GPL(pm8xxx_adc_btm_end);
1012
1013static ssize_t pm8xxx_adc_show(struct device *dev,
1014 struct device_attribute *devattr, char *buf)
1015{
1016 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -07001017 struct pm8xxx_adc_chan_result result;
1018 int rc = -1;
1019
Siddartha Mohanadosscb6d3002012-03-15 10:44:11 -07001020 rc = pm8xxx_adc_read(attr->index, &result);
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -07001021
1022 if (rc)
1023 return 0;
1024
Siddartha Mohanadossae39c902011-11-09 17:54:31 -08001025 return snprintf(buf, PM8XXX_ADC_HWMON_NAME_LENGTH,
1026 "Result:%lld Raw:%d\n", result.physical, result.adc_code);
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -07001027}
1028
1029static int get_adc(void *data, u64 *val)
1030{
1031 struct pm8xxx_adc_chan_result result;
1032 int i = (int)data;
1033 int rc;
1034
1035 rc = pm8xxx_adc_read(i, &result);
1036 if (!rc)
1037 pr_info("ADC value raw:%x physical:%lld\n",
1038 result.adc_code, result.physical);
1039 *val = result.physical;
1040
1041 return 0;
1042}
1043DEFINE_SIMPLE_ATTRIBUTE(reg_fops, get_adc, NULL, "%llu\n");
1044
1045static int get_mpp_adc(void *data, u64 *val)
1046{
1047 struct pm8xxx_adc_chan_result result;
1048 int i = (int)data;
1049 int rc;
1050
1051 rc = pm8xxx_adc_mpp_config_read(i,
1052 ADC_MPP_1_AMUX6, &result);
1053 if (!rc)
1054 pr_info("ADC MPP value raw:%x physical:%lld\n",
1055 result.adc_code, result.physical);
1056 *val = result.physical;
1057
1058 return 0;
1059}
1060DEFINE_SIMPLE_ATTRIBUTE(reg_mpp_fops, get_mpp_adc, NULL, "%llu\n");
1061
1062#ifdef CONFIG_DEBUG_FS
1063static void create_debugfs_entries(void)
1064{
1065 int i = 0;
1066 pmic_adc->dent = debugfs_create_dir("pm8xxx_adc", NULL);
1067
1068 if (IS_ERR(pmic_adc->dent)) {
1069 pr_err("pmic adc debugfs dir not created\n");
1070 return;
1071 }
1072
1073 for (i = 0; i < pmic_adc->adc_num_board_channel; i++)
1074 debugfs_create_file(pmic_adc->adc_channel[i].name,
1075 0644, pmic_adc->dent,
1076 (void *)pmic_adc->adc_channel[i].channel_name,
1077 &reg_fops);
1078}
1079#else
1080static inline void create_debugfs_entries(void)
1081{
1082}
1083#endif
1084static struct sensor_device_attribute pm8xxx_adc_attr =
1085 SENSOR_ATTR(NULL, S_IRUGO, pm8xxx_adc_show, NULL, 0);
1086
1087static int32_t pm8xxx_adc_init_hwmon(struct platform_device *pdev)
1088{
1089 struct pm8xxx_adc *adc_pmic = pmic_adc;
Siddartha Mohanadosscb6d3002012-03-15 10:44:11 -07001090 int rc = 0, i, channel;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -07001091
1092 for (i = 0; i < pmic_adc->adc_num_board_channel; i++) {
Siddartha Mohanadosscb6d3002012-03-15 10:44:11 -07001093 channel = adc_pmic->adc_channel[i].channel_name;
1094 if (pm8xxx_adc_check_channel_valid(channel)) {
1095 pr_err("Invalid ADC init HWMON channel: %d\n", channel);
1096 continue;
1097 }
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -07001098 pm8xxx_adc_attr.index = adc_pmic->adc_channel[i].channel_name;
1099 pm8xxx_adc_attr.dev_attr.attr.name =
1100 adc_pmic->adc_channel[i].name;
1101 memcpy(&adc_pmic->sens_attr[i], &pm8xxx_adc_attr,
1102 sizeof(pm8xxx_adc_attr));
1103 rc = device_create_file(&pdev->dev,
1104 &adc_pmic->sens_attr[i].dev_attr);
1105 if (rc) {
1106 dev_err(&pdev->dev, "device_create_file failed for "
1107 "dev %s\n",
1108 adc_pmic->adc_channel[i].name);
1109 goto hwmon_err_sens;
1110 }
1111 }
1112
1113 return 0;
1114hwmon_err_sens:
1115 pr_info("Init HWMON failed for pm8xxx_adc with %d\n", rc);
1116 return rc;
1117}
1118
1119#ifdef CONFIG_PM
1120static int pm8xxx_adc_suspend_noirq(struct device *dev)
1121{
1122 struct pm8xxx_adc *adc_pmic = pmic_adc;
1123
1124 adc_pmic->msm_suspend_check = 1;
1125
1126 return 0;
1127}
1128
1129static int pm8xxx_adc_resume_noirq(struct device *dev)
1130{
1131 struct pm8xxx_adc *adc_pmic = pmic_adc;
1132
1133 adc_pmic->msm_suspend_check = 0;
1134
1135 return 0;
1136}
1137
1138static const struct dev_pm_ops pm8xxx_adc_dev_pm_ops = {
1139 .suspend_noirq = pm8xxx_adc_suspend_noirq,
1140 .resume_noirq = pm8xxx_adc_resume_noirq,
1141};
1142
1143#define PM8XXX_ADC_DEV_PM_OPS (&pm8xxx_adc_dev_pm_ops)
1144#else
1145#define PM8XXX_ADC_DEV_PM_OPS NULL
1146#endif
1147
1148static int __devexit pm8xxx_adc_teardown(struct platform_device *pdev)
1149{
1150 struct pm8xxx_adc *adc_pmic = pmic_adc;
1151 int i;
1152
1153 wake_lock_destroy(&adc_pmic->adc_wakelock);
1154 platform_set_drvdata(pdev, NULL);
1155 pmic_adc = NULL;
Siddartha Mohanadoss2c546d32012-02-21 23:01:08 -08001156 if (!pa_therm) {
1157 regulator_put(pa_therm);
1158 pa_therm = NULL;
1159 }
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -07001160 for (i = 0; i < adc_pmic->adc_num_board_channel; i++)
1161 device_remove_file(adc_pmic->dev,
1162 &adc_pmic->sens_attr[i].dev_attr);
1163 pm8xxx_adc_initialized = false;
1164
1165 return 0;
1166}
1167
1168static int __devinit pm8xxx_adc_probe(struct platform_device *pdev)
1169{
1170 const struct pm8xxx_adc_platform_data *pdata = pdev->dev.platform_data;
1171 struct pm8xxx_adc *adc_pmic;
1172 struct pm8xxx_adc_amux_properties *adc_amux_prop;
1173 int rc = 0;
1174
1175 if (!pdata) {
1176 dev_err(&pdev->dev, "no platform data?\n");
1177 return -EINVAL;
1178 }
1179
1180 adc_pmic = devm_kzalloc(&pdev->dev, sizeof(struct pm8xxx_adc) +
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -07001181 (sizeof(struct sensor_device_attribute) *
1182 pdata->adc_num_board_channel), GFP_KERNEL);
1183 if (!adc_pmic) {
1184 dev_err(&pdev->dev, "Unable to allocate memory\n");
1185 return -ENOMEM;
1186 }
1187
1188 adc_amux_prop = devm_kzalloc(&pdev->dev,
1189 sizeof(struct pm8xxx_adc_amux_properties) +
1190 sizeof(struct pm8xxx_adc_chan_properties)
1191 , GFP_KERNEL);
1192 if (!adc_amux_prop) {
1193 dev_err(&pdev->dev, "Unable to allocate memory\n");
1194 return -ENOMEM;
1195 }
1196
1197 adc_pmic->dev = &pdev->dev;
1198 adc_pmic->adc_prop = pdata->adc_prop;
1199 adc_pmic->conv = adc_amux_prop;
1200 init_completion(&adc_pmic->adc_rslt_completion);
1201 adc_pmic->adc_channel = pdata->adc_channel;
1202 adc_pmic->adc_num_board_channel = pdata->adc_num_board_channel;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -07001203 adc_pmic->mpp_base = pdata->adc_mpp_base;
1204
1205 mutex_init(&adc_pmic->adc_lock);
1206 mutex_init(&adc_pmic->mpp_adc_lock);
1207 spin_lock_init(&adc_pmic->btm_lock);
1208
1209 adc_pmic->adc_irq = platform_get_irq(pdev, PM8XXX_ADC_IRQ_0);
1210 if (adc_pmic->adc_irq < 0)
1211 return adc_pmic->adc_irq;
1212
1213 rc = devm_request_irq(&pdev->dev, adc_pmic->adc_irq,
1214 pm8xxx_adc_isr,
1215 IRQF_TRIGGER_RISING, "pm8xxx_adc_interrupt", adc_pmic);
1216 if (rc) {
1217 dev_err(&pdev->dev, "failed to request adc irq "
1218 "with error %d\n", rc);
Abhijeet Dharmapurikarf5285a22012-04-10 23:42:45 -07001219 } else {
1220 enable_irq_wake(adc_pmic->adc_irq);
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -07001221 }
1222
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -07001223 adc_pmic->btm_warm_irq = platform_get_irq(pdev, PM8XXX_ADC_IRQ_1);
1224 if (adc_pmic->btm_warm_irq < 0)
1225 return adc_pmic->btm_warm_irq;
1226
1227 rc = devm_request_irq(&pdev->dev, adc_pmic->btm_warm_irq,
1228 pm8xxx_btm_warm_isr,
1229 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
1230 "pm8xxx_btm_warm_interrupt", adc_pmic);
1231 if (rc) {
1232 pr_err("btm warm irq failed %d with interrupt number %d\n",
1233 rc, adc_pmic->btm_warm_irq);
1234 dev_err(&pdev->dev, "failed to request btm irq\n");
1235 }
1236
1237 disable_irq_nosync(adc_pmic->btm_warm_irq);
1238
1239 adc_pmic->btm_cool_irq = platform_get_irq(pdev, PM8XXX_ADC_IRQ_2);
1240 if (adc_pmic->btm_cool_irq < 0)
1241 return adc_pmic->btm_cool_irq;
1242
1243 rc = devm_request_irq(&pdev->dev, adc_pmic->btm_cool_irq,
1244 pm8xxx_btm_cool_isr,
1245 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
1246 "pm8xxx_btm_cool_interrupt", adc_pmic);
1247 if (rc) {
1248 pr_err("btm cool irq failed with return %d and number %d\n",
1249 rc, adc_pmic->btm_cool_irq);
1250 dev_err(&pdev->dev, "failed to request btm irq\n");
1251 }
1252
1253 disable_irq_nosync(adc_pmic->btm_cool_irq);
1254 platform_set_drvdata(pdev, adc_pmic);
1255 wake_lock_init(&adc_pmic->adc_wakelock, WAKE_LOCK_SUSPEND,
1256 "pm8xxx_adc_wakelock");
1257 adc_pmic->msm_suspend_check = 0;
1258 pmic_adc = adc_pmic;
1259
1260 INIT_WORK(&adc_pmic->warm_work, pm8xxx_adc_btm_warm_scheduler_fn);
1261 INIT_WORK(&adc_pmic->cool_work, pm8xxx_adc_btm_cool_scheduler_fn);
1262 create_debugfs_entries();
1263 pm8xxx_adc_calib_first_adc = false;
1264 pm8xxx_adc_calib_device_init = false;
1265 pm8xxx_adc_initialized = true;
1266
1267 rc = pm8xxx_adc_init_hwmon(pdev);
1268 if (rc) {
1269 pr_err("pm8xxx adc init hwmon failed with %d\n", rc);
1270 dev_err(&pdev->dev, "failed to initialize pm8xxx hwmon adc\n");
1271 }
1272 adc_pmic->hwmon = hwmon_device_register(adc_pmic->dev);
Siddartha Mohanadoss2c546d32012-02-21 23:01:08 -08001273
1274 pa_therm = regulator_get(adc_pmic->dev, "pa_therm");
1275 if (IS_ERR(pa_therm)) {
1276 rc = PTR_ERR(pa_therm);
1277 pr_err("failed to request pa_therm vreg with error %d\n", rc);
1278 pa_therm = NULL;
1279 }
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -07001280 return 0;
1281}
1282
1283static struct platform_driver pm8xxx_adc_driver = {
1284 .probe = pm8xxx_adc_probe,
1285 .remove = __devexit_p(pm8xxx_adc_teardown),
1286 .driver = {
1287 .name = PM8XXX_ADC_DEV_NAME,
1288 .owner = THIS_MODULE,
1289 .pm = PM8XXX_ADC_DEV_PM_OPS,
1290 },
1291};
1292
1293static int __init pm8xxx_adc_init(void)
1294{
1295 return platform_driver_register(&pm8xxx_adc_driver);
1296}
1297module_init(pm8xxx_adc_init);
1298
1299static void __exit pm8xxx_adc_exit(void)
1300{
1301 platform_driver_unregister(&pm8xxx_adc_driver);
1302}
1303module_exit(pm8xxx_adc_exit);
1304
1305MODULE_ALIAS("platform:" PM8XXX_ADC_DEV_NAME);
1306MODULE_DESCRIPTION("PMIC8921/8018 ADC driver");
1307MODULE_LICENSE("GPL v2");