blob: 0902c611a3bf6f8a82c8b647f50ea48d81fc6111 [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;
134 uint32_t adc_num_channel;
135 uint32_t adc_num_board_channel;
136 struct completion adc_rslt_completion;
137 struct pm8xxx_adc_amux *adc_channel;
138 int btm_warm_irq;
139 int btm_cool_irq;
140 struct dentry *dent;
141 struct work_struct warm_work;
142 struct work_struct cool_work;
143 uint32_t mpp_base;
144 struct device *hwmon;
145 struct wake_lock adc_wakelock;
146 int msm_suspend_check;
147 struct pm8xxx_adc_amux_properties *conv;
Siddartha Mohanadoss402673e2012-01-06 16:31:44 -0800148 struct pm8xxx_adc_arb_btm_param batt;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700149 struct sensor_device_attribute sens_attr[0];
150};
151
152struct pm8xxx_adc_amux_properties {
153 uint32_t amux_channel;
154 uint32_t decimation;
155 uint32_t amux_ip_rsv;
156 uint32_t amux_mpp_channel;
157 struct pm8xxx_adc_chan_properties chan_prop[0];
158};
159
160static const struct pm8xxx_adc_scaling_ratio pm8xxx_amux_scaling_ratio[] = {
161 {1, 1},
162 {1, 3},
163 {1, 4},
164 {1, 6}
165};
166
167static struct pm8xxx_adc *pmic_adc;
Siddartha Mohanadoss2c546d32012-02-21 23:01:08 -0800168static struct regulator *pa_therm;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700169
170static struct pm8xxx_adc_scale_fn adc_scale_fn[] = {
171 [ADC_SCALE_DEFAULT] = {pm8xxx_adc_scale_default},
172 [ADC_SCALE_BATT_THERM] = {pm8xxx_adc_scale_batt_therm},
173 [ADC_SCALE_PA_THERM] = {pm8xxx_adc_scale_pa_therm},
174 [ADC_SCALE_PMIC_THERM] = {pm8xxx_adc_scale_pmic_therm},
175 [ADC_SCALE_XOTHERM] = {pm8xxx_adc_tdkntcg_therm},
176};
177
178/* On PM8921 ADC the MPP needs to first be configured
179as an analog input to the AMUX pre-mux channel before
180issuing a read request. PM8921 MPP 8 is mapped to AMUX8
181and is common between remote processor's.
182On PM8018 ADC the MPP is directly connected to the AMUX
183pre-mux. Therefore clients of the PM8018 MPP do not need
184to configure the MPP as an analog input to the pre-mux.
185Clients can directly issue request on the pre-mux AMUX
186channel to read the ADC on the MPP */
187static struct pm8xxx_mpp_config_data pm8xxx_adc_mpp_config = {
188 .type = PM8XXX_MPP_TYPE_A_INPUT,
189 /* AMUX6 is dedicated to be used for apps processor */
190 .level = PM8XXX_MPP_AIN_AMUX_CH6,
191 .control = PM8XXX_MPP_AOUT_CTRL_DISABLE,
192};
193
194/* MPP Configuration for default settings */
195static struct pm8xxx_mpp_config_data pm8xxx_adc_mpp_unconfig = {
196 .type = PM8XXX_MPP_TYPE_SINK,
197 .level = PM8XXX_MPP_AIN_AMUX_CH5,
198 .control = PM8XXX_MPP_AOUT_CTRL_DISABLE,
199};
200
201static bool pm8xxx_adc_calib_first_adc;
202static bool pm8xxx_adc_initialized, pm8xxx_adc_calib_device_init;
203
204static int32_t pm8xxx_adc_arb_cntrl(uint32_t arb_cntrl,
205 uint32_t channel)
206{
207 struct pm8xxx_adc *adc_pmic = pmic_adc;
208 int i, rc;
209 u8 data_arb_cntrl = 0;
210
211 if (arb_cntrl) {
212 if (adc_pmic->msm_suspend_check)
213 pr_err("PM8xxx ADC request made after suspend_noirq "
214 "with channel: %d\n", channel);
215 data_arb_cntrl |= PM8XXX_ADC_ARB_USRP_CNTRL1_EN_ARB;
216 wake_lock(&adc_pmic->adc_wakelock);
217 }
218
219 /* Write twice to the CNTRL register for the arbiter settings
220 to take into effect */
221 for (i = 0; i < 2; i++) {
222 rc = pm8xxx_writeb(adc_pmic->dev->parent,
223 PM8XXX_ADC_ARB_USRP_CNTRL1, data_arb_cntrl);
224 if (rc < 0) {
225 pr_err("PM8xxx arb cntrl write failed with %d\n", rc);
226 return rc;
227 }
228 }
229
230 if (arb_cntrl) {
231 data_arb_cntrl |= PM8XXX_ADC_ARB_USRP_CNTRL1_REQ;
232 rc = pm8xxx_writeb(adc_pmic->dev->parent,
233 PM8XXX_ADC_ARB_USRP_CNTRL1, data_arb_cntrl);
234 } else
235 wake_unlock(&adc_pmic->adc_wakelock);
236
237 return 0;
238}
239
240static int32_t pm8xxx_adc_patherm_power(bool on)
241{
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700242 int rc = 0;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700243
Siddartha Mohanadoss2c546d32012-02-21 23:01:08 -0800244 if (!pa_therm) {
245 pr_err("pm8xxx adc pa_therm not valid\n");
246 return -EINVAL;
247 }
248
249 if (on) {
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700250 rc = regulator_set_voltage(pa_therm,
251 PM8XXX_ADC_PA_THERM_VREG_UV_MIN,
252 PM8XXX_ADC_PA_THERM_VREG_UV_MAX);
253 if (rc < 0) {
254 pr_err("failed to set the voltage for "
255 "pa_therm with error %d\n", rc);
Siddartha Mohanadoss2c546d32012-02-21 23:01:08 -0800256 return rc;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700257 }
258
259 rc = regulator_set_optimum_mode(pa_therm,
260 PM8XXX_ADC_PA_THERM_VREG_UA_LOAD);
261 if (rc < 0) {
262 pr_err("failed to set optimum mode for "
263 "pa_therm with error %d\n", rc);
Siddartha Mohanadoss2c546d32012-02-21 23:01:08 -0800264 return rc;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700265 }
266
Siddartha Mohanadoss2c546d32012-02-21 23:01:08 -0800267 rc = regulator_enable(pa_therm);
268 if (rc < 0) {
269 pr_err("failed to enable pa_therm vreg "
270 "with error %d\n", rc);
271 return rc;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700272 }
273 } else {
Siddartha Mohanadoss2c546d32012-02-21 23:01:08 -0800274 rc = regulator_disable(pa_therm);
275 if (rc < 0) {
276 pr_err("failed to disable pa_therm vreg "
277 "with error %d\n", rc);
278 return rc;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700279 }
280 }
281
282 return rc;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700283}
284
285static int32_t pm8xxx_adc_channel_power_enable(uint32_t channel,
286 bool power_cntrl)
287{
288 int rc = 0;
289
290 switch (channel)
291 case ADC_MPP_1_AMUX8:
Siddartha Mohanadoss2c546d32012-02-21 23:01:08 -0800292 rc = pm8xxx_adc_patherm_power(power_cntrl);
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700293
294 return rc;
295}
296
297
298static uint32_t pm8xxx_adc_read_reg(uint32_t reg, u8 *data)
299{
300 struct pm8xxx_adc *adc_pmic = pmic_adc;
301 int rc;
302
303 rc = pm8xxx_readb(adc_pmic->dev->parent, reg, data);
304 if (rc < 0) {
305 pr_err("PM8xxx adc read reg %d failed with %d\n", reg, rc);
306 return rc;
307 }
308
309 return 0;
310}
311
312static uint32_t pm8xxx_adc_write_reg(uint32_t reg, u8 data)
313{
314 struct pm8xxx_adc *adc_pmic = pmic_adc;
315 int rc;
316
317 rc = pm8xxx_writeb(adc_pmic->dev->parent, reg, data);
318 if (rc < 0) {
319 pr_err("PM8xxx adc write reg %d failed with %d\n", reg, rc);
320 return rc;
321 }
322
323 return 0;
324}
325
326static int32_t pm8xxx_adc_configure(
327 struct pm8xxx_adc_amux_properties *chan_prop)
328{
329 struct pm8xxx_adc *adc_pmic = pmic_adc;
330 u8 data_amux_chan = 0, data_arb_rsv = 0, data_dig_param = 0;
331 int rc;
332
333 data_amux_chan |= chan_prop->amux_channel << PM8XXX_ADC_AMUX_SEL;
334
335 if (chan_prop->amux_mpp_channel)
336 data_amux_chan |= chan_prop->amux_mpp_channel <<
337 PM8XXX_ADC_AMUX_MPP_SEL;
338
339 rc = pm8xxx_adc_write_reg(PM8XXX_ADC_ARB_USRP_AMUX_CNTRL,
340 data_amux_chan);
341 if (rc < 0)
342 return rc;
343
Siddartha Mohanadoss866fe9f2011-12-13 23:01:40 -0800344 rc = pm8xxx_adc_read_reg(PM8XXX_ADC_ARB_USRP_RSV, &data_arb_rsv);
345 if (rc < 0)
346 return rc;
347
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700348 data_arb_rsv &= (PM8XXX_ADC_ARB_USRP_RSV_RST |
349 PM8XXX_ADC_ARB_USRP_RSV_DTEST0 |
350 PM8XXX_ADC_ARB_USRP_RSV_DTEST1 |
Siddartha Mohanadoss866fe9f2011-12-13 23:01:40 -0800351 PM8XXX_ADC_ARB_USRP_RSV_OP);
352 data_arb_rsv |= (chan_prop->amux_ip_rsv << PM8XXX_ADC_RSV_IP_SEL |
353 PM8XXX_ADC_ARB_USRP_RSV_TRM);
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700354
355 rc = pm8xxx_adc_write_reg(PM8XXX_ADC_ARB_USRP_RSV, data_arb_rsv);
356 if (rc < 0)
357 return rc;
358
359 rc = pm8xxx_adc_read_reg(PM8XXX_ADC_ARB_USRP_DIG_PARAM,
360 &data_dig_param);
361 if (rc < 0)
362 return rc;
363
364 /* Default 2.4Mhz clock rate */
365 /* Client chooses the decimation */
366 switch (chan_prop->decimation) {
367 case ADC_DECIMATION_TYPE1:
368 data_dig_param |= PM8XXX_ADC_ARB_USRP_DIG_PARAM_DEC_RATE0;
369 break;
370 case ADC_DECIMATION_TYPE2:
371 data_dig_param |= (PM8XXX_ADC_ARB_USRP_DIG_PARAM_DEC_RATE0
372 | PM8XXX_ADC_ARB_USRP_DIG_PARAM_DEC_RATE1);
373 break;
374 default:
375 data_dig_param |= PM8XXX_ADC_ARB_USRP_DIG_PARAM_DEC_RATE0;
376 break;
377 }
378 rc = pm8xxx_adc_write_reg(PM8XXX_ADC_ARB_USRP_DIG_PARAM,
379 PM8XXX_ADC_ARB_ANA_DIG);
380 if (rc < 0)
381 return rc;
382
383 rc = pm8xxx_adc_write_reg(PM8XXX_ADC_ARB_USRP_ANA_PARAM,
384 PM8XXX_ADC_ARB_ANA_DIG);
385 if (rc < 0)
386 return rc;
387
388 if (!pm8xxx_adc_calib_first_adc)
389 enable_irq(adc_pmic->adc_irq);
390
391 rc = pm8xxx_adc_arb_cntrl(1, data_amux_chan);
392 if (rc < 0) {
393 pr_err("Configuring ADC Arbiter"
394 "enable failed with %d\n", rc);
395 return rc;
396 }
397
398 return 0;
399}
400
401static uint32_t pm8xxx_adc_read_adc_code(int32_t *data)
402{
403 struct pm8xxx_adc *adc_pmic = pmic_adc;
404 uint8_t rslt_lsb, rslt_msb;
405 int32_t rc, max_ideal_adc_code = 1 << adc_pmic->adc_prop->bitresolution;
406
407 rc = pm8xxx_readb(adc_pmic->dev->parent,
408 PM8XXX_ADC_ARB_USRP_DATA0, &rslt_lsb);
409 if (rc < 0) {
410 pr_err("PM8xxx adc result read failed with %d\n", rc);
411 return rc;
412 }
413
414 rc = pm8xxx_readb(adc_pmic->dev->parent,
415 PM8XXX_ADC_ARB_USRP_DATA1, &rslt_msb);
416 if (rc < 0) {
417 pr_err("PM8xxx adc result read failed with %d\n", rc);
418 return rc;
419 }
420
421 *data = (rslt_msb << 8) | rslt_lsb;
422
423 /* Use the midpoint to determine underflow or overflow */
424 if (*data > max_ideal_adc_code + (max_ideal_adc_code >> 1))
425 *data |= ((1 << (8 * sizeof(*data) -
426 adc_pmic->adc_prop->bitresolution)) - 1) <<
427 adc_pmic->adc_prop->bitresolution;
428
429 /* Default value for switching off the arbiter after reading
430 the ADC value. Bit 0 set to 0. */
431 rc = pm8xxx_adc_arb_cntrl(0, CHANNEL_NONE);
432 if (rc < 0) {
433 pr_err("%s: Configuring ADC Arbiter disable"
434 "failed\n", __func__);
435 return rc;
436 }
437
438 return 0;
439}
440
441static void pm8xxx_adc_btm_warm_scheduler_fn(struct work_struct *work)
442{
443 struct pm8xxx_adc *adc_pmic = container_of(work, struct pm8xxx_adc,
444 warm_work);
445 unsigned long flags = 0;
446 bool warm_status;
447
448 spin_lock_irqsave(&adc_pmic->btm_lock, flags);
449 warm_status = irq_read_line(adc_pmic->btm_warm_irq);
Siddartha Mohanadoss402673e2012-01-06 16:31:44 -0800450 if (adc_pmic->batt.btm_warm_fn != NULL)
451 adc_pmic->batt.btm_warm_fn(warm_status);
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700452 spin_unlock_irqrestore(&adc_pmic->btm_lock, flags);
453}
454
455static void pm8xxx_adc_btm_cool_scheduler_fn(struct work_struct *work)
456{
457 struct pm8xxx_adc *adc_pmic = container_of(work, struct pm8xxx_adc,
458 cool_work);
459 unsigned long flags = 0;
460 bool cool_status;
461
462 spin_lock_irqsave(&adc_pmic->btm_lock, flags);
463 cool_status = irq_read_line(adc_pmic->btm_cool_irq);
Siddartha Mohanadoss402673e2012-01-06 16:31:44 -0800464 if (adc_pmic->batt.btm_cool_fn != NULL)
465 adc_pmic->batt.btm_cool_fn(cool_status);
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700466 spin_unlock_irqrestore(&adc_pmic->btm_lock, flags);
467}
468
469static irqreturn_t pm8xxx_adc_isr(int irq, void *dev_id)
470{
471 struct pm8xxx_adc *adc_8xxx = dev_id;
472
473 disable_irq_nosync(adc_8xxx->adc_irq);
474
475 if (pm8xxx_adc_calib_first_adc)
476 return IRQ_HANDLED;
477 /* TODO Handle spurius interrupt condition */
478 complete(&adc_8xxx->adc_rslt_completion);
479
480 return IRQ_HANDLED;
481}
482
483static irqreturn_t pm8xxx_btm_warm_isr(int irq, void *dev_id)
484{
485 struct pm8xxx_adc *btm_8xxx = dev_id;
486
487 schedule_work(&btm_8xxx->warm_work);
488
489 return IRQ_HANDLED;
490}
491
492static irqreturn_t pm8xxx_btm_cool_isr(int irq, void *dev_id)
493{
494 struct pm8xxx_adc *btm_8xxx = dev_id;
495
496 schedule_work(&btm_8xxx->cool_work);
497
498 return IRQ_HANDLED;
499}
500
501static uint32_t pm8xxx_adc_calib_device(void)
502{
503 struct pm8xxx_adc *adc_pmic = pmic_adc;
504 struct pm8xxx_adc_amux_properties conv;
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800505 int rc, calib_read_1, calib_read_2;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700506 u8 data_arb_usrp_cntrl1 = 0;
507
508 conv.amux_channel = CHANNEL_125V;
509 conv.decimation = ADC_DECIMATION_TYPE2;
510 conv.amux_ip_rsv = AMUX_RSV1;
511 conv.amux_mpp_channel = PREMUX_MPP_SCALE_0;
512 pm8xxx_adc_calib_first_adc = true;
513 rc = pm8xxx_adc_configure(&conv);
514 if (rc) {
515 pr_err("pm8xxx_adc configure failed with %d\n", rc);
516 goto calib_fail;
517 }
518
519 while (data_arb_usrp_cntrl1 != (PM8XXX_ADC_ARB_USRP_CNTRL1_EOC |
520 PM8XXX_ADC_ARB_USRP_CNTRL1_EN_ARB)) {
521 rc = pm8xxx_adc_read_reg(PM8XXX_ADC_ARB_USRP_CNTRL1,
522 &data_arb_usrp_cntrl1);
523 if (rc < 0)
524 return rc;
525 usleep_range(PM8XXX_ADC_CONV_TIME_MIN,
526 PM8XXX_ADC_CONV_TIME_MAX);
527 }
528 data_arb_usrp_cntrl1 = 0;
529
530 rc = pm8xxx_adc_read_adc_code(&calib_read_1);
531 if (rc) {
532 pr_err("pm8xxx_adc read adc failed with %d\n", rc);
533 pm8xxx_adc_calib_first_adc = false;
534 goto calib_fail;
535 }
536 pm8xxx_adc_calib_first_adc = false;
537
538 conv.amux_channel = CHANNEL_625MV;
539 conv.decimation = ADC_DECIMATION_TYPE2;
540 conv.amux_ip_rsv = AMUX_RSV1;
541 conv.amux_mpp_channel = PREMUX_MPP_SCALE_0;
542 pm8xxx_adc_calib_first_adc = true;
543 rc = pm8xxx_adc_configure(&conv);
544 if (rc) {
545 pr_err("pm8xxx_adc configure failed with %d\n", rc);
546 goto calib_fail;
547 }
548
549 while (data_arb_usrp_cntrl1 != (PM8XXX_ADC_ARB_USRP_CNTRL1_EOC |
550 PM8XXX_ADC_ARB_USRP_CNTRL1_EN_ARB)) {
551 rc = pm8xxx_adc_read_reg(PM8XXX_ADC_ARB_USRP_CNTRL1,
552 &data_arb_usrp_cntrl1);
553 if (rc < 0)
554 return rc;
555 usleep_range(PM8XXX_ADC_CONV_TIME_MIN,
556 PM8XXX_ADC_CONV_TIME_MAX);
557 }
558 data_arb_usrp_cntrl1 = 0;
559
560 rc = pm8xxx_adc_read_adc_code(&calib_read_2);
561 if (rc) {
562 pr_err("pm8xxx_adc read adc failed with %d\n", rc);
563 pm8xxx_adc_calib_first_adc = false;
564 goto calib_fail;
565 }
566 pm8xxx_adc_calib_first_adc = false;
567
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700568 adc_pmic->conv->chan_prop->adc_graph[ADC_CALIB_ABSOLUTE].dy =
569 (calib_read_1 - calib_read_2);
570 adc_pmic->conv->chan_prop->adc_graph[ADC_CALIB_ABSOLUTE].dx
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800571 = PM8XXX_CHANNEL_ADC_625_UV;
572 adc_pmic->conv->chan_prop->adc_graph[ADC_CALIB_ABSOLUTE].adc_vref =
573 calib_read_1;
574 adc_pmic->conv->chan_prop->adc_graph[ADC_CALIB_ABSOLUTE].adc_gnd =
575 calib_read_2;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700576 rc = pm8xxx_adc_arb_cntrl(0, CHANNEL_NONE);
577 if (rc < 0) {
578 pr_err("%s: Configuring ADC Arbiter disable"
579 "failed\n", __func__);
580 return rc;
581 }
582 /* Ratiometric Calibration */
583 conv.amux_channel = CHANNEL_MUXOFF;
584 conv.decimation = ADC_DECIMATION_TYPE2;
585 conv.amux_ip_rsv = AMUX_RSV5;
586 conv.amux_mpp_channel = PREMUX_MPP_SCALE_0;
587 pm8xxx_adc_calib_first_adc = true;
588 rc = pm8xxx_adc_configure(&conv);
589 if (rc) {
590 pr_err("pm8xxx_adc configure failed with %d\n", rc);
591 goto calib_fail;
592 }
593
594 while (data_arb_usrp_cntrl1 != (PM8XXX_ADC_ARB_USRP_CNTRL1_EOC |
595 PM8XXX_ADC_ARB_USRP_CNTRL1_EN_ARB)) {
596 rc = pm8xxx_adc_read_reg(PM8XXX_ADC_ARB_USRP_CNTRL1,
597 &data_arb_usrp_cntrl1);
598 if (rc < 0)
599 return rc;
600 usleep_range(PM8XXX_ADC_CONV_TIME_MIN,
601 PM8XXX_ADC_CONV_TIME_MAX);
602 }
603 data_arb_usrp_cntrl1 = 0;
604
605 rc = pm8xxx_adc_read_adc_code(&calib_read_1);
606 if (rc) {
607 pr_err("pm8xxx_adc read adc failed with %d\n", rc);
608 pm8xxx_adc_calib_first_adc = false;
609 goto calib_fail;
610 }
611 pm8xxx_adc_calib_first_adc = false;
612
613 conv.amux_channel = CHANNEL_MUXOFF;
614 conv.decimation = ADC_DECIMATION_TYPE2;
615 conv.amux_ip_rsv = AMUX_RSV4;
616 conv.amux_mpp_channel = PREMUX_MPP_SCALE_0;
617 pm8xxx_adc_calib_first_adc = true;
618 rc = pm8xxx_adc_configure(&conv);
619 if (rc) {
620 pr_err("pm8xxx_adc configure failed with %d\n", rc);
621 goto calib_fail;
622 }
623
624 while (data_arb_usrp_cntrl1 != (PM8XXX_ADC_ARB_USRP_CNTRL1_EOC |
625 PM8XXX_ADC_ARB_USRP_CNTRL1_EN_ARB)) {
626 rc = pm8xxx_adc_read_reg(PM8XXX_ADC_ARB_USRP_CNTRL1,
627 &data_arb_usrp_cntrl1);
628 if (rc < 0)
629 return rc;
630 usleep_range(PM8XXX_ADC_CONV_TIME_MIN,
631 PM8XXX_ADC_CONV_TIME_MAX);
632 }
633 data_arb_usrp_cntrl1 = 0;
634
635 rc = pm8xxx_adc_read_adc_code(&calib_read_2);
636 if (rc) {
637 pr_err("pm8xxx_adc read adc failed with %d\n", rc);
638 pm8xxx_adc_calib_first_adc = false;
639 goto calib_fail;
640 }
641 pm8xxx_adc_calib_first_adc = false;
642
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700643 adc_pmic->conv->chan_prop->adc_graph[ADC_CALIB_RATIOMETRIC].dy =
644 (calib_read_1 - calib_read_2);
645 adc_pmic->conv->chan_prop->adc_graph[ADC_CALIB_RATIOMETRIC].dx =
646 adc_pmic->adc_prop->adc_vdd_reference;
Siddartha Mohanadossae39c902011-11-09 17:54:31 -0800647 adc_pmic->conv->chan_prop->adc_graph[ADC_CALIB_RATIOMETRIC].adc_vref =
648 calib_read_1;
649 adc_pmic->conv->chan_prop->adc_graph[ADC_CALIB_RATIOMETRIC].adc_gnd =
650 calib_read_2;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700651calib_fail:
652 rc = pm8xxx_adc_arb_cntrl(0, CHANNEL_NONE);
653 if (rc < 0) {
654 pr_err("%s: Configuring ADC Arbiter disable"
655 "failed\n", __func__);
656 }
657
658 return rc;
659}
660
661uint32_t pm8xxx_adc_read(enum pm8xxx_adc_channels channel,
662 struct pm8xxx_adc_chan_result *result)
663{
664 struct pm8xxx_adc *adc_pmic = pmic_adc;
665 int i = 0, rc = 0, rc_fail, amux_prescaling, scale_type;
666 enum pm8xxx_adc_premux_mpp_scale_type mpp_scale;
667
668 if (!pm8xxx_adc_initialized)
669 return -ENODEV;
670
671 if (!pm8xxx_adc_calib_device_init) {
672 if (pm8xxx_adc_calib_device() == 0)
673 pm8xxx_adc_calib_device_init = true;
674 }
675
676 mutex_lock(&adc_pmic->adc_lock);
677
678 for (i = 0; i < adc_pmic->adc_num_channel; i++) {
679 if (channel == adc_pmic->adc_channel[i].channel_name)
680 break;
681 }
682
683 if (i == adc_pmic->adc_num_channel) {
684 rc = -EBADF;
685 goto fail_unlock;
686 }
687
688 if (channel < PM8XXX_CHANNEL_MPP_SCALE1_IDX) {
689 mpp_scale = PREMUX_MPP_SCALE_0;
690 adc_pmic->conv->amux_channel = channel;
Siddartha Mohanadossae39c902011-11-09 17:54:31 -0800691 } else if (channel >= PM8XXX_CHANNEL_MPP_SCALE1_IDX &&
692 channel < PM8XXX_CHANNEL_MPP_SCALE3_IDX) {
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700693 mpp_scale = PREMUX_MPP_SCALE_1;
694 adc_pmic->conv->amux_channel = channel %
695 PM8XXX_CHANNEL_MPP_SCALE1_IDX;
Siddartha Mohanadossae39c902011-11-09 17:54:31 -0800696 } else {
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700697 mpp_scale = PREMUX_MPP_SCALE_1_DIV3;
698 adc_pmic->conv->amux_channel = channel %
699 PM8XXX_CHANNEL_MPP_SCALE3_IDX;
700 }
701
702 adc_pmic->conv->amux_mpp_channel = mpp_scale;
703 adc_pmic->conv->amux_ip_rsv = adc_pmic->adc_channel[i].adc_rsv;
704 adc_pmic->conv->decimation = adc_pmic->adc_channel[i].adc_decimation;
705 amux_prescaling = adc_pmic->adc_channel[i].chan_path_prescaling;
706
707 adc_pmic->conv->chan_prop->offset_gain_numerator =
708 pm8xxx_amux_scaling_ratio[amux_prescaling].num;
709 adc_pmic->conv->chan_prop->offset_gain_denominator =
710 pm8xxx_amux_scaling_ratio[amux_prescaling].den;
711
712 rc = pm8xxx_adc_channel_power_enable(channel, true);
713 if (rc) {
714 rc = -EINVAL;
715 goto fail_unlock;
716 }
717
718 rc = pm8xxx_adc_configure(adc_pmic->conv);
719 if (rc) {
720 rc = -EINVAL;
721 goto fail;
722 }
723
724 wait_for_completion(&adc_pmic->adc_rslt_completion);
725
726 rc = pm8xxx_adc_read_adc_code(&result->adc_code);
727 if (rc) {
728 rc = -EINVAL;
729 goto fail;
730 }
731
732 scale_type = adc_pmic->adc_channel[i].adc_scale_fn;
733 if (scale_type >= ADC_SCALE_NONE) {
734 rc = -EBADF;
735 goto fail;
736 }
737
738 adc_scale_fn[scale_type].chan(result->adc_code,
739 adc_pmic->adc_prop, adc_pmic->conv->chan_prop, result);
740
741 rc = pm8xxx_adc_channel_power_enable(channel, false);
742 if (rc) {
743 rc = -EINVAL;
744 goto fail_unlock;
745 }
746
747 mutex_unlock(&adc_pmic->adc_lock);
748
749 return 0;
750fail:
751 rc_fail = pm8xxx_adc_channel_power_enable(channel, false);
752 if (rc_fail)
753 pr_err("pm8xxx adc power disable failed\n");
754fail_unlock:
755 mutex_unlock(&adc_pmic->adc_lock);
756 pr_err("pm8xxx adc error with %d\n", rc);
757 return rc;
758}
759EXPORT_SYMBOL_GPL(pm8xxx_adc_read);
760
761uint32_t pm8xxx_adc_mpp_config_read(uint32_t mpp_num,
762 enum pm8xxx_adc_channels channel,
763 struct pm8xxx_adc_chan_result *result)
764{
765 struct pm8xxx_adc *adc_pmic = pmic_adc;
766 int rc = 0;
767
Siddartha Mohanadoss2c546d32012-02-21 23:01:08 -0800768 if (!pm8xxx_adc_initialized)
769 return -ENODEV;
770
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700771 if (!adc_pmic->mpp_base) {
772 rc = -EINVAL;
773 pr_info("PM8xxx MPP base invalid with error %d\n", rc);
774 return rc;
775 }
776
777 if (mpp_num == PM8XXX_AMUX_MPP_8) {
778 rc = -EINVAL;
779 pr_info("PM8xxx MPP8 is already configured "
780 "to AMUX8. Use pm8xxx_adc_read() instead.\n");
781 return rc;
782 }
783
784 mutex_lock(&adc_pmic->mpp_adc_lock);
785
786 rc = pm8xxx_mpp_config(((mpp_num - 1) + adc_pmic->mpp_base),
787 &pm8xxx_adc_mpp_config);
788 if (rc < 0) {
789 pr_err("pm8xxx adc mpp config error with %d\n", rc);
790 goto fail;
791 }
792
793 usleep_range(PM8XXX_ADC_MPP_SETTLE_TIME_MIN,
794 PM8XXX_ADC_MPP_SETTLE_TIME_MAX);
795
796 rc = pm8xxx_adc_read(channel, result);
797 if (rc < 0)
798 pr_err("pm8xxx adc read error with %d\n", rc);
799
800 rc = pm8xxx_mpp_config(((mpp_num - 1) + adc_pmic->mpp_base),
801 &pm8xxx_adc_mpp_unconfig);
802 if (rc < 0)
803 pr_err("pm8xxx adc mpp config error with %d\n", rc);
804fail:
805 mutex_unlock(&adc_pmic->mpp_adc_lock);
806
807 return rc;
808}
809EXPORT_SYMBOL_GPL(pm8xxx_adc_mpp_config_read);
810
811uint32_t pm8xxx_adc_btm_configure(struct pm8xxx_adc_arb_btm_param *btm_param)
812{
813 struct pm8xxx_adc *adc_pmic = pmic_adc;
814 u8 data_btm_cool_thr0, data_btm_cool_thr1;
815 u8 data_btm_warm_thr0, data_btm_warm_thr1;
816 u8 arb_btm_cntrl1;
817 unsigned long flags = 0;
818 int rc;
819
820 if (adc_pmic == NULL) {
821 pr_err("PMIC ADC not valid\n");
822 return -EINVAL;
823 }
824
825 if ((btm_param->btm_cool_fn == NULL) &&
826 (btm_param->btm_warm_fn == NULL)) {
827 pr_err("No BTM warm/cool notification??\n");
828 return -EINVAL;
829 }
830
Siddartha Mohanadossae39c902011-11-09 17:54:31 -0800831 rc = pm8xxx_adc_batt_scaler(btm_param, adc_pmic->adc_prop,
832 adc_pmic->conv->chan_prop);
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700833 if (rc < 0) {
834 pr_err("Failed to lookup the BTM thresholds\n");
835 return rc;
836 }
837
Siddartha Mohanadoss68ceac12011-12-09 16:04:41 -0800838 if (btm_param->interval > PM8XXX_ADC_BTM_INTERVAL_MAX) {
839 pr_info("Bug in PMIC BTM interval time and cannot set"
840 " a value greater than 0x14 %x\n", btm_param->interval);
841 btm_param->interval = PM8XXX_ADC_BTM_INTERVAL_MAX;
842 }
843
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700844 spin_lock_irqsave(&adc_pmic->btm_lock, flags);
845
846 data_btm_cool_thr0 = ((btm_param->low_thr_voltage << 24) >> 24);
847 data_btm_cool_thr1 = ((btm_param->low_thr_voltage << 16) >> 24);
848 data_btm_warm_thr0 = ((btm_param->high_thr_voltage << 24) >> 24);
849 data_btm_warm_thr1 = ((btm_param->high_thr_voltage << 16) >> 24);
850
851 if (btm_param->btm_cool_fn != NULL) {
852 rc = pm8xxx_adc_write_reg(PM8XXX_ADC_ARB_BTM_BAT_COOL_THR0,
853 data_btm_cool_thr0);
854 if (rc < 0)
855 goto write_err;
856
857 rc = pm8xxx_adc_write_reg(PM8XXX_ADC_ARB_BTM_BAT_COOL_THR1,
858 data_btm_cool_thr1);
859 if (rc < 0)
860 goto write_err;
861
Siddartha Mohanadoss402673e2012-01-06 16:31:44 -0800862 adc_pmic->batt.btm_cool_fn = btm_param->btm_cool_fn;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700863 }
864
865 if (btm_param->btm_warm_fn != NULL) {
866 rc = pm8xxx_adc_write_reg(PM8XXX_ADC_ARB_BTM_BAT_WARM_THR0,
867 data_btm_warm_thr0);
868 if (rc < 0)
869 goto write_err;
870
871 rc = pm8xxx_adc_write_reg(PM8XXX_ADC_ARB_BTM_BAT_WARM_THR1,
872 data_btm_warm_thr1);
873 if (rc < 0)
874 goto write_err;
875
Siddartha Mohanadoss402673e2012-01-06 16:31:44 -0800876 adc_pmic->batt.btm_warm_fn = btm_param->btm_warm_fn;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700877 }
878
879 rc = pm8xxx_adc_read_reg(PM8XXX_ADC_ARB_BTM_CNTRL1, &arb_btm_cntrl1);
880 if (rc < 0)
881 goto bail_out;
882
883 btm_param->interval &= PM8XXX_ADC_BTM_INTERVAL_SEL_MASK;
884 arb_btm_cntrl1 |=
885 btm_param->interval << PM8XXX_ADC_BTM_INTERVAL_SEL_SHIFT;
886
887 rc = pm8xxx_adc_write_reg(PM8XXX_ADC_ARB_BTM_CNTRL1, arb_btm_cntrl1);
888 if (rc < 0)
889 goto write_err;
890
891 spin_unlock_irqrestore(&adc_pmic->btm_lock, flags);
892
893 return rc;
894bail_out:
895write_err:
896 spin_unlock_irqrestore(&adc_pmic->btm_lock, flags);
897 pr_debug("%s: with error code %d\n", __func__, rc);
898 return rc;
899}
900EXPORT_SYMBOL_GPL(pm8xxx_adc_btm_configure);
901
902static uint32_t pm8xxx_adc_btm_read(uint32_t channel)
903{
904 struct pm8xxx_adc *adc_pmic = pmic_adc;
905 int rc, i;
906 u8 arb_btm_dig_param, arb_btm_ana_param, arb_btm_rsv;
907 u8 arb_btm_amux_cntrl, data_arb_btm_cntrl = 0;
908 unsigned long flags;
909
910 arb_btm_amux_cntrl = channel << PM8XXX_ADC_BTM_CHANNEL_SEL;
911 arb_btm_rsv = adc_pmic->adc_channel[channel].adc_rsv;
912 arb_btm_dig_param = arb_btm_ana_param = PM8XXX_ADC_ARB_ANA_DIG;
913
914 spin_lock_irqsave(&adc_pmic->btm_lock, flags);
915
916 rc = pm8xxx_adc_write_reg(PM8XXX_ADC_ARB_BTM_AMUX_CNTRL,
917 arb_btm_amux_cntrl);
918 if (rc < 0)
919 goto write_err;
920
921 arb_btm_rsv = PM8XXX_ADC_BTM_RSV;
922
923 rc = pm8xxx_adc_write_reg(PM8XXX_ADC_ARB_BTM_RSV, arb_btm_rsv);
924 if (rc < 0)
925 goto write_err;
926
927 rc = pm8xxx_adc_write_reg(PM8XXX_ADC_ARB_BTM_DIG_PARAM,
928 arb_btm_dig_param);
929 if (rc < 0)
930 goto write_err;
931
932 rc = pm8xxx_adc_write_reg(PM8XXX_ADC_ARB_BTM_ANA_PARAM,
933 arb_btm_ana_param);
934 if (rc < 0)
935 goto write_err;
936
937 data_arb_btm_cntrl |= PM8XXX_ADC_ARB_BTM_CNTRL1_EN_BTM;
938
939 for (i = 0; i < 2; i++) {
940 rc = pm8xxx_adc_write_reg(PM8XXX_ADC_ARB_BTM_CNTRL1,
941 data_arb_btm_cntrl);
942 if (rc < 0)
943 goto write_err;
944 }
945
946 data_arb_btm_cntrl |= PM8XXX_ADC_ARB_BTM_CNTRL1_REQ
947 | PM8XXX_ADC_ARB_BTM_CNTRL1_SEL_OP_MODE;
948
949 rc = pm8xxx_adc_write_reg(PM8XXX_ADC_ARB_BTM_CNTRL1,
950 data_arb_btm_cntrl);
951 if (rc < 0)
952 goto write_err;
953
Siddartha Mohanadoss402673e2012-01-06 16:31:44 -0800954 if (pmic_adc->batt.btm_warm_fn != NULL)
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700955 enable_irq(adc_pmic->btm_warm_irq);
956
Siddartha Mohanadoss402673e2012-01-06 16:31:44 -0800957 if (pmic_adc->batt.btm_cool_fn != NULL)
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700958 enable_irq(adc_pmic->btm_cool_irq);
959
960write_err:
961 spin_unlock_irqrestore(&adc_pmic->btm_lock, flags);
962 return rc;
963}
964
965uint32_t pm8xxx_adc_btm_start(void)
966{
967 return pm8xxx_adc_btm_read(CHANNEL_BATT_THERM);
968}
969EXPORT_SYMBOL_GPL(pm8xxx_adc_btm_start);
970
971uint32_t pm8xxx_adc_btm_end(void)
972{
973 struct pm8xxx_adc *adc_pmic = pmic_adc;
974 int i, rc;
Siddartha Mohanadoss6217da02011-12-13 20:23:05 -0800975 u8 data_arb_btm_cntrl = 0;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700976 unsigned long flags;
977
978 disable_irq_nosync(adc_pmic->btm_warm_irq);
979 disable_irq_nosync(adc_pmic->btm_cool_irq);
980
981 spin_lock_irqsave(&adc_pmic->btm_lock, flags);
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700982
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700983 /* Write twice to the CNTRL register for the arbiter settings
984 to take into effect */
985 for (i = 0; i < 2; i++) {
986 rc = pm8xxx_adc_write_reg(PM8XXX_ADC_ARB_BTM_CNTRL1,
987 data_arb_btm_cntrl);
988 if (rc < 0) {
989 spin_unlock_irqrestore(&adc_pmic->btm_lock, flags);
990 return rc;
991 }
992 }
993
994 spin_unlock_irqrestore(&adc_pmic->btm_lock, flags);
995
996 return rc;
997}
998EXPORT_SYMBOL_GPL(pm8xxx_adc_btm_end);
999
1000static ssize_t pm8xxx_adc_show(struct device *dev,
1001 struct device_attribute *devattr, char *buf)
1002{
1003 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
1004 struct pm8xxx_adc *adc_pmic = pmic_adc;
1005 struct pm8xxx_adc_chan_result result;
1006 int rc = -1;
1007
1008 if (attr->index < adc_pmic->adc_num_channel)
1009 rc = pm8xxx_adc_read(attr->index, &result);
1010
1011 if (rc)
1012 return 0;
1013
Siddartha Mohanadossae39c902011-11-09 17:54:31 -08001014 return snprintf(buf, PM8XXX_ADC_HWMON_NAME_LENGTH,
1015 "Result:%lld Raw:%d\n", result.physical, result.adc_code);
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -07001016}
1017
1018static int get_adc(void *data, u64 *val)
1019{
1020 struct pm8xxx_adc_chan_result result;
1021 int i = (int)data;
1022 int rc;
1023
1024 rc = pm8xxx_adc_read(i, &result);
1025 if (!rc)
1026 pr_info("ADC value raw:%x physical:%lld\n",
1027 result.adc_code, result.physical);
1028 *val = result.physical;
1029
1030 return 0;
1031}
1032DEFINE_SIMPLE_ATTRIBUTE(reg_fops, get_adc, NULL, "%llu\n");
1033
1034static int get_mpp_adc(void *data, u64 *val)
1035{
1036 struct pm8xxx_adc_chan_result result;
1037 int i = (int)data;
1038 int rc;
1039
1040 rc = pm8xxx_adc_mpp_config_read(i,
1041 ADC_MPP_1_AMUX6, &result);
1042 if (!rc)
1043 pr_info("ADC MPP value raw:%x physical:%lld\n",
1044 result.adc_code, result.physical);
1045 *val = result.physical;
1046
1047 return 0;
1048}
1049DEFINE_SIMPLE_ATTRIBUTE(reg_mpp_fops, get_mpp_adc, NULL, "%llu\n");
1050
1051#ifdef CONFIG_DEBUG_FS
1052static void create_debugfs_entries(void)
1053{
1054 int i = 0;
1055 pmic_adc->dent = debugfs_create_dir("pm8xxx_adc", NULL);
1056
1057 if (IS_ERR(pmic_adc->dent)) {
1058 pr_err("pmic adc debugfs dir not created\n");
1059 return;
1060 }
1061
1062 for (i = 0; i < pmic_adc->adc_num_board_channel; i++)
1063 debugfs_create_file(pmic_adc->adc_channel[i].name,
1064 0644, pmic_adc->dent,
1065 (void *)pmic_adc->adc_channel[i].channel_name,
1066 &reg_fops);
1067}
1068#else
1069static inline void create_debugfs_entries(void)
1070{
1071}
1072#endif
1073static struct sensor_device_attribute pm8xxx_adc_attr =
1074 SENSOR_ATTR(NULL, S_IRUGO, pm8xxx_adc_show, NULL, 0);
1075
1076static int32_t pm8xxx_adc_init_hwmon(struct platform_device *pdev)
1077{
1078 struct pm8xxx_adc *adc_pmic = pmic_adc;
1079 int rc = 0, i;
1080
1081 for (i = 0; i < pmic_adc->adc_num_board_channel; i++) {
1082 pm8xxx_adc_attr.index = adc_pmic->adc_channel[i].channel_name;
1083 pm8xxx_adc_attr.dev_attr.attr.name =
1084 adc_pmic->adc_channel[i].name;
1085 memcpy(&adc_pmic->sens_attr[i], &pm8xxx_adc_attr,
1086 sizeof(pm8xxx_adc_attr));
1087 rc = device_create_file(&pdev->dev,
1088 &adc_pmic->sens_attr[i].dev_attr);
1089 if (rc) {
1090 dev_err(&pdev->dev, "device_create_file failed for "
1091 "dev %s\n",
1092 adc_pmic->adc_channel[i].name);
1093 goto hwmon_err_sens;
1094 }
1095 }
1096
1097 return 0;
1098hwmon_err_sens:
1099 pr_info("Init HWMON failed for pm8xxx_adc with %d\n", rc);
1100 return rc;
1101}
1102
1103#ifdef CONFIG_PM
1104static int pm8xxx_adc_suspend_noirq(struct device *dev)
1105{
1106 struct pm8xxx_adc *adc_pmic = pmic_adc;
1107
1108 adc_pmic->msm_suspend_check = 1;
1109
1110 return 0;
1111}
1112
1113static int pm8xxx_adc_resume_noirq(struct device *dev)
1114{
1115 struct pm8xxx_adc *adc_pmic = pmic_adc;
1116
1117 adc_pmic->msm_suspend_check = 0;
1118
1119 return 0;
1120}
1121
1122static const struct dev_pm_ops pm8xxx_adc_dev_pm_ops = {
1123 .suspend_noirq = pm8xxx_adc_suspend_noirq,
1124 .resume_noirq = pm8xxx_adc_resume_noirq,
1125};
1126
1127#define PM8XXX_ADC_DEV_PM_OPS (&pm8xxx_adc_dev_pm_ops)
1128#else
1129#define PM8XXX_ADC_DEV_PM_OPS NULL
1130#endif
1131
1132static int __devexit pm8xxx_adc_teardown(struct platform_device *pdev)
1133{
1134 struct pm8xxx_adc *adc_pmic = pmic_adc;
1135 int i;
1136
1137 wake_lock_destroy(&adc_pmic->adc_wakelock);
1138 platform_set_drvdata(pdev, NULL);
1139 pmic_adc = NULL;
Siddartha Mohanadoss2c546d32012-02-21 23:01:08 -08001140 if (!pa_therm) {
1141 regulator_put(pa_therm);
1142 pa_therm = NULL;
1143 }
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -07001144 for (i = 0; i < adc_pmic->adc_num_board_channel; i++)
1145 device_remove_file(adc_pmic->dev,
1146 &adc_pmic->sens_attr[i].dev_attr);
1147 pm8xxx_adc_initialized = false;
1148
1149 return 0;
1150}
1151
1152static int __devinit pm8xxx_adc_probe(struct platform_device *pdev)
1153{
1154 const struct pm8xxx_adc_platform_data *pdata = pdev->dev.platform_data;
1155 struct pm8xxx_adc *adc_pmic;
1156 struct pm8xxx_adc_amux_properties *adc_amux_prop;
1157 int rc = 0;
1158
1159 if (!pdata) {
1160 dev_err(&pdev->dev, "no platform data?\n");
1161 return -EINVAL;
1162 }
1163
1164 adc_pmic = devm_kzalloc(&pdev->dev, sizeof(struct pm8xxx_adc) +
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -07001165 (sizeof(struct sensor_device_attribute) *
1166 pdata->adc_num_board_channel), GFP_KERNEL);
1167 if (!adc_pmic) {
1168 dev_err(&pdev->dev, "Unable to allocate memory\n");
1169 return -ENOMEM;
1170 }
1171
1172 adc_amux_prop = devm_kzalloc(&pdev->dev,
1173 sizeof(struct pm8xxx_adc_amux_properties) +
1174 sizeof(struct pm8xxx_adc_chan_properties)
1175 , GFP_KERNEL);
1176 if (!adc_amux_prop) {
1177 dev_err(&pdev->dev, "Unable to allocate memory\n");
1178 return -ENOMEM;
1179 }
1180
1181 adc_pmic->dev = &pdev->dev;
1182 adc_pmic->adc_prop = pdata->adc_prop;
1183 adc_pmic->conv = adc_amux_prop;
1184 init_completion(&adc_pmic->adc_rslt_completion);
1185 adc_pmic->adc_channel = pdata->adc_channel;
1186 adc_pmic->adc_num_board_channel = pdata->adc_num_board_channel;
1187 adc_pmic->adc_num_channel = ADC_MPP_2_CHANNEL_NONE;
1188 adc_pmic->mpp_base = pdata->adc_mpp_base;
1189
1190 mutex_init(&adc_pmic->adc_lock);
1191 mutex_init(&adc_pmic->mpp_adc_lock);
1192 spin_lock_init(&adc_pmic->btm_lock);
1193
1194 adc_pmic->adc_irq = platform_get_irq(pdev, PM8XXX_ADC_IRQ_0);
1195 if (adc_pmic->adc_irq < 0)
1196 return adc_pmic->adc_irq;
1197
1198 rc = devm_request_irq(&pdev->dev, adc_pmic->adc_irq,
1199 pm8xxx_adc_isr,
1200 IRQF_TRIGGER_RISING, "pm8xxx_adc_interrupt", adc_pmic);
1201 if (rc) {
1202 dev_err(&pdev->dev, "failed to request adc irq "
1203 "with error %d\n", rc);
1204 }
1205
1206 disable_irq_nosync(adc_pmic->adc_irq);
1207
1208 adc_pmic->btm_warm_irq = platform_get_irq(pdev, PM8XXX_ADC_IRQ_1);
1209 if (adc_pmic->btm_warm_irq < 0)
1210 return adc_pmic->btm_warm_irq;
1211
1212 rc = devm_request_irq(&pdev->dev, adc_pmic->btm_warm_irq,
1213 pm8xxx_btm_warm_isr,
1214 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
1215 "pm8xxx_btm_warm_interrupt", adc_pmic);
1216 if (rc) {
1217 pr_err("btm warm irq failed %d with interrupt number %d\n",
1218 rc, adc_pmic->btm_warm_irq);
1219 dev_err(&pdev->dev, "failed to request btm irq\n");
1220 }
1221
1222 disable_irq_nosync(adc_pmic->btm_warm_irq);
1223
1224 adc_pmic->btm_cool_irq = platform_get_irq(pdev, PM8XXX_ADC_IRQ_2);
1225 if (adc_pmic->btm_cool_irq < 0)
1226 return adc_pmic->btm_cool_irq;
1227
1228 rc = devm_request_irq(&pdev->dev, adc_pmic->btm_cool_irq,
1229 pm8xxx_btm_cool_isr,
1230 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
1231 "pm8xxx_btm_cool_interrupt", adc_pmic);
1232 if (rc) {
1233 pr_err("btm cool irq failed with return %d and number %d\n",
1234 rc, adc_pmic->btm_cool_irq);
1235 dev_err(&pdev->dev, "failed to request btm irq\n");
1236 }
1237
1238 disable_irq_nosync(adc_pmic->btm_cool_irq);
1239 platform_set_drvdata(pdev, adc_pmic);
1240 wake_lock_init(&adc_pmic->adc_wakelock, WAKE_LOCK_SUSPEND,
1241 "pm8xxx_adc_wakelock");
1242 adc_pmic->msm_suspend_check = 0;
1243 pmic_adc = adc_pmic;
1244
1245 INIT_WORK(&adc_pmic->warm_work, pm8xxx_adc_btm_warm_scheduler_fn);
1246 INIT_WORK(&adc_pmic->cool_work, pm8xxx_adc_btm_cool_scheduler_fn);
1247 create_debugfs_entries();
1248 pm8xxx_adc_calib_first_adc = false;
1249 pm8xxx_adc_calib_device_init = false;
1250 pm8xxx_adc_initialized = true;
1251
1252 rc = pm8xxx_adc_init_hwmon(pdev);
1253 if (rc) {
1254 pr_err("pm8xxx adc init hwmon failed with %d\n", rc);
1255 dev_err(&pdev->dev, "failed to initialize pm8xxx hwmon adc\n");
1256 }
1257 adc_pmic->hwmon = hwmon_device_register(adc_pmic->dev);
Siddartha Mohanadoss2c546d32012-02-21 23:01:08 -08001258
1259 pa_therm = regulator_get(adc_pmic->dev, "pa_therm");
1260 if (IS_ERR(pa_therm)) {
1261 rc = PTR_ERR(pa_therm);
1262 pr_err("failed to request pa_therm vreg with error %d\n", rc);
1263 pa_therm = NULL;
1264 }
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -07001265 return 0;
1266}
1267
1268static struct platform_driver pm8xxx_adc_driver = {
1269 .probe = pm8xxx_adc_probe,
1270 .remove = __devexit_p(pm8xxx_adc_teardown),
1271 .driver = {
1272 .name = PM8XXX_ADC_DEV_NAME,
1273 .owner = THIS_MODULE,
1274 .pm = PM8XXX_ADC_DEV_PM_OPS,
1275 },
1276};
1277
1278static int __init pm8xxx_adc_init(void)
1279{
1280 return platform_driver_register(&pm8xxx_adc_driver);
1281}
1282module_init(pm8xxx_adc_init);
1283
1284static void __exit pm8xxx_adc_exit(void)
1285{
1286 platform_driver_unregister(&pm8xxx_adc_driver);
1287}
1288module_exit(pm8xxx_adc_exit);
1289
1290MODULE_ALIAS("platform:" PM8XXX_ADC_DEV_NAME);
1291MODULE_DESCRIPTION("PMIC8921/8018 ADC driver");
1292MODULE_LICENSE("GPL v2");