blob: 17ae34f49aeb62dd74751fb12eb3f28a37ae3a37 [file] [log] [blame]
Siddartha Mohanadoss31f60962012-11-27 14:11:02 -08001/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
2 *
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
14#define pr_fmt(fmt) "%s: " fmt, __func__
15
16#include <linux/kernel.h>
17#include <linux/of.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/types.h>
24#include <linux/hwmon.h>
25#include <linux/module.h>
26#include <linux/debugfs.h>
27#include <linux/spmi.h>
28#include <linux/of_irq.h>
29#include <linux/wakelock.h>
30#include <linux/interrupt.h>
31#include <linux/completion.h>
32#include <linux/hwmon-sysfs.h>
33#include <linux/qpnp/qpnp-adc.h>
34#include <linux/thermal.h>
35#include <linux/platform_device.h>
36
37/* QPNP VADC TM register definition */
38#define QPNP_STATUS1 0x8
39#define QPNP_STATUS1_OP_MODE 4
40#define QPNP_STATUS1_MEAS_INTERVAL_EN_STS BIT(2)
41#define QPNP_STATUS1_REQ_STS BIT(1)
42#define QPNP_STATUS1_EOC BIT(0)
43#define QPNP_STATUS2 0x9
44#define QPNP_STATUS2_CONV_SEQ_STATE 6
45#define QPNP_STATUS2_FIFO_NOT_EMPTY_FLAG BIT(1)
46#define QPNP_STATUS2_CONV_SEQ_TIMEOUT_STS BIT(0)
47#define QPNP_CONV_TIMEOUT_ERR 2
48
49#define QPNP_MODE_CTL 0x40
50#define QPNP_OP_MODE_SHIFT 3
51#define QPNP_VREF_XO_THM_FORCE BIT(2)
52#define QPNP_AMUX_TRIM_EN BIT(1)
53#define QPNP_ADC_TRIM_EN BIT(0)
54#define QPNP_EN_CTL1 0x46
55#define QPNP_ADC_TM_EN BIT(7)
56#define QPNP_ADC_CH_SEL_CTL 0x48
57#define QPNP_ADC_DIG_PARAM 0x50
58#define QPNP_ADC_DIG_DEC_RATIO_SEL_SHIFT 3
59#define QPNP_HW_SETTLE_DELAY 0x51
60#define QPNP_CONV_REQ 0x52
61#define QPNP_CONV_REQ_SET BIT(7)
62#define QPNP_CONV_SEQ_CTL 0x54
63#define QPNP_CONV_SEQ_HOLDOFF_SHIFT 4
64#define QPNP_CONV_SEQ_TRIG_CTL 0x55
65#define QPNP_ADC_TM_MEAS_INTERVAL_CTL 0x57
66#define QPNP_ADC_TM_MEAS_INTERVAL_TIME_SHIFT 0x3
67#define QPNP_ADC_TM_MEAS_INTERVAL_CTL2 0x58
68#define QPNP_ADC_TM_MEAS_INTERVAL_CTL2_SHIFT 0x4
69#define QPNP_ADC_TM_MEAS_INTERVAL_CTL2_MASK 0xf0
70#define QPNP_ADC_TM_MEAS_INTERVAL_CTL3_MASK 0xf
71
72#define QPNP_ADC_MEAS_INTERVAL_OP_CTL 0x59
73#define QPNP_ADC_MEAS_INTERVAL_OP BIT(7)
74
75#define QPNP_FAST_AVG_CTL 0x5a
76#define QPNP_FAST_AVG_EN 0x5b
77
78#define QPNP_M0_LOW_THR_LSB 0x5c
79#define QPNP_M0_LOW_THR_MSB 0x5d
80#define QPNP_M0_HIGH_THR_LSB 0x5e
81#define QPNP_M0_HIGH_THR_MSB 0x5f
82#define QPNP_M1_LOW_THR_LSB 0x69
83#define QPNP_M1_LOW_THR_MSB 0x6a
84#define QPNP_M1_HIGH_THR_LSB 0x6b
85#define QPNP_M1_HIGH_THR_MSB 0x6c
86#define QPNP_M2_LOW_THR_LSB 0x71
87#define QPNP_M2_LOW_THR_MSB 0x72
88#define QPNP_M2_HIGH_THR_LSB 0x7b
89#define QPNP_M2_HIGH_THR_MSB 0x7c
90#define QPNP_M3_LOW_THR_LSB 0x79
91#define QPNP_M3_LOW_THR_MSB 0x7a
92#define QPNP_M3_HIGH_THR_LSB 0x7b
93#define QPNP_M3_HIGH_THR_MSB 0x7c
94#define QPNP_M4_LOW_THR_LSB 0x81
95#define QPNP_M4_LOW_THR_MSB 0x82
96#define QPNP_M4_HIGH_THR_LSB 0x83
97#define QPNP_M4_HIGH_THR_MSB 0x84
98
99#define QPNP_ADC_TM_MULTI_MEAS_EN 0x41
100#define QPNP_ADC_TM_MULTI_MEAS_EN_M0 BIT(0)
101#define QPNP_ADC_TM_MULTI_MEAS_EN_M1 BIT(1)
102#define QPNP_ADC_TM_MULTI_MEAS_EN_M2 BIT(2)
103#define QPNP_ADC_TM_MULTI_MEAS_EN_M3 BIT(3)
104#define QPNP_ADC_TM_MULTI_MEAS_EN_M4 BIT(4)
105#define QPNP_ADC_TM_LOW_THR_INT_EN 0x42
106#define QPNP_ADC_TM_LOW_THR_INT_EN_M0 BIT(0)
107#define QPNP_ADC_TM_LOW_THR_INT_EN_M1 BIT(1)
108#define QPNP_ADC_TM_LOW_THR_INT_EN_M2 BIT(2)
109#define QPNP_ADC_TM_LOW_THR_INT_EN_M3 BIT(3)
110#define QPNP_ADC_TM_LOW_THR_INT_EN_M4 BIT(4)
111#define QPNP_ADC_TM_HIGH_THR_INT_EN 0x43
112#define QPNP_ADC_TM_HIGH_THR_INT_EN_M0 BIT(0)
113#define QPNP_ADC_TM_HIGH_THR_INT_EN_M1 BIT(1)
114#define QPNP_ADC_TM_HIGH_THR_INT_EN_M2 BIT(2)
115#define QPNP_ADC_TM_HIGH_THR_INT_EN_M3 BIT(3)
116#define QPNP_ADC_TM_HIGH_THR_INT_EN_M4 BIT(4)
117
118#define QPNP_ADC_TM_M0_MEAS_INTERVAL_CTL 0x57
119#define QPNP_ADC_TM_M1_MEAS_INTERVAL_CTL 0x6d
120#define QPNP_ADC_TM_M2_MEAS_INTERVAL_CTL 0x75
121#define QPNP_ADC_TM_M3_MEAS_INTERVAL_CTL 0x7d
122#define QPNP_ADC_TM_M4_MEAS_INTERVAL_CTL 0x85
123#define QPNP_ADC_TM_STATUS1 0x8
124#define QPNP_ADC_TM_STATUS_LOW 0xa
125#define QPNP_ADC_TM_STATUS_HIGH 0xb
126
127#define QPNP_ADC_TM_M0_LOW_THR 0x5d5c
128#define QPNP_ADC_TM_M0_HIGH_THR 0x5f5e
129#define QPNP_ADC_TM_MEAS_INTERVAL 0x0
130
131#define QPNP_ADC_TM_THR_LSB_MASK(val) (val & 0xff)
132#define QPNP_ADC_TM_THR_MSB_MASK(val) ((val & 0xff00) >> 8)
133
134struct qpnp_adc_tm_sensor {
135 struct thermal_zone_device *tz_dev;
136 enum thermal_device_mode mode;
137 uint32_t sensor_num;
138 enum qpnp_adc_meas_timer_select timer_select;
139 uint32_t meas_interval;
140 uint32_t low_thr;
141 uint32_t high_thr;
142 uint32_t btm_channel_num;
143 struct work_struct work;
144};
145
146struct qpnp_adc_tm_drv {
147 struct qpnp_adc_drv *adc;
148 struct qpnp_adc_tm_usbid_param *usb_id_param;
149 struct work_struct usbid_work;
150 struct qpnp_adc_tm_btm_param *battery_param;
151 struct work_struct batt_work;
152 bool adc_tm_initialized;
153 struct qpnp_adc_tm_sensor sensor[0];
154};
155
156struct qpnp_adc_tm_drv *qpnp_adc_tm;
157
158struct qpnp_adc_tm_trip_reg_type {
159 uint16_t low_thr_lsb_addr;
160 uint16_t low_thr_msb_addr;
161 uint16_t high_thr_lsb_addr;
162 uint16_t high_thr_msb_addr;
163 u8 multi_meas_en;
164 u8 low_thr_int_chan_en;
165 u8 high_thr_int_chan_en;
166};
167
168static struct qpnp_adc_tm_trip_reg_type adc_tm_data[] = {
169 [QPNP_ADC_TM_M0_ADC_CH_SEL_CTL] = {QPNP_M0_LOW_THR_LSB,
170 QPNP_M0_LOW_THR_MSB, QPNP_M0_HIGH_THR_LSB,
171 QPNP_M0_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M0,
172 QPNP_ADC_TM_LOW_THR_INT_EN_M0, QPNP_ADC_TM_HIGH_THR_INT_EN_M0},
173 [QPNP_ADC_TM_M1_ADC_CH_SEL_CTL] = {QPNP_M1_LOW_THR_LSB,
174 QPNP_M1_LOW_THR_MSB, QPNP_M1_HIGH_THR_LSB,
175 QPNP_M1_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M1,
176 QPNP_ADC_TM_LOW_THR_INT_EN_M1, QPNP_ADC_TM_HIGH_THR_INT_EN_M1},
177 [QPNP_ADC_TM_M2_ADC_CH_SEL_CTL] = {QPNP_M2_LOW_THR_LSB,
178 QPNP_M2_LOW_THR_MSB, QPNP_M2_HIGH_THR_LSB,
179 QPNP_M2_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M2,
180 QPNP_ADC_TM_LOW_THR_INT_EN_M2, QPNP_ADC_TM_HIGH_THR_INT_EN_M2},
181 [QPNP_ADC_TM_M3_ADC_CH_SEL_CTL] = {QPNP_M3_LOW_THR_LSB,
182 QPNP_M3_LOW_THR_MSB, QPNP_M3_HIGH_THR_LSB,
183 QPNP_M3_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M3,
184 QPNP_ADC_TM_LOW_THR_INT_EN_M3, QPNP_ADC_TM_HIGH_THR_INT_EN_M3},
185 [QPNP_ADC_TM_M4_ADC_CH_SEL_CTL] = {QPNP_M4_LOW_THR_LSB,
186 QPNP_M4_LOW_THR_MSB, QPNP_M4_HIGH_THR_LSB,
187 QPNP_M4_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M4,
188 QPNP_ADC_TM_LOW_THR_INT_EN_M4, QPNP_ADC_TM_HIGH_THR_INT_EN_M4},
189};
190
191static int32_t qpnp_adc_tm_read_reg(int16_t reg, u8 *data)
192{
193 struct qpnp_adc_tm_drv *adc_tm = qpnp_adc_tm;
194 int rc = 0;
195
196 rc = spmi_ext_register_readl(adc_tm->adc->spmi->ctrl,
197 adc_tm->adc->slave, (adc_tm->adc->offset + reg), data, 1);
198 if (rc < 0)
199 pr_err("adc-tm read reg %d failed with %d\n", reg, rc);
200
201 return rc;
202}
203
204static int32_t qpnp_adc_tm_write_reg(int16_t reg, u8 data)
205{
206 struct qpnp_adc_tm_drv *adc_tm = qpnp_adc_tm;
207 int rc = 0;
208 u8 *buf;
209
210 buf = &data;
211
212 rc = spmi_ext_register_writel(adc_tm->adc->spmi->ctrl,
213 adc_tm->adc->slave, (adc_tm->adc->offset + reg), buf, 1);
214 if (rc < 0)
215 pr_err("adc-tm write reg %d failed with %d\n", reg, rc);
216
217 return rc;
218}
219
220static int32_t qpnp_adc_tm_enable(bool state)
221{
222 int rc = 0;
223 u8 data = 0, enable_check = 0;
224
225 if (state) {
226 data = QPNP_ADC_TM_EN;
227 rc = qpnp_adc_tm_write_reg(QPNP_EN_CTL1,
228 data);
229 if (rc < 0)
230 pr_err("adc-tm enable failed\n");
231 } else {
232 rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_MULTI_MEAS_EN,
233 &enable_check);
234 if (rc < 0) {
235 pr_err("multi measurement read failed\n");
236 return rc;
237 }
238
239 if (!enable_check) {
240 data = 0;
241 rc = qpnp_adc_tm_write_reg(QPNP_EN_CTL1, data);
242 if (rc < 0)
243 pr_err("adc-tm disable failed\n");
244 }
245 }
246
247 return rc;
248}
249
250static int32_t qpnp_adc_tm_enable_req_sts_check(void)
251{
252 u8 status1;
253 int rc;
254
255 /* The VADC_TM bank needs to be disabled for new conversion request */
256 rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_STATUS1, &status1);
257 if (rc) {
258 pr_err("adc-tm read status1 failed\n");
259 return rc;
260 }
261
262 /* Disable the bank if a conversion is occuring */
263 if (status1 & QPNP_STATUS1_REQ_STS) {
264 rc = qpnp_adc_tm_write_reg(QPNP_EN_CTL1, 0);
265 if (rc < 0)
266 pr_err("adc-tm disable failed\n");
267 }
268
269 return rc;
270}
271
272static int32_t qpnp_adc_tm_mode_select(u8 mode_ctl)
273{
274 int rc;
275
276 /* VADC_BTM current sets mode to recurring measurements */
277 rc = qpnp_adc_tm_write_reg(QPNP_MODE_CTL, mode_ctl);
278 if (rc < 0)
279 pr_err("adc-tm write mode selection err\n");
280
281 return rc;
282}
283
284static int32_t qpnp_adc_tm_timer_interval_select(
285 struct qpnp_vadc_chan_properties *chan_prop)
286{
287 int rc;
288 u8 meas_interval_timer2 = 0;
289
290 /* Configure USB_ID to timer1, batt_therm to timer2 */
291 switch (chan_prop->timer_select) {
292 case ADC_MEAS_TIMER_SELECT1:
293 rc = qpnp_adc_tm_write_reg(QPNP_ADC_TM_MEAS_INTERVAL_CTL,
294 chan_prop->meas_interval1);
295 if (rc < 0) {
296 pr_err("timer1 configure failed\n");
297 return rc;
298 }
299 break;
300 case ADC_MEAS_TIMER_SELECT2:
301 rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_MEAS_INTERVAL_CTL2,
302 &meas_interval_timer2);
303 if (rc < 0) {
304 pr_err("timer2 configure read failed\n");
305 return rc;
306 }
307 meas_interval_timer2 |=
308 (chan_prop->meas_interval2 <<
309 QPNP_ADC_TM_MEAS_INTERVAL_CTL2_SHIFT);
310 rc = qpnp_adc_tm_write_reg(QPNP_ADC_TM_MEAS_INTERVAL_CTL2,
311 meas_interval_timer2);
312 if (rc < 0) {
313 pr_err("timer2 configure failed\n");
314 return rc;
315 }
316 break;
317 case ADC_MEAS_TIMER_SELECT3:
318 /* Thermal channels uses timer3, default to 1 second */
319 rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_MEAS_INTERVAL_CTL2,
320 &meas_interval_timer2);
321 if (rc < 0) {
322 pr_err("timer3 read failed\n");
323 return rc;
324 }
325 chan_prop->meas_interval2 = ADC_MEAS3_INTERVAL_1S;
326 meas_interval_timer2 |= chan_prop->meas_interval2;
327 rc = qpnp_adc_tm_write_reg(QPNP_ADC_TM_MEAS_INTERVAL_CTL2,
328 meas_interval_timer2);
329 if (rc < 0) {
330 pr_err("timer3 configure failed\n");
331 return rc;
332 }
333 break;
334 default:
335 pr_err("Invalid timer selection\n");
336 return -EINVAL;
337 }
338
339 return rc;
340}
341
342static int32_t qpnp_adc_tm_meas_int_update(uint16_t reg_addr_src,
343 u8 reg_addr_dst, bool state)
344{
345 u8 bit_mask_check = 0;
346 int rc = 0;
347
348 rc = qpnp_adc_tm_read_reg(reg_addr_src, &bit_mask_check);
349 if (rc < 0) {
350 pr_err("read failed for addr:%x\n", reg_addr_src);
351 return rc;
352 }
353
354 if (state)
355 bit_mask_check |= reg_addr_dst;
356 else
357 bit_mask_check &= ~reg_addr_dst;
358
359 rc = qpnp_adc_tm_write_reg(reg_addr_src, bit_mask_check);
360 if (rc < 0)
361 pr_err("write failed for addr:%x\n", reg_addr_src);
362
363 return rc;
364}
365
366static int32_t qpnp_adc_tm_usbid_btm_thr_en(uint32_t btm_chan,
367 struct qpnp_vadc_chan_properties *chan_prop)
368{
369 int rc = 0;
370
371 rc = qpnp_adc_tm_write_reg(
372 adc_tm_data[btm_chan].low_thr_lsb_addr,
373 QPNP_ADC_TM_THR_LSB_MASK(chan_prop->low_thr));
374 if (rc < 0) {
375 pr_err("low threshold lsb setting failed\n");
376 return rc;
377 }
378
379 rc = qpnp_adc_tm_write_reg(
380 adc_tm_data[btm_chan].low_thr_msb_addr,
381 QPNP_ADC_TM_THR_MSB_MASK(chan_prop->low_thr));
382 if (rc < 0) {
383 pr_err("low threshold msb setting failed\n");
384 return rc;
385 }
386
387 rc = qpnp_adc_tm_write_reg(
388 adc_tm_data[btm_chan].high_thr_lsb_addr,
389 QPNP_ADC_TM_THR_LSB_MASK(chan_prop->high_thr));
390 if (rc < 0) {
391 pr_err("high threshold lsb setting failed\n");
392 return rc;
393 }
394
395 rc = qpnp_adc_tm_write_reg(
396 adc_tm_data[btm_chan].high_thr_msb_addr,
397 QPNP_ADC_TM_THR_MSB_MASK(chan_prop->high_thr));
398 if (rc < 0)
399 pr_err("high threshold msb setting failed\n");
400
401 return rc;
402}
403
404static int32_t qpnp_adc_tm_channel_configure(uint32_t btm_chan,
405 struct qpnp_vadc_chan_properties *chan_prop,
406 uint32_t amux_channel)
407{
408 int rc = 0;
409
410 switch (btm_chan) {
411 case QPNP_ADC_TM_M0_ADC_CH_SEL_CTL:
412 case QPNP_ADC_TM_M1_ADC_CH_SEL_CTL:
413 /* Update low and high notification thresholds */
414 rc = qpnp_adc_tm_usbid_btm_thr_en(btm_chan,
415 chan_prop);
416 if (rc < 0) {
417 pr_err("setting chan:%d threshold failed\n", btm_chan);
418 return rc;
419 }
420
421 if ((chan_prop->state_request ==
422 ADC_TM_LOW_THR_ENABLE) ||
423 (chan_prop->state_request ==
424 ADC_TM_HIGH_LOW_THR_ENABLE)) {
425 /* Enable low threshold's interrupt */
426 rc = qpnp_adc_tm_meas_int_update(
427 QPNP_ADC_TM_LOW_THR_INT_EN,
428 adc_tm_data[btm_chan].low_thr_int_chan_en,
429 true);
430 if (rc < 0) {
431 pr_err("low thr enable err:%d\n", btm_chan);
432 return rc;
433 }
434 }
435
436 if ((chan_prop->state_request ==
437 ADC_TM_HIGH_THR_ENABLE) ||
438 (chan_prop->state_request ==
439 ADC_TM_HIGH_LOW_THR_ENABLE)) {
440 /* Enable high threshold's interrupt */
441 rc = qpnp_adc_tm_meas_int_update(
442 QPNP_ADC_TM_HIGH_THR_INT_EN,
443 adc_tm_data[btm_chan].high_thr_int_chan_en,
444 true);
445 if (rc < 0) {
446 pr_err("high thr enable err:%d\n", btm_chan);
447 return rc;
448 }
449 }
450 /* intention fall through to configure common chan meas */
451 case QPNP_ADC_TM_M2_ADC_CH_SEL_CTL:
452 case QPNP_ADC_TM_M3_ADC_CH_SEL_CTL:
453 case QPNP_ADC_TM_M4_ADC_CH_SEL_CTL:
454 /* Configure AMUX control register for channel selection */
455 rc = qpnp_adc_tm_write_reg(btm_chan, amux_channel);
456 if (rc < 0) {
457 pr_err("btm_chan:%d selection failed\n", btm_chan);
458 return rc;
459 }
460
461 /* Enable corresponding BTM channel measurement */
462 rc = qpnp_adc_tm_meas_int_update(
463 QPNP_ADC_TM_MULTI_MEAS_EN,
464 adc_tm_data[btm_chan].multi_meas_en, true);
465 if (rc < 0) {
466 pr_err("multi measurement en failed\n");
467 return rc;
468 }
469 break;
470 default:
471 return -EINVAL;
472 }
473
474 return rc;
475}
476
477static int32_t qpnp_adc_tm_configure(
478 struct qpnp_adc_amux_properties *chan_prop)
479{
480 u8 decimation = 0;
481 int rc = 0;
482 uint32_t btm_chan = 0;
483
484 /* Check if a conversion is in progress */
485 rc = qpnp_adc_tm_enable_req_sts_check();
486 if (rc < 0) {
487 pr_err("adc-tm req_sts check failed\n");
488 return rc;
489 }
490
491 /* Set measurement in recurring mode */
492 rc = qpnp_adc_tm_mode_select(chan_prop->mode_sel);
493 if (rc < 0) {
494 pr_err("adc-tm mode select failed\n");
495 return rc;
496 }
497
498 /* Configure AMUX channel */
499 rc = qpnp_adc_tm_write_reg(QPNP_ADC_CH_SEL_CTL,
500 chan_prop->amux_channel);
501 if (rc < 0) {
502 pr_err("adc-tm channel selection err\n");
503 return rc;
504 }
505
506 /* Digital paramater setup */
507 decimation |= chan_prop->decimation <<
508 QPNP_ADC_DIG_DEC_RATIO_SEL_SHIFT;
509 rc = qpnp_adc_tm_write_reg(QPNP_ADC_DIG_PARAM, decimation);
510 if (rc < 0) {
511 pr_err("adc-tm digital parameter setup err\n");
512 return rc;
513 }
514
515 /* Hardware setting time */
516 rc = qpnp_adc_tm_write_reg(QPNP_HW_SETTLE_DELAY,
517 chan_prop->hw_settle_time);
518 if (rc < 0) {
519 pr_err("adc-tm hw settling time setup err\n");
520 return rc;
521 }
522
523 /* Fast averaging setup */
524 rc = qpnp_adc_tm_write_reg(QPNP_FAST_AVG_CTL,
525 chan_prop->fast_avg_setup);
526 if (rc < 0) {
527 pr_err("adc-tm fast-avg setup err\n");
528 return rc;
529 }
530
531 /* Measurement interval setup */
532 rc = qpnp_adc_tm_timer_interval_select(chan_prop->chan_prop);
533 if (rc < 0) {
534 pr_err("adc-tm timer select failed\n");
535 return rc;
536 }
537
538 /* Channel configuration setup */
539 btm_chan = chan_prop->chan_prop->tm_channel_select;
540 rc = qpnp_adc_tm_channel_configure(btm_chan, chan_prop->chan_prop,
541 chan_prop->amux_channel);
542 if (rc < 0) {
543 pr_err("adc-tm channel configure failed\n");
544 return rc;
545 }
546
547 /* Enable bank */
548 rc = qpnp_adc_tm_enable(true);
549 if (rc)
550 return rc;
551
552 /* Recurring interval measurement enable */
553 rc = qpnp_adc_tm_meas_int_update(QPNP_ADC_MEAS_INTERVAL_OP_CTL,
554 QPNP_ADC_MEAS_INTERVAL_OP, true);
555 if (rc < 0) {
556 pr_err("adc-tm meas interval op configure failed\n");
557 return rc;
558 }
559
560 /* Request conversion */
561 rc = qpnp_adc_tm_write_reg(QPNP_CONV_REQ, QPNP_CONV_REQ_SET);
562 if (rc < 0) {
563 pr_err("adc-tm request conversion failed\n");
564 return rc;
565 }
566
567 return 0;
568}
569
570static int qpnp_adc_tm_get_mode(struct thermal_zone_device *thermal,
571 enum thermal_device_mode *mode)
572{
573 struct qpnp_adc_tm_sensor *adc_tm = thermal->devdata;
574
575 if (!adc_tm || !mode)
576 return -EINVAL;
577
578 *mode = adc_tm->mode;
579
580 return 0;
581}
582
583static int qpnp_adc_tm_set_mode(struct thermal_zone_device *thermal,
584 enum thermal_device_mode mode)
585{
586 struct qpnp_adc_tm_sensor *adc_tm = thermal->devdata;
587 struct qpnp_adc_tm_drv *adc_drv = qpnp_adc_tm;
588 int rc = 0, channel;
589
590 if (!adc_tm)
591 return -EINVAL;
592
593 if (mode == THERMAL_DEVICE_ENABLED) {
594 adc_drv->adc->amux_prop->amux_channel = adc_tm->sensor_num;
595 channel = adc_tm->sensor_num;
596 adc_drv->adc->amux_prop->decimation =
597 adc_drv->adc->adc_channels[channel].adc_decimation;
598 adc_drv->adc->amux_prop->hw_settle_time =
599 adc_drv->adc->adc_channels[channel].hw_settle_time;
600 adc_drv->adc->amux_prop->fast_avg_setup =
601 adc_drv->adc->adc_channels[channel].fast_avg_setup;
602 adc_drv->adc->amux_prop->mode_sel =
603 ADC_OP_MEASUREMENT_INTERVAL << QPNP_OP_MODE_SHIFT;
604 adc_drv->adc->amux_prop->chan_prop->timer_select =
605 ADC_MEAS_TIMER_SELECT1;
606 adc_drv->adc->amux_prop->chan_prop->meas_interval1 =
607 ADC_MEAS1_INTERVAL_1S;
608 adc_drv->adc->amux_prop->chan_prop->low_thr = adc_tm->low_thr;
609 adc_drv->adc->amux_prop->chan_prop->high_thr = adc_tm->high_thr;
610 adc_drv->adc->amux_prop->chan_prop->tm_channel_select =
611 adc_tm->btm_channel_num;
612
613 rc = qpnp_adc_tm_configure(adc_drv->adc->amux_prop);
614 if (rc) {
615 pr_err("adc-tm tm configure failed with %d\n", rc);
616 return -EINVAL;
617 }
618 } else if (mode == THERMAL_DEVICE_DISABLED) {
619 rc = qpnp_adc_tm_meas_int_update(QPNP_ADC_TM_MULTI_MEAS_EN,
620 adc_tm_data[adc_tm->btm_channel_num].multi_meas_en,
621 false);
622 if (rc < 0) {
623 pr_err("multi measurement update failed\n");
624 return rc;
625 }
626
627 rc = qpnp_adc_tm_enable(false);
628 if (rc < 0) {
629 pr_err("adc-tm disable failed\n");
630 return rc;
631 }
632 }
633
634 adc_tm->mode = mode;
635
636 return 0;
637}
638
639static int qpnp_adc_tm_get_trip_type(struct thermal_zone_device *thermal,
640 int trip, enum thermal_trip_type *type)
641{
642 struct qpnp_adc_tm_sensor *adc_tm = thermal->devdata;
643
644 if (!adc_tm || !type || type < 0)
645 return -EINVAL;
646
647 switch (trip) {
648 case ADC_TM_TRIP_HIGH_WARM:
649 *type = THERMAL_TRIP_CONFIGURABLE_HI;
650 break;
651 case ADC_TM_TRIP_LOW_COOL:
652 *type = THERMAL_TRIP_CONFIGURABLE_LOW;
653 break;
654 default:
655 return -EINVAL;
656 }
657
658 return 0;
659}
660
661static int qpnp_adc_tm_get_trip_temp(struct thermal_zone_device *thermal,
662 int trip, unsigned long *temp)
663{
664 struct qpnp_adc_tm_sensor *adc_tm_sensor = thermal->devdata;
665 struct qpnp_adc_tm_drv *adc_tm = qpnp_adc_tm;
666 int64_t result = 0;
667 u8 trip_cool_thr0, trip_cool_thr1, trip_warm_thr0, trip_warm_thr1;
668 unsigned int reg, rc = 0, btm_channel_num;
669 uint16_t reg_low_thr_lsb, reg_low_thr_msb;
670 uint16_t reg_high_thr_lsb, reg_high_thr_msb;
671
672 if (!adc_tm)
673 return -EINVAL;
674
675 btm_channel_num = adc_tm_sensor->btm_channel_num;
676 reg_low_thr_lsb = adc_tm_data[btm_channel_num].low_thr_lsb_addr;
677 reg_low_thr_msb = adc_tm_data[btm_channel_num].low_thr_msb_addr;
678 reg_high_thr_lsb = adc_tm_data[btm_channel_num].high_thr_lsb_addr;
679 reg_high_thr_msb = adc_tm_data[btm_channel_num].high_thr_msb_addr;
680
681 switch (trip) {
682 case ADC_TM_TRIP_HIGH_WARM:
683 rc = qpnp_adc_tm_read_reg(reg_low_thr_lsb, &trip_warm_thr0);
684 if (rc) {
685 pr_err("adc-tm low_thr_lsb err\n");
686 return rc;
687 }
688
689 rc = qpnp_adc_tm_read_reg(reg_low_thr_msb, &trip_warm_thr1);
690 if (rc) {
691 pr_err("adc-tm low_thr_msb err\n");
692 return rc;
693 }
694 reg = (trip_warm_thr1 << 8) | trip_warm_thr0;
695 break;
696 case ADC_TM_TRIP_LOW_COOL:
697 rc = qpnp_adc_tm_read_reg(reg_high_thr_lsb, &trip_cool_thr0);
698 if (rc) {
699 pr_err("adc-tm_tm high_thr_lsb err\n");
700 return rc;
701 }
702
703 rc = qpnp_adc_tm_read_reg(reg_high_thr_msb, &trip_cool_thr1);
704 if (rc) {
705 pr_err("adc-tm_tm high_thr_lsb err\n");
706 return rc;
707 }
708 reg = (trip_cool_thr1 << 8) | trip_cool_thr0;
709 break;
710 default:
711 return -EINVAL;
712 }
713
714 rc = qpnp_adc_tm_scale_voltage_therm_pu2(reg, &result);
715 if (rc < 0) {
716 pr_err("Failed to lookup the therm thresholds\n");
717 return rc;
718 }
719
720 *temp = result;
721
722 return 0;
723}
724
725static int qpnp_adc_tm_set_trip_temp(struct thermal_zone_device *thermal,
726 int trip, long temp)
727{
728 struct qpnp_adc_tm_sensor *adc_tm_sensor = thermal->devdata;
729 struct qpnp_adc_tm_drv *adc_tm = qpnp_adc_tm;
730 struct qpnp_adc_tm_config tm_config;
731 u8 trip_cool_thr0, trip_cool_thr1, trip_warm_thr0, trip_warm_thr1;
732 uint16_t reg_low_thr_lsb, reg_low_thr_msb;
733 uint16_t reg_high_thr_lsb, reg_high_thr_msb;
734 int rc = 0, btm_channel_num;
735
736 if (!adc_tm)
737 return -EINVAL;
738
739 tm_config.channel = adc_tm_sensor->sensor_num;
740 switch (trip) {
741 case ADC_TM_TRIP_HIGH_WARM:
742 tm_config.high_thr_temp = temp;
743 break;
744 case ADC_TM_TRIP_LOW_COOL:
745 tm_config.low_thr_temp = temp;
746 break;
747 default:
748 return -EINVAL;
749 }
750
751 rc = qpnp_adc_tm_scale_therm_voltage_pu2(&tm_config);
752 if (rc < 0) {
753 pr_err("Failed to lookup the adc-tm thresholds\n");
754 return rc;
755 }
756
757 trip_warm_thr0 = ((tm_config.low_thr_voltage << 24) >> 24);
758 trip_warm_thr1 = ((tm_config.low_thr_voltage << 16) >> 24);
759 trip_cool_thr0 = ((tm_config.high_thr_voltage << 24) >> 24);
760 trip_cool_thr1 = ((tm_config.high_thr_voltage << 16) >> 24);
761
762 btm_channel_num = adc_tm_sensor->btm_channel_num;
763 reg_low_thr_lsb = adc_tm_data[btm_channel_num].low_thr_lsb_addr;
764 reg_low_thr_msb = adc_tm_data[btm_channel_num].low_thr_msb_addr;
765 reg_high_thr_lsb = adc_tm_data[btm_channel_num].high_thr_lsb_addr;
766 reg_high_thr_msb = adc_tm_data[btm_channel_num].high_thr_msb_addr;
767
768 switch (trip) {
769 case ADC_TM_TRIP_HIGH_WARM:
770 rc = qpnp_adc_tm_write_reg(reg_low_thr_lsb, trip_cool_thr0);
771 if (rc) {
772 pr_err("adc-tm_tm read threshold err\n");
773 return rc;
774 }
775
776 rc = qpnp_adc_tm_write_reg(reg_low_thr_msb, trip_cool_thr1);
777 if (rc) {
778 pr_err("adc-tm_tm read threshold err\n");
779 return rc;
780 }
781 adc_tm_sensor->low_thr = tm_config.high_thr_voltage;
782 break;
783 case ADC_TM_TRIP_LOW_COOL:
784 rc = qpnp_adc_tm_write_reg(reg_high_thr_lsb, trip_warm_thr0);
785 if (rc) {
786 pr_err("adc-tm_tm read threshold err\n");
787 return rc;
788 }
789
790 rc = qpnp_adc_tm_write_reg(reg_high_thr_msb, trip_warm_thr1);
791 if (rc) {
792 pr_err("adc-tm_tm read threshold err\n");
793 return rc;
794 }
795 adc_tm_sensor->high_thr = tm_config.low_thr_voltage;
796 break;
797 default:
798 return -EINVAL;
799 }
800
801 return 0;
802}
803
804static void notify_uspace_qpnp_adc_tm_fn(struct work_struct *work)
805{
806 struct qpnp_adc_tm_sensor *adc_tm = container_of(work,
807 struct qpnp_adc_tm_sensor, work);
808
809 sysfs_notify(&adc_tm->tz_dev->device.kobj,
810 NULL, "btm");
811}
812
813static void notify_usb_fn(struct work_struct *work)
814{
815 struct qpnp_adc_tm_drv *adc_tm = container_of(work,
816 struct qpnp_adc_tm_drv, usbid_work);
817 int rc;
818 u8 status_low, status_high;
819
820 if (adc_tm->usb_id_param->threshold_notification != NULL) {
821 rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_STATUS_LOW,
822 &status_low);
823 if (rc) {
824 pr_err("adc-tm read low status failed\n");
825 return;
826 }
827
828 rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_STATUS_HIGH,
829 &status_high);
830 if (rc) {
831 pr_err("adc-tm read high status failed\n");
832 return;
833 }
834
835 if (status_low & 1)
836 adc_tm->usb_id_param->threshold_notification(
837 ADC_TM_LOW_STATE, adc_tm->usb_id_param->usbid_ctx);
838 else if (status_high & 1)
839 adc_tm->usb_id_param->threshold_notification(
840 ADC_TM_HIGH_STATE, adc_tm->usb_id_param->usbid_ctx);
841 }
842
843 return;
844}
845
846static void notify_batt_fn(struct work_struct *work)
847{
848 struct qpnp_adc_tm_drv *adc_tm = container_of(work,
849 struct qpnp_adc_tm_drv, batt_work);
850 int rc;
851 u8 status_low, status_high;
852
853 if (adc_tm->battery_param->threshold_notification != NULL) {
854 rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_STATUS_LOW,
855 &status_low);
856 if (rc) {
857 pr_err("adc-tm read low status failed\n");
858 return;
859 }
860
861 rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_STATUS_HIGH,
862 &status_high);
863 if (rc) {
864 pr_err("adc-tm read high status failed\n");
865 return;
866 }
867
868 if (status_low & QPNP_ADC_TM_LOW_THR_INT_EN_M1)
869 adc_tm->battery_param->threshold_notification(
Siddartha Mohanadossd71e2402013-02-01 17:36:23 -0800870 ADC_TM_LOW_STATE, adc_tm->battery_param->btm_ctx);
Siddartha Mohanadoss31f60962012-11-27 14:11:02 -0800871 else if (status_high & QPNP_ADC_TM_HIGH_THR_INT_EN_M1)
872 adc_tm->battery_param->threshold_notification(
Siddartha Mohanadossd71e2402013-02-01 17:36:23 -0800873 ADC_TM_HIGH_STATE, adc_tm->battery_param->btm_ctx);
Siddartha Mohanadoss31f60962012-11-27 14:11:02 -0800874 }
875
876 return;
877}
878
879static int qpnp_adc_tm_activate_trip_type_fn(uint32_t btm_channel_num,
880 enum thermal_trip_activation_mode mode, u8 *data, uint32_t reg)
881{
882 u8 thr_int = 0;
883 int rc = 0;
884
885 rc = qpnp_adc_tm_read_reg(reg, &thr_int);
886 if (rc) {
887 pr_err("multi meas read failed\n");
888 return rc;
889 }
890
891 thr_int = adc_tm_data[btm_channel_num].low_thr_int_chan_en;
892
893 if (mode == THERMAL_TRIP_ACTIVATION_ENABLED)
894 thr_int |= *data;
895 else
896 thr_int &= ~*data;
897
898 rc = qpnp_adc_tm_write_reg(reg, thr_int);
899 if (rc)
900 pr_err("multi meas write failed\n");
901
902 return rc;
903}
904
905static int qpnp_adc_tm_activate_trip_type(struct thermal_zone_device *thermal,
906 int trip, enum thermal_trip_activation_mode mode)
907{
908 struct qpnp_adc_tm_sensor *adc_tm = thermal->devdata;
909 int rc = 0;
910 u8 thr_int_en = 0;
911
912 if (!adc_tm)
913 return -EINVAL;
914
915 switch (trip) {
916 case ADC_TM_TRIP_HIGH_WARM:
917 thr_int_en = adc_tm_data[adc_tm->btm_channel_num].
918 low_thr_int_chan_en;
919 rc = qpnp_adc_tm_activate_trip_type_fn(adc_tm->btm_channel_num,
920 mode, &thr_int_en, QPNP_ADC_TM_LOW_THR_INT_EN);
921 if (rc)
922 pr_err("channel:%x failed\n", adc_tm->btm_channel_num);
923 break;
924 case ADC_TM_TRIP_LOW_COOL:
925 thr_int_en = adc_tm_data[adc_tm->btm_channel_num].
926 high_thr_int_chan_en;
927 rc = qpnp_adc_tm_activate_trip_type_fn(adc_tm->btm_channel_num,
928 mode, &thr_int_en, QPNP_ADC_TM_HIGH_THR_INT_EN);
929 if (rc)
930 pr_err("channel:%x failed\n", adc_tm->btm_channel_num);
931 break;
932 default:
933 return -EINVAL;
934 }
935
936 return rc;
937}
938
939static int qpnp_adc_tm_read_status(void)
940{
941 struct qpnp_adc_tm_drv *adc_tm = qpnp_adc_tm;
942 u8 status_low = 0, status_high = 0, qpnp_adc_tm_meas_en = 0;
943 u8 adc_tm_low_enable = 0, adc_tm_high_enable = 0;
944 u8 thr_int_disable = 0;
945 int rc = 0, sensor_notify_num = 0;
946
Siddartha Mohanadossb60f6462012-11-20 18:06:51 -0800947 if (!adc_tm || !adc_tm->adc_tm_initialized)
948 return -ENODEV;
949
Siddartha Mohanadoss31f60962012-11-27 14:11:02 -0800950 rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_STATUS_LOW, &status_low);
951 if (rc) {
952 pr_err("adc-tm-tm read status low failed with %d\n", rc);
953 goto fail;
954 }
955
956 rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_STATUS_HIGH, &status_high);
957 if (rc) {
958 pr_err("adc-tm-tm read status high failed with %d\n", rc);
959 goto fail;
960 }
961
962 /* Check which interrupt threshold is lower and measure against the
963 * enabled channel */
964 rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_MULTI_MEAS_EN,
965 &qpnp_adc_tm_meas_en);
966 if (rc) {
967 pr_err("adc-tm-tm read status high failed with %d\n", rc);
968 goto fail;
969 }
970
971 adc_tm_low_enable = qpnp_adc_tm_meas_en & status_low;
972 adc_tm_high_enable = qpnp_adc_tm_meas_en & status_high;
973
974 if (adc_tm_high_enable) {
975 sensor_notify_num = (adc_tm_high_enable >> 3);
976 switch (adc_tm_high_enable) {
977 case 1:
978 case 2:
979 {
980 if (adc_tm_high_enable == 1)
981 thr_int_disable =
982 QPNP_ADC_TM_HIGH_THR_INT_EN_M0;
983 else if (adc_tm_high_enable == 2)
984 thr_int_disable =
985 QPNP_ADC_TM_HIGH_THR_INT_EN_M1;
986
987 rc = qpnp_adc_tm_meas_int_update(
988 QPNP_ADC_TM_HIGH_THR_INT_EN,
989 thr_int_disable, false);
990 if (rc < 0) {
991 pr_err("high threshold int read failed\n");
992 goto fail;
993 }
994
995 if (adc_tm_high_enable == 1)
996 schedule_work(&adc_tm->usbid_work);
997 else if (adc_tm_high_enable == 2)
998 schedule_work(&adc_tm->batt_work);
999 }
1000 break;
1001 case 4:
1002 case 8:
1003 case 16:
1004 {
1005 /* High voltage threshold is triggered by low temp */
1006 rc = qpnp_adc_tm_activate_trip_type(
1007 adc_tm->sensor[sensor_notify_num].tz_dev,
1008 ADC_TM_TRIP_LOW_COOL,
1009 THERMAL_TRIP_ACTIVATION_DISABLED);
1010 if (rc < 0) {
1011 pr_err("notify error:%d\n", sensor_notify_num);
1012 goto fail;
1013 }
1014 schedule_work(&adc_tm->sensor[sensor_notify_num].work);
1015 }
1016 break;
1017 default:
1018 rc = -EINVAL;
1019 }
1020 }
1021
1022 if (adc_tm_low_enable) {
1023 sensor_notify_num = (adc_tm_low_enable >> 3);
1024 switch (adc_tm_low_enable) {
1025 case 1:
1026 case 2:
1027 {
1028 if (adc_tm_low_enable == 1)
1029 thr_int_disable = QPNP_ADC_TM_LOW_THR_INT_EN_M0;
1030 else if (adc_tm_low_enable == 2)
1031 thr_int_disable = QPNP_ADC_TM_LOW_THR_INT_EN_M1;
1032
1033 rc = qpnp_adc_tm_meas_int_update(
1034 QPNP_ADC_TM_LOW_THR_INT_EN,
1035 thr_int_disable, false);
1036 if (rc < 0) {
1037 pr_err("low threshold int disable failed\n");
1038 goto fail;
1039 }
1040
1041 if (adc_tm_low_enable == 1)
1042 schedule_work(&adc_tm->usbid_work);
1043 else if (adc_tm_low_enable == 2)
1044 schedule_work(&adc_tm->batt_work);
1045 }
1046 break;
1047 case 4:
1048 case 8:
1049 case 16:
1050 {
1051 /* Low voltage threshold is triggered by high temp */
1052 rc = qpnp_adc_tm_activate_trip_type(
1053 adc_tm->sensor[sensor_notify_num].tz_dev,
1054 ADC_TM_TRIP_HIGH_WARM,
1055 THERMAL_TRIP_ACTIVATION_DISABLED);
1056 if (rc < 0) {
1057 pr_err("notify error:%d\n", sensor_notify_num);
1058 goto fail;
1059 }
1060 schedule_work(&adc_tm->sensor[sensor_notify_num].work);
1061 }
1062 break;
1063 default:
1064 rc = -EINVAL;
1065 }
1066 }
1067
1068fail:
1069 return rc;
1070}
1071
1072static void qpnp_adc_tm_high_thr_work(struct work_struct *work)
1073{
1074 int rc;
1075
1076 rc = qpnp_adc_tm_read_status();
1077
1078 return;
1079}
1080DECLARE_WORK(trigger_completion_adc_tm_high_thr_work,
1081 qpnp_adc_tm_high_thr_work);
1082
1083static irqreturn_t qpnp_adc_tm_high_thr_isr(int irq, void *data)
1084{
1085 schedule_work(&trigger_completion_adc_tm_high_thr_work);
1086
1087 return IRQ_HANDLED;
1088}
1089
1090static void qpnp_adc_tm_low_thr_work(struct work_struct *work)
1091{
1092 int rc;
1093
1094 rc = qpnp_adc_tm_read_status();
1095
1096 return;
1097}
1098DECLARE_WORK(trigger_completion_adc_tm_low_thr_work, qpnp_adc_tm_low_thr_work);
1099
1100static irqreturn_t qpnp_adc_tm_low_thr_isr(int irq, void *data)
1101{
1102 schedule_work(&trigger_completion_adc_tm_low_thr_work);
1103
1104 return IRQ_HANDLED;
1105}
1106
1107static irqreturn_t qpnp_adc_tm_isr(int irq, void *dev_id)
1108{
1109 struct qpnp_adc_tm_drv *adc_tm = dev_id;
1110
1111 complete(&adc_tm->adc->adc_rslt_completion);
1112
1113 return IRQ_HANDLED;
1114}
1115
1116static int qpnp_adc_read_temp(struct thermal_zone_device *thermal,
1117 unsigned long *temp)
1118{
1119 struct qpnp_adc_tm_sensor *adc_tm_sensor = thermal->devdata;
1120 struct qpnp_vadc_result result;
1121 int rc = 0;
1122
1123 rc = qpnp_vadc_read(adc_tm_sensor->sensor_num, &result);
1124 if (rc)
1125 return rc;
1126
1127 *temp = result.physical;
1128
1129 return rc;
1130}
1131
1132static struct thermal_zone_device_ops qpnp_adc_tm_thermal_ops = {
1133 .get_temp = qpnp_adc_read_temp,
1134 .get_mode = qpnp_adc_tm_get_mode,
1135 .set_mode = qpnp_adc_tm_set_mode,
1136 .get_trip_type = qpnp_adc_tm_get_trip_type,
1137 .activate_trip_type = qpnp_adc_tm_activate_trip_type,
1138 .get_trip_temp = qpnp_adc_tm_get_trip_temp,
1139 .set_trip_temp = qpnp_adc_tm_set_trip_temp,
1140};
1141
1142int32_t qpnp_adc_tm_usbid_configure(struct qpnp_adc_tm_usbid_param *param)
1143{
1144 struct qpnp_adc_tm_drv *adc_tm = qpnp_adc_tm;
1145 uint32_t channel;
1146 int rc = 0;
1147
1148 if (!adc_tm || !adc_tm->adc_tm_initialized)
1149 return -ENODEV;
1150
1151 if (param->threshold_notification == NULL) {
1152 pr_err("No USB_ID high/low voltage notificaton??\n");
1153 return -EINVAL;
1154 }
1155
1156 mutex_lock(&adc_tm->adc->adc_lock);
1157
1158 adc_tm->adc->amux_prop->amux_channel = LR_MUX10_PU2_AMUX_USB_ID_LV;
1159 channel = LR_MUX10_PU2_AMUX_USB_ID_LV;
1160 adc_tm->adc->amux_prop->decimation =
1161 adc_tm->adc->adc_channels[channel].adc_decimation;
1162 adc_tm->adc->amux_prop->hw_settle_time =
1163 adc_tm->adc->adc_channels[channel].hw_settle_time;
1164 adc_tm->adc->amux_prop->fast_avg_setup =
1165 adc_tm->adc->adc_channels[channel].fast_avg_setup;
1166 adc_tm->adc->amux_prop->mode_sel =
1167 ADC_OP_MEASUREMENT_INTERVAL << QPNP_OP_MODE_SHIFT;
1168 adc_tm->adc->amux_prop->chan_prop->meas_interval1 =
1169 ADC_MEAS1_INTERVAL_1S;
1170 qpnp_adc_usb_scaler(param, &adc_tm->adc->amux_prop->chan_prop->low_thr,
1171 &adc_tm->adc->amux_prop->chan_prop->high_thr);
1172 adc_tm->adc->amux_prop->chan_prop->tm_channel_select =
1173 QPNP_ADC_TM_M0_ADC_CH_SEL_CTL;
1174 adc_tm->adc->amux_prop->chan_prop->timer_select =
1175 ADC_MEAS_TIMER_SELECT1;
1176 adc_tm->adc->amux_prop->chan_prop->state_request =
1177 param->state_request;
1178 rc = qpnp_adc_tm_configure(adc_tm->adc->amux_prop);
1179 if (rc) {
1180 pr_err("adc-tm configure failed with %d\n", rc);
1181 goto fail_unlock;
1182 }
1183
1184 adc_tm->usb_id_param = param;
1185
1186fail_unlock:
1187 mutex_unlock(&adc_tm->adc->adc_lock);
1188
1189 return rc;
1190}
1191EXPORT_SYMBOL(qpnp_adc_tm_usbid_configure);
1192
1193static int32_t qpnp_adc_tm_chan_usbid_chan_btm_end(
1194 uint32_t btm_chan_num)
1195{
1196 int32_t rc = 0;
1197
1198 rc = qpnp_adc_tm_meas_int_update(QPNP_ADC_TM_LOW_THR_INT_EN,
1199 adc_tm_data[btm_chan_num].low_thr_int_chan_en,
1200 false);
1201 if (rc < 0) {
1202 pr_err("low threshold int write failed\n");
1203 return rc;
1204 }
1205
1206 rc = qpnp_adc_tm_meas_int_update(QPNP_ADC_TM_HIGH_THR_INT_EN,
1207 adc_tm_data[btm_chan_num].high_thr_int_chan_en,
1208 false);
1209 if (rc < 0) {
1210 pr_err("high threshold int enable failed\n");
1211 return rc;
1212 }
1213
1214 rc = qpnp_adc_tm_meas_int_update(QPNP_ADC_TM_MULTI_MEAS_EN,
1215 adc_tm_data[btm_chan_num].multi_meas_en,
1216 false);
1217 if (rc < 0) {
1218 pr_err("multi measurement en failed\n");
1219 return rc;
1220 }
1221
1222 rc = qpnp_adc_tm_enable(false);
1223 if (rc < 0)
1224 pr_err("TM disable failed\n");
1225
1226 return rc;
1227}
1228
1229int32_t qpnp_adc_tm_usbid_end(void)
1230{
1231 struct qpnp_adc_tm_drv *adc_tm = qpnp_adc_tm;
1232 int rc = 0;
1233
1234 if (!adc_tm || !adc_tm->adc_tm_initialized)
1235 return -ENODEV;
1236
1237 mutex_lock(&adc_tm->adc->adc_lock);
1238
1239 rc = qpnp_adc_tm_chan_usbid_chan_btm_end(
1240 QPNP_ADC_TM_M0_ADC_CH_SEL_CTL);
1241 if (rc < 0)
1242 pr_err("disabling thresholds for usb channel failed\n");
1243
1244 mutex_unlock(&adc_tm->adc->adc_lock);
1245
1246 return rc;
1247}
1248EXPORT_SYMBOL(qpnp_adc_tm_usbid_end);
1249
1250int32_t qpnp_adc_tm_btm_configure(struct qpnp_adc_tm_btm_param *param)
1251{
1252 struct qpnp_adc_tm_drv *adc_tm = qpnp_adc_tm;
1253 uint32_t channel;
1254 int rc = 0;
1255
1256 if (!adc_tm || !adc_tm->adc_tm_initialized)
1257 return -ENODEV;
1258
1259 if (param->threshold_notification == NULL) {
1260 pr_err("No battery high/low temp notificaton??\n");
1261 return -EINVAL;
1262 }
1263
1264 mutex_lock(&adc_tm->adc->adc_lock);
1265
1266 adc_tm->adc->amux_prop->amux_channel = LR_MUX1_BATT_THERM;
1267 channel = LR_MUX1_BATT_THERM;
1268 adc_tm->adc->amux_prop->decimation =
1269 adc_tm->adc->adc_channels[channel].adc_decimation;
1270 adc_tm->adc->amux_prop->hw_settle_time =
1271 adc_tm->adc->adc_channels[channel].hw_settle_time;
1272 adc_tm->adc->amux_prop->fast_avg_setup =
1273 adc_tm->adc->adc_channels[channel].fast_avg_setup;
1274 adc_tm->adc->amux_prop->mode_sel =
1275 ADC_OP_MEASUREMENT_INTERVAL << QPNP_OP_MODE_SHIFT;
1276 adc_tm->adc->amux_prop->chan_prop->meas_interval2 =
1277 ADC_MEAS2_INTERVAL_1S;
1278 qpnp_adc_btm_scaler(param, &adc_tm->adc->amux_prop->chan_prop->low_thr,
1279 &adc_tm->adc->amux_prop->chan_prop->high_thr);
1280 adc_tm->adc->amux_prop->chan_prop->tm_channel_select =
1281 QPNP_ADC_TM_M1_ADC_CH_SEL_CTL;
1282 adc_tm->adc->amux_prop->chan_prop->timer_select =
1283 ADC_MEAS_TIMER_SELECT2;
1284 adc_tm->adc->amux_prop->chan_prop->state_request =
1285 param->state_request;
1286 rc = qpnp_adc_tm_configure(adc_tm->adc->amux_prop);
1287 if (rc) {
1288 pr_err("adc-tm configure failed with %d\n", rc);
1289 goto fail_unlock;
1290 }
1291
1292 adc_tm->battery_param = param;
1293
1294fail_unlock:
1295 mutex_unlock(&adc_tm->adc->adc_lock);
1296
1297 return rc;
1298}
1299EXPORT_SYMBOL(qpnp_adc_tm_btm_configure);
1300
1301int32_t qpnp_adc_tm_btm_end(void)
1302{
1303 struct qpnp_adc_tm_drv *adc_tm = qpnp_adc_tm;
1304 int rc = 0;
1305
1306 if (!adc_tm || !adc_tm->adc_tm_initialized)
1307 return -ENODEV;
1308
1309 mutex_lock(&adc_tm->adc->adc_lock);
1310
1311 rc = qpnp_adc_tm_chan_usbid_chan_btm_end(
1312 QPNP_ADC_TM_M1_ADC_CH_SEL_CTL);
1313 if (rc < 0)
1314 pr_err("disabling thresholds for batt channel failed\n");
1315
1316 mutex_unlock(&adc_tm->adc->adc_lock);
1317
1318 return rc;
1319}
1320EXPORT_SYMBOL(qpnp_adc_tm_btm_end);
1321
1322int32_t qpnp_adc_tm_is_ready(void)
1323{
1324 struct qpnp_adc_tm_drv *adc_tm = qpnp_adc_tm;
1325
1326 if (!adc_tm || !adc_tm->adc_tm_initialized)
1327 return -EPROBE_DEFER;
1328 else
1329 return 0;
1330}
1331EXPORT_SYMBOL(qpnp_adc_tm_is_ready);
1332
1333static int __devinit qpnp_adc_tm_probe(struct spmi_device *spmi)
1334{
1335 struct device_node *node = spmi->dev.of_node, *child;
1336 struct qpnp_adc_tm_drv *adc_tm;
1337 struct qpnp_adc_drv *adc_qpnp;
1338 int32_t count_adc_channel_list = 0, rc, i = 0, j = 0;
1339 u8 thr_init = 0;
1340
1341 if (!node)
1342 return -EINVAL;
1343
1344 if (qpnp_adc_tm) {
1345 pr_err("adc-tm already in use\n");
1346 return -EBUSY;
1347 }
1348
1349 for_each_child_of_node(node, child)
1350 count_adc_channel_list++;
1351
1352 if (!count_adc_channel_list) {
1353 pr_err("No channel listing\n");
1354 return -EINVAL;
1355 }
1356
1357 adc_tm = devm_kzalloc(&spmi->dev, sizeof(struct qpnp_adc_tm_drv) +
1358 (count_adc_channel_list *
1359 sizeof(struct qpnp_adc_tm_sensor)),
1360 GFP_KERNEL);
1361 if (!adc_tm) {
1362 dev_err(&spmi->dev, "Unable to allocate memory\n");
1363 return -ENOMEM;
1364 }
1365
1366 adc_qpnp = devm_kzalloc(&spmi->dev, sizeof(struct qpnp_adc_drv),
1367 GFP_KERNEL);
1368 if (!adc_qpnp) {
1369 dev_err(&spmi->dev, "Unable to allocate memory\n");
Siddartha Mohanadossb60f6462012-11-20 18:06:51 -08001370 rc = -ENOMEM;
1371 goto fail;
Siddartha Mohanadoss31f60962012-11-27 14:11:02 -08001372 }
1373
1374 adc_tm->adc = adc_qpnp;
1375
1376 rc = qpnp_adc_get_devicetree_data(spmi, adc_tm->adc);
1377 if (rc) {
1378 dev_err(&spmi->dev, "failed to read device tree\n");
Siddartha Mohanadossb60f6462012-11-20 18:06:51 -08001379 goto fail;
Siddartha Mohanadoss31f60962012-11-27 14:11:02 -08001380 }
1381
1382 /* Register the ADC peripheral interrupt */
1383 adc_tm->adc->adc_high_thr_irq = spmi_get_irq_byname(spmi,
1384 NULL, "high-thr-en-set");
1385 if (adc_tm->adc->adc_high_thr_irq < 0) {
1386 pr_err("Invalid irq\n");
Siddartha Mohanadossb60f6462012-11-20 18:06:51 -08001387 rc = -ENXIO;
1388 goto fail;
Siddartha Mohanadoss31f60962012-11-27 14:11:02 -08001389 }
1390
1391 adc_tm->adc->adc_low_thr_irq = spmi_get_irq_byname(spmi,
1392 NULL, "low-thr-en-set");
1393 if (adc_tm->adc->adc_low_thr_irq < 0) {
1394 pr_err("Invalid irq\n");
Siddartha Mohanadossb60f6462012-11-20 18:06:51 -08001395 rc = -ENXIO;
1396 goto fail;
Siddartha Mohanadoss31f60962012-11-27 14:11:02 -08001397 }
1398
1399 rc = devm_request_irq(&spmi->dev, adc_tm->adc->adc_irq_eoc,
1400 qpnp_adc_tm_isr, IRQF_TRIGGER_RISING,
1401 "qpnp_adc_tm_interrupt", adc_tm);
1402 if (rc) {
1403 dev_err(&spmi->dev,
1404 "failed to request adc irq with error %d\n", rc);
Siddartha Mohanadossb60f6462012-11-20 18:06:51 -08001405 goto fail;
Siddartha Mohanadoss31f60962012-11-27 14:11:02 -08001406 } else {
1407 enable_irq_wake(adc_tm->adc->adc_irq_eoc);
1408 }
1409
1410 rc = devm_request_irq(&spmi->dev, adc_tm->adc->adc_high_thr_irq,
1411 qpnp_adc_tm_high_thr_isr,
1412 IRQF_TRIGGER_RISING, "qpnp_adc_tm_high_interrupt", adc_tm);
1413 if (rc) {
1414 dev_err(&spmi->dev, "failed to request adc irq\n");
Siddartha Mohanadossb60f6462012-11-20 18:06:51 -08001415 goto fail;
Siddartha Mohanadoss31f60962012-11-27 14:11:02 -08001416 } else {
1417 enable_irq_wake(adc_tm->adc->adc_high_thr_irq);
1418 }
1419
1420 rc = devm_request_irq(&spmi->dev, adc_tm->adc->adc_low_thr_irq,
1421 qpnp_adc_tm_low_thr_isr,
1422 IRQF_TRIGGER_RISING, "qpnp_adc_tm_low_interrupt", adc_tm);
1423 if (rc) {
1424 dev_err(&spmi->dev, "failed to request adc irq\n");
Siddartha Mohanadossb60f6462012-11-20 18:06:51 -08001425 goto fail;
Siddartha Mohanadoss31f60962012-11-27 14:11:02 -08001426 } else {
1427 enable_irq_wake(adc_tm->adc->adc_low_thr_irq);
1428 }
1429
1430 for_each_child_of_node(node, child) {
1431 char name[25];
1432 int btm_channel_num;
1433 rc = of_property_read_u32(child,
1434 "qcom,btm-channel-number", &btm_channel_num);
1435 if (rc) {
1436 pr_err("Invalid btm channel number\n");
Siddartha Mohanadossb60f6462012-11-20 18:06:51 -08001437 goto fail;
Siddartha Mohanadoss31f60962012-11-27 14:11:02 -08001438 }
1439
1440 if ((btm_channel_num != QPNP_ADC_TM_M0_ADC_CH_SEL_CTL) &&
1441 (btm_channel_num != QPNP_ADC_TM_M1_ADC_CH_SEL_CTL)) {
1442 /* Register with the thermal zone */
1443 adc_tm->sensor[i].mode = THERMAL_DEVICE_DISABLED;
1444 snprintf(name, sizeof(name), "qpnp_adc_tm_sensor%d", i);
1445 adc_tm->sensor[i].sensor_num =
1446 adc_tm->adc->adc_channels[j].channel_num;
1447 adc_tm->sensor[i].btm_channel_num = btm_channel_num;
1448 adc_tm->sensor[i].meas_interval =
1449 QPNP_ADC_TM_MEAS_INTERVAL;
1450 adc_tm->sensor[i].low_thr = QPNP_ADC_TM_M0_LOW_THR;
1451 adc_tm->sensor[i].high_thr = QPNP_ADC_TM_M0_HIGH_THR;
1452 adc_tm->sensor[i].tz_dev =
1453 thermal_zone_device_register(name,
1454 ADC_TM_TRIP_NUM,
1455 &adc_tm->sensor[i],
1456 &qpnp_adc_tm_thermal_ops, 0, 0, 0, 0);
1457 if (IS_ERR(adc_tm->sensor[i].tz_dev))
1458 pr_err("thermal device register failed.\n");
1459 INIT_WORK(&adc_tm->sensor[i].work,
1460 notify_uspace_qpnp_adc_tm_fn);
1461 i++;
1462 }
1463 j++;
1464 }
1465 INIT_WORK(&adc_tm->usbid_work, notify_usb_fn);
1466 INIT_WORK(&adc_tm->batt_work, notify_batt_fn);
1467 qpnp_adc_tm = adc_tm;
1468 dev_set_drvdata(&spmi->dev, adc_tm);
1469 rc = qpnp_adc_tm_write_reg(QPNP_ADC_TM_HIGH_THR_INT_EN, thr_init);
1470 if (rc < 0) {
1471 pr_err("high thr init failed\n");
Siddartha Mohanadossb60f6462012-11-20 18:06:51 -08001472 goto fail;
Siddartha Mohanadoss31f60962012-11-27 14:11:02 -08001473 }
1474
1475 rc = qpnp_adc_tm_write_reg(QPNP_ADC_TM_LOW_THR_INT_EN, thr_init);
1476 if (rc < 0) {
1477 pr_err("low thr init failed\n");
Siddartha Mohanadossb60f6462012-11-20 18:06:51 -08001478 goto fail;
Siddartha Mohanadoss31f60962012-11-27 14:11:02 -08001479 }
1480
1481 rc = qpnp_adc_tm_write_reg(QPNP_ADC_TM_MULTI_MEAS_EN, thr_init);
1482 if (rc < 0) {
1483 pr_err("multi meas en failed\n");
Siddartha Mohanadossb60f6462012-11-20 18:06:51 -08001484 goto fail;
Siddartha Mohanadoss31f60962012-11-27 14:11:02 -08001485 }
1486
1487 adc_tm->adc_tm_initialized = true;
1488
1489 return 0;
Siddartha Mohanadossb60f6462012-11-20 18:06:51 -08001490fail:
Siddartha Mohanadoss32019b52012-12-23 17:05:45 -08001491 qpnp_adc_tm = NULL;
Siddartha Mohanadossb60f6462012-11-20 18:06:51 -08001492 return rc;
Siddartha Mohanadoss31f60962012-11-27 14:11:02 -08001493}
1494
1495static int __devexit qpnp_adc_tm_remove(struct spmi_device *spmi)
1496{
1497 struct qpnp_adc_tm_drv *adc_tm = dev_get_drvdata(&spmi->dev);
1498 struct device_node *node = spmi->dev.of_node;
1499 struct device_node *child;
1500 int i = 0;
1501
1502 for_each_child_of_node(node, child) {
1503 thermal_zone_device_unregister(adc_tm->sensor[i].tz_dev);
1504 i++;
1505 }
1506
1507 adc_tm->adc_tm_initialized = false;
1508 dev_set_drvdata(&spmi->dev, NULL);
1509
1510 return 0;
1511}
1512
1513static const struct of_device_id qpnp_adc_tm_match_table[] = {
1514 { .compatible = "qcom,qpnp-adc-tm" },
1515 {}
1516};
1517
1518static struct spmi_driver qpnp_adc_tm_driver = {
1519 .driver = {
1520 .name = "qcom,qpnp-adc-tm",
1521 .of_match_table = qpnp_adc_tm_match_table,
1522 },
1523 .probe = qpnp_adc_tm_probe,
1524 .remove = qpnp_adc_tm_remove,
1525};
1526
1527static int __init qpnp_adc_tm_init(void)
1528{
1529 return spmi_driver_register(&qpnp_adc_tm_driver);
1530}
1531module_init(qpnp_adc_tm_init);
1532
1533static void __exit qpnp_adc_tm_exit(void)
1534{
1535 spmi_driver_unregister(&qpnp_adc_tm_driver);
1536}
1537module_exit(qpnp_adc_tm_exit);
1538
1539MODULE_DESCRIPTION("QPNP PMIC ADC Threshold Monitoring driver");
1540MODULE_LICENSE("GPL v2");