blob: 64ff2843afd8fc85d88f51cc8439b76d4b7a8037 [file] [log] [blame]
Jishnu Prakash04ee9ec2019-04-23 18:36:04 +05301/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002 *
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/regmap.h>
18#include <linux/of.h>
19#include <linux/err.h>
20#include <linux/init.h>
21#include <linux/slab.h>
22#include <linux/delay.h>
23#include <linux/mutex.h>
24#include <linux/types.h>
25#include <linux/hwmon.h>
26#include <linux/module.h>
27#include <linux/debugfs.h>
28#include <linux/spmi.h>
29#include <linux/platform_device.h>
30#include <linux/of_irq.h>
31#include <linux/interrupt.h>
32#include <linux/completion.h>
33#include <linux/hwmon-sysfs.h>
34#include <linux/qpnp/qpnp-adc.h>
35#include <linux/thermal.h>
36#include <linux/platform_device.h>
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -070037#include "thermal_core.h"
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -080038
39/* QPNP VADC TM register definition */
40#define QPNP_REVISION3 0x2
41#define QPNP_PERPH_SUBTYPE 0x5
42#define QPNP_PERPH_TYPE2 0x2
43#define QPNP_REVISION_EIGHT_CHANNEL_SUPPORT 2
44#define QPNP_PERPH_SUBTYPE_TWO_CHANNEL_SUPPORT 0x22
Prasad Malisetty358dda32018-02-20 06:14:26 +053045#define QPNP_STATUS1 0x8
46#define QPNP_STATUS1_OP_MODE 4
47#define QPNP_STATUS1_MEAS_INTERVAL_EN_STS BIT(2)
48#define QPNP_STATUS1_REQ_STS BIT(1)
49#define QPNP_STATUS1_EOC BIT(0)
50#define QPNP_STATUS2 0x9
51#define QPNP_STATUS2_CONV_SEQ_STATE 6
52#define QPNP_STATUS2_FIFO_NOT_EMPTY_FLAG BIT(1)
53#define QPNP_STATUS2_CONV_SEQ_TIMEOUT_STS BIT(0)
54#define QPNP_CONV_TIMEOUT_ERR 2
55
56#define QPNP_MODE_CTL 0x40
57#define QPNP_OP_MODE_SHIFT 3
58#define QPNP_VREF_XO_THM_FORCE BIT(2)
59#define QPNP_AMUX_TRIM_EN BIT(1)
60#define QPNP_ADC_TRIM_EN BIT(0)
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -080061#define QPNP_EN_CTL1 0x46
62#define QPNP_ADC_TM_EN BIT(7)
63#define QPNP_BTM_CONV_REQ 0x47
64#define QPNP_ADC_CONV_REQ_EN BIT(7)
65
Prasad Malisetty358dda32018-02-20 06:14:26 +053066#define QPNP_ADC_DIG_PARAM 0x50
67#define QPNP_ADC_DIG_DEC_RATIO_SEL_SHIFT 3
68#define QPNP_HW_SETTLE_DELAY 0x51
69#define QPNP_CONV_SEQ_CTL 0x54
70#define QPNP_CONV_SEQ_HOLDOFF_SHIFT 4
71#define QPNP_CONV_SEQ_TRIG_CTL 0x55
72#define QPNP_ADC_TM_MEAS_INTERVAL_CTL 0x57
73#define QPNP_ADC_TM_MEAS_INTERVAL_TIME_SHIFT 0x3
74#define QPNP_ADC_TM_MEAS_INTERVAL_CTL2 0x58
75#define QPNP_ADC_TM_MEAS_INTERVAL_CTL2_SHIFT 0x4
76#define QPNP_ADC_TM_MEAS_INTERVAL_CTL2_MASK 0xf0
77#define QPNP_ADC_TM_MEAS_INTERVAL_CTL3_MASK 0xf
78
79#define QPNP_ADC_MEAS_INTERVAL_OP_CTL 0x59
80#define QPNP_ADC_MEAS_INTERVAL_OP BIT(7)
81
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -070082#define QPNP_OP_MODE_SHIFT 3
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -080083#define QPNP_CONV_REQ 0x52
84#define QPNP_CONV_REQ_SET BIT(7)
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -080085
Prasad Malisetty358dda32018-02-20 06:14:26 +053086#define QPNP_FAST_AVG_CTL 0x5a
87#define QPNP_FAST_AVG_EN 0x5b
88#define QPNP_FAST_AVG_ENABLED BIT(7)
89
90#define QPNP_M0_LOW_THR_LSB 0x5c
91#define QPNP_M0_LOW_THR_MSB 0x5d
92#define QPNP_M0_HIGH_THR_LSB 0x5e
93#define QPNP_M0_HIGH_THR_MSB 0x5f
94#define QPNP_M1_ADC_CH_SEL_CTL 0x68
95#define QPNP_M1_LOW_THR_LSB 0x69
96#define QPNP_M1_LOW_THR_MSB 0x6a
97#define QPNP_M1_HIGH_THR_LSB 0x6b
98#define QPNP_M1_HIGH_THR_MSB 0x6c
99#define QPNP_M2_ADC_CH_SEL_CTL 0x70
100#define QPNP_M2_LOW_THR_LSB 0x71
101#define QPNP_M2_LOW_THR_MSB 0x72
102#define QPNP_M2_HIGH_THR_LSB 0x73
103#define QPNP_M2_HIGH_THR_MSB 0x74
104#define QPNP_M3_ADC_CH_SEL_CTL 0x78
105#define QPNP_M3_LOW_THR_LSB 0x79
106#define QPNP_M3_LOW_THR_MSB 0x7a
107#define QPNP_M3_HIGH_THR_LSB 0x7b
108#define QPNP_M3_HIGH_THR_MSB 0x7c
109#define QPNP_M4_ADC_CH_SEL_CTL 0x80
110#define QPNP_M4_LOW_THR_LSB 0x81
111#define QPNP_M4_LOW_THR_MSB 0x82
112#define QPNP_M4_HIGH_THR_LSB 0x83
113#define QPNP_M4_HIGH_THR_MSB 0x84
114#define QPNP_M5_ADC_CH_SEL_CTL 0x88
115#define QPNP_M5_LOW_THR_LSB 0x89
116#define QPNP_M5_LOW_THR_MSB 0x8a
117#define QPNP_M5_HIGH_THR_LSB 0x8b
118#define QPNP_M5_HIGH_THR_MSB 0x8c
119#define QPNP_M6_ADC_CH_SEL_CTL 0x90
120#define QPNP_M6_LOW_THR_LSB 0x91
121#define QPNP_M6_LOW_THR_MSB 0x92
122#define QPNP_M6_HIGH_THR_LSB 0x93
123#define QPNP_M6_HIGH_THR_MSB 0x94
124#define QPNP_M7_ADC_CH_SEL_CTL 0x98
125#define QPNP_M7_LOW_THR_LSB 0x99
126#define QPNP_M7_LOW_THR_MSB 0x9a
127#define QPNP_M7_HIGH_THR_LSB 0x9b
128#define QPNP_M7_HIGH_THR_MSB 0x9c
129
130#define QPNP_ADC_TM_MULTI_MEAS_EN 0x41
131#define QPNP_ADC_TM_MULTI_MEAS_EN_M0 BIT(0)
132#define QPNP_ADC_TM_MULTI_MEAS_EN_M1 BIT(1)
133#define QPNP_ADC_TM_MULTI_MEAS_EN_M2 BIT(2)
134#define QPNP_ADC_TM_MULTI_MEAS_EN_M3 BIT(3)
135#define QPNP_ADC_TM_MULTI_MEAS_EN_M4 BIT(4)
136#define QPNP_ADC_TM_MULTI_MEAS_EN_M5 BIT(5)
137#define QPNP_ADC_TM_MULTI_MEAS_EN_M6 BIT(6)
138#define QPNP_ADC_TM_MULTI_MEAS_EN_M7 BIT(7)
139#define QPNP_ADC_TM_LOW_THR_INT_EN 0x42
140#define QPNP_ADC_TM_LOW_THR_INT_EN_M0 BIT(0)
141#define QPNP_ADC_TM_LOW_THR_INT_EN_M1 BIT(1)
142#define QPNP_ADC_TM_LOW_THR_INT_EN_M2 BIT(2)
143#define QPNP_ADC_TM_LOW_THR_INT_EN_M3 BIT(3)
144#define QPNP_ADC_TM_LOW_THR_INT_EN_M4 BIT(4)
145#define QPNP_ADC_TM_LOW_THR_INT_EN_M5 BIT(5)
146#define QPNP_ADC_TM_LOW_THR_INT_EN_M6 BIT(6)
147#define QPNP_ADC_TM_LOW_THR_INT_EN_M7 BIT(7)
148#define QPNP_ADC_TM_HIGH_THR_INT_EN 0x43
149#define QPNP_ADC_TM_HIGH_THR_INT_EN_M0 BIT(0)
150#define QPNP_ADC_TM_HIGH_THR_INT_EN_M1 BIT(1)
151#define QPNP_ADC_TM_HIGH_THR_INT_EN_M2 BIT(2)
152#define QPNP_ADC_TM_HIGH_THR_INT_EN_M3 BIT(3)
153#define QPNP_ADC_TM_HIGH_THR_INT_EN_M4 BIT(4)
154#define QPNP_ADC_TM_HIGH_THR_INT_EN_M5 BIT(5)
155#define QPNP_ADC_TM_HIGH_THR_INT_EN_M6 BIT(6)
156#define QPNP_ADC_TM_HIGH_THR_INT_EN_M7 BIT(7)
157
158#define QPNP_ADC_TM_M0_MEAS_INTERVAL_CTL 0x59
159#define QPNP_ADC_TM_M1_MEAS_INTERVAL_CTL 0x6d
160#define QPNP_ADC_TM_M2_MEAS_INTERVAL_CTL 0x75
161#define QPNP_ADC_TM_M3_MEAS_INTERVAL_CTL 0x7d
162#define QPNP_ADC_TM_M4_MEAS_INTERVAL_CTL 0x85
163#define QPNP_ADC_TM_M5_MEAS_INTERVAL_CTL 0x8d
164#define QPNP_ADC_TM_M6_MEAS_INTERVAL_CTL 0x95
165#define QPNP_ADC_TM_M7_MEAS_INTERVAL_CTL 0x9d
166
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800167#define QPNP_ADC_TM_STATUS1 0x8
168#define QPNP_ADC_TM_STATUS_LOW 0xa
169#define QPNP_ADC_TM_STATUS_HIGH 0xb
170
171#define QPNP_ADC_TM_M0_LOW_THR 0x5d5c
172#define QPNP_ADC_TM_M0_HIGH_THR 0x5f5e
173#define QPNP_ADC_TM_MEAS_INTERVAL 0x0
174
175#define QPNP_ADC_TM_THR_LSB_MASK(val) (val & 0xff)
176#define QPNP_ADC_TM_THR_MSB_MASK(val) ((val & 0xff00) >> 8)
177
Prasad Malisetty358dda32018-02-20 06:14:26 +0530178#define QPNP_MIN_TIME 2000
179#define QPNP_MAX_TIME 2100
180#define QPNP_RETRY 1000
181
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800182/* QPNP ADC TM HC start */
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -0700183#define QPNP_BTM_HC_STATUS1 0x08
184#define QPNP_BTM_HC_STATUS_LOW 0x0a
185#define QPNP_BTM_HC_STATUS_HIGH 0x0b
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800186
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -0700187#define QPNP_BTM_HC_ADC_DIG_PARAM 0x42
188#define QPNP_BTM_HC_FAST_AVG_CTL 0x43
189#define QPNP_BTM_EN_CTL1 0x46
190#define QPNP_BTM_CONV_REQ 0x47
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800191
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -0700192#define QPNP_BTM_MEAS_INTERVAL_CTL 0x50
193#define QPNP_BTM_MEAS_INTERVAL_CTL2 0x51
Jishnu Prakashd09bc692018-05-02 10:54:28 +0530194#define QPNP_BTM_MEAS_INTERVAL_CTL_PM5 0x44
195#define QPNP_BTM_MEAS_INTERVAL_CTL2_PM5 0x45
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -0700196#define QPNP_ADC_TM_MEAS_INTERVAL_TIME_SHIFT 0x3
197#define QPNP_ADC_TM_MEAS_INTERVAL_CTL2_SHIFT 0x4
198#define QPNP_ADC_TM_MEAS_INTERVAL_CTL2_MASK 0xf0
199#define QPNP_ADC_TM_MEAS_INTERVAL_CTL3_MASK 0xf
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800200
201#define QPNP_BTM_Mn_ADC_CH_SEL_CTL(n) ((n * 8) + 0x60)
202#define QPNP_BTM_Mn_LOW_THR0(n) ((n * 8) + 0x61)
203#define QPNP_BTM_Mn_LOW_THR1(n) ((n * 8) + 0x62)
204#define QPNP_BTM_Mn_HIGH_THR0(n) ((n * 8) + 0x63)
205#define QPNP_BTM_Mn_HIGH_THR1(n) ((n * 8) + 0x64)
206#define QPNP_BTM_Mn_MEAS_INTERVAL_CTL(n) ((n * 8) + 0x65)
207#define QPNP_BTM_Mn_CTL(n) ((n * 8) + 0x66)
208#define QPNP_BTM_CTL_HW_SETTLE_DELAY_MASK 0xf
209#define QPNP_BTM_CTL_CAL_SEL 0x30
210#define QPNP_BTM_CTL_CAL_SEL_MASK_SHIFT 4
211#define QPNP_BTM_CTL_CAL_VAL 0x40
212
213#define QPNP_BTM_Mn_EN(n) ((n * 8) + 0x67)
214#define QPNP_BTM_Mn_MEAS_EN BIT(7)
215#define QPNP_BTM_Mn_HIGH_THR_INT_EN BIT(1)
216#define QPNP_BTM_Mn_LOW_THR_INT_EN BIT(0)
217
218#define QPNP_BTM_Mn_DATA0(n) ((n * 2) + 0xa0)
219#define QPNP_BTM_Mn_DATA1(n) ((n * 2) + 0xa1)
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -0700220#define QPNP_BTM_CHANNELS 8
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800221
Jishnu Prakash092c7ce2018-09-18 15:43:01 +0530222#define QPNP_ADC_WAKEUP_SRC_TIMEOUT_MS 2000
223
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800224/* QPNP ADC TM HC end */
225
226struct qpnp_adc_thr_info {
227 u8 status_low;
228 u8 status_high;
229 u8 qpnp_adc_tm_meas_en;
230 u8 adc_tm_low_enable;
231 u8 adc_tm_high_enable;
232 u8 adc_tm_low_thr_set;
233 u8 adc_tm_high_thr_set;
Prasad Malisetty358dda32018-02-20 06:14:26 +0530234 spinlock_t adc_tm_low_lock;
235 spinlock_t adc_tm_high_lock;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800236};
237
238struct qpnp_adc_thr_client_info {
239 struct list_head list;
240 struct qpnp_adc_tm_btm_param *btm_param;
241 int32_t low_thr_requested;
242 int32_t high_thr_requested;
243 enum qpnp_state_request state_requested;
244 enum qpnp_state_request state_req_copy;
245 bool low_thr_set;
246 bool high_thr_set;
247 bool notify_low_thr;
248 bool notify_high_thr;
249};
250
251struct qpnp_adc_tm_sensor {
252 struct thermal_zone_device *tz_dev;
253 struct qpnp_adc_tm_chip *chip;
254 enum thermal_device_mode mode;
255 uint32_t sensor_num;
256 enum qpnp_adc_meas_timer_select timer_select;
257 uint32_t meas_interval;
258 uint32_t low_thr;
259 uint32_t high_thr;
260 uint32_t btm_channel_num;
261 uint32_t vadc_channel_num;
262 struct workqueue_struct *req_wq;
263 struct work_struct work;
264 bool thermal_node;
265 uint32_t scale_type;
266 struct list_head thr_list;
267 bool high_thr_triggered;
268 bool low_thr_triggered;
269};
270
271struct qpnp_adc_tm_chip {
272 struct device *dev;
273 struct qpnp_adc_drv *adc;
274 struct list_head list;
275 bool adc_tm_initialized;
276 bool adc_tm_recalib_check;
277 int max_channels_available;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800278 struct qpnp_vadc_chip *vadc_dev;
279 struct workqueue_struct *high_thr_wq;
280 struct workqueue_struct *low_thr_wq;
281 struct workqueue_struct *thr_wq;
282 struct work_struct trigger_high_thr_work;
283 struct work_struct trigger_low_thr_work;
284 struct work_struct trigger_thr_work;
285 bool adc_vote_enable;
286 struct qpnp_adc_thr_info th_info;
287 bool adc_tm_hc;
288 struct qpnp_adc_tm_sensor sensor[0];
289};
290
291LIST_HEAD(qpnp_adc_tm_device_list);
292
Prasad Malisetty358dda32018-02-20 06:14:26 +0530293struct qpnp_adc_tm_trip_reg_type {
294 enum qpnp_adc_tm_channel_select btm_amux_chan;
295 uint16_t low_thr_lsb_addr;
296 uint16_t low_thr_msb_addr;
297 uint16_t high_thr_lsb_addr;
298 uint16_t high_thr_msb_addr;
299 u8 multi_meas_en;
300 u8 low_thr_int_chan_en;
301 u8 high_thr_int_chan_en;
302 u8 meas_interval_ctl;
303};
304
305static struct qpnp_adc_tm_trip_reg_type adc_tm_data[] = {
306 [QPNP_ADC_TM_CHAN0] = {QPNP_ADC_TM_M0_ADC_CH_SEL_CTL,
307 QPNP_M0_LOW_THR_LSB,
308 QPNP_M0_LOW_THR_MSB, QPNP_M0_HIGH_THR_LSB,
309 QPNP_M0_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M0,
310 QPNP_ADC_TM_LOW_THR_INT_EN_M0, QPNP_ADC_TM_HIGH_THR_INT_EN_M0,
311 QPNP_ADC_TM_M0_MEAS_INTERVAL_CTL},
312 [QPNP_ADC_TM_CHAN1] = {QPNP_ADC_TM_M1_ADC_CH_SEL_CTL,
313 QPNP_M1_LOW_THR_LSB,
314 QPNP_M1_LOW_THR_MSB, QPNP_M1_HIGH_THR_LSB,
315 QPNP_M1_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M1,
316 QPNP_ADC_TM_LOW_THR_INT_EN_M1, QPNP_ADC_TM_HIGH_THR_INT_EN_M1,
317 QPNP_ADC_TM_M1_MEAS_INTERVAL_CTL},
318 [QPNP_ADC_TM_CHAN2] = {QPNP_ADC_TM_M2_ADC_CH_SEL_CTL,
319 QPNP_M2_LOW_THR_LSB,
320 QPNP_M2_LOW_THR_MSB, QPNP_M2_HIGH_THR_LSB,
321 QPNP_M2_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M2,
322 QPNP_ADC_TM_LOW_THR_INT_EN_M2, QPNP_ADC_TM_HIGH_THR_INT_EN_M2,
323 QPNP_ADC_TM_M2_MEAS_INTERVAL_CTL},
324 [QPNP_ADC_TM_CHAN3] = {QPNP_ADC_TM_M3_ADC_CH_SEL_CTL,
325 QPNP_M3_LOW_THR_LSB,
326 QPNP_M3_LOW_THR_MSB, QPNP_M3_HIGH_THR_LSB,
327 QPNP_M3_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M3,
328 QPNP_ADC_TM_LOW_THR_INT_EN_M3, QPNP_ADC_TM_HIGH_THR_INT_EN_M3,
329 QPNP_ADC_TM_M3_MEAS_INTERVAL_CTL},
330 [QPNP_ADC_TM_CHAN4] = {QPNP_ADC_TM_M4_ADC_CH_SEL_CTL,
331 QPNP_M4_LOW_THR_LSB,
332 QPNP_M4_LOW_THR_MSB, QPNP_M4_HIGH_THR_LSB,
333 QPNP_M4_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M4,
334 QPNP_ADC_TM_LOW_THR_INT_EN_M4, QPNP_ADC_TM_HIGH_THR_INT_EN_M4,
335 QPNP_ADC_TM_M4_MEAS_INTERVAL_CTL},
336 [QPNP_ADC_TM_CHAN5] = {QPNP_ADC_TM_M5_ADC_CH_SEL_CTL,
337 QPNP_M5_LOW_THR_LSB,
338 QPNP_M5_LOW_THR_MSB, QPNP_M5_HIGH_THR_LSB,
339 QPNP_M5_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M5,
340 QPNP_ADC_TM_LOW_THR_INT_EN_M5, QPNP_ADC_TM_HIGH_THR_INT_EN_M5,
341 QPNP_ADC_TM_M5_MEAS_INTERVAL_CTL},
342 [QPNP_ADC_TM_CHAN6] = {QPNP_ADC_TM_M6_ADC_CH_SEL_CTL,
343 QPNP_M6_LOW_THR_LSB,
344 QPNP_M6_LOW_THR_MSB, QPNP_M6_HIGH_THR_LSB,
345 QPNP_M6_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M6,
346 QPNP_ADC_TM_LOW_THR_INT_EN_M6, QPNP_ADC_TM_HIGH_THR_INT_EN_M6,
347 QPNP_ADC_TM_M6_MEAS_INTERVAL_CTL},
348 [QPNP_ADC_TM_CHAN7] = {QPNP_ADC_TM_M7_ADC_CH_SEL_CTL,
349 QPNP_M7_LOW_THR_LSB,
350 QPNP_M7_LOW_THR_MSB, QPNP_M7_HIGH_THR_LSB,
351 QPNP_M7_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M7,
352 QPNP_ADC_TM_LOW_THR_INT_EN_M7, QPNP_ADC_TM_HIGH_THR_INT_EN_M7,
353 QPNP_ADC_TM_M7_MEAS_INTERVAL_CTL},
354};
355
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800356static struct qpnp_adc_tm_reverse_scale_fn adc_tm_rscale_fn[] = {
357 [SCALE_R_VBATT] = {qpnp_adc_vbatt_rscaler},
358 [SCALE_RBATT_THERM] = {qpnp_adc_btm_scaler},
359 [SCALE_R_USB_ID] = {qpnp_adc_usb_scaler},
360 [SCALE_RPMIC_THERM] = {qpnp_adc_scale_millidegc_pmic_voltage_thr},
361 [SCALE_R_SMB_BATT_THERM] = {qpnp_adc_smb_btm_rscaler},
362 [SCALE_R_ABSOLUTE] = {qpnp_adc_absolute_rthr},
363 [SCALE_QRD_SKUH_RBATT_THERM] = {qpnp_adc_qrd_skuh_btm_scaler},
364 [SCALE_QRD_SKUT1_RBATT_THERM] = {qpnp_adc_qrd_skut1_btm_scaler},
Jishnu Prakash142a3ff2018-10-08 15:28:08 +0530365 [SCALE_QRD_215_RBATT_THERM] = {qpnp_adc_qrd_215_btm_scaler},
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800366};
367
368static int32_t qpnp_adc_tm_read_reg(struct qpnp_adc_tm_chip *chip,
369 int16_t reg, u8 *data, int len)
370{
371 int rc = 0;
372
373 rc = regmap_bulk_read(chip->adc->regmap, (chip->adc->offset + reg),
374 data, len);
375 if (rc < 0)
376 pr_err("adc-tm read reg %d failed with %d\n", reg, rc);
377
378 return rc;
379}
380
381static int32_t qpnp_adc_tm_write_reg(struct qpnp_adc_tm_chip *chip,
382 int16_t reg, u8 data, int len)
383{
384 int rc = 0;
385 u8 *buf;
386
387 buf = &data;
388
389 rc = regmap_bulk_write(chip->adc->regmap, (chip->adc->offset + reg),
390 buf, len);
391 if (rc < 0)
392 pr_err("adc-tm write reg %d failed with %d\n", reg, rc);
393
394 return rc;
395}
396
Prasad Malisetty358dda32018-02-20 06:14:26 +0530397static int32_t qpnp_adc_tm_fast_avg_en(struct qpnp_adc_tm_chip *chip,
398 uint32_t *fast_avg_sample)
399{
400 int rc = 0, version = 0;
401 u8 fast_avg_en = 0;
402
403 version = qpnp_adc_get_revid_version(chip->dev);
404 if (!((version == QPNP_REV_ID_8916_1_0) ||
405 (version == QPNP_REV_ID_8916_1_1) ||
406 (version == QPNP_REV_ID_8916_2_0))) {
407 pr_debug("fast-avg-en not required for this version\n");
408 return rc;
409 }
410
411 fast_avg_en = QPNP_FAST_AVG_ENABLED;
412 rc = qpnp_adc_tm_write_reg(chip, QPNP_FAST_AVG_EN, fast_avg_en, 1);
413 if (rc < 0) {
414 pr_err("adc-tm fast-avg enable err\n");
415 return rc;
416 }
417
418 if (*fast_avg_sample >= 3)
419 *fast_avg_sample = 2;
420
421 return rc;
422}
423
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800424static int qpnp_adc_tm_check_vreg_vote(struct qpnp_adc_tm_chip *chip)
425{
426 int rc = 0;
427
428 if (!chip->adc_vote_enable) {
429 if (chip->adc->hkadc_ldo && chip->adc->hkadc_ldo_ok) {
430 rc = qpnp_adc_enable_voltage(chip->adc);
431 if (rc) {
432 pr_err("failed enabling VADC LDO\n");
433 return rc;
434 }
435 chip->adc_vote_enable = true;
436 }
437 }
438
439 return rc;
440}
441
442static int32_t qpnp_adc_tm_enable(struct qpnp_adc_tm_chip *chip)
443{
444 int rc = 0;
445 u8 data = 0;
446
447 rc = qpnp_adc_tm_check_vreg_vote(chip);
448 if (rc) {
449 pr_err("ADC TM VREG enable failed:%d\n", rc);
450 return rc;
451 }
452
453 data = QPNP_ADC_TM_EN;
454 rc = qpnp_adc_tm_write_reg(chip, QPNP_EN_CTL1, data, 1);
455 if (rc < 0) {
456 pr_err("adc-tm enable failed\n");
457 return rc;
458 }
459
Prasad Malisetty358dda32018-02-20 06:14:26 +0530460 if (chip->adc_tm_hc) {
461 data = QPNP_ADC_CONV_REQ_EN;
462 rc = qpnp_adc_tm_write_reg(chip, QPNP_BTM_CONV_REQ, data, 1);
463 if (rc < 0) {
464 pr_err("adc-tm enable failed\n");
465 return rc;
466 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800467 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800468 return rc;
469}
470
471static int32_t qpnp_adc_tm_disable(struct qpnp_adc_tm_chip *chip)
472{
Prasad Malisetty358dda32018-02-20 06:14:26 +0530473 u8 data = 0;
474 int rc = 0;
475
Rama Krishna Phani A66e48b42018-03-13 18:29:08 +0530476 if (!chip->adc_tm_hc) {
477 rc = qpnp_adc_tm_write_reg(chip, QPNP_EN_CTL1, data, 1);
Prasad Malisetty358dda32018-02-20 06:14:26 +0530478 if (rc < 0) {
Rama Krishna Phani A66e48b42018-03-13 18:29:08 +0530479 pr_err("adc-tm disable failed\n");
Prasad Malisetty358dda32018-02-20 06:14:26 +0530480 return rc;
481 }
482 }
483
Prasad Malisetty358dda32018-02-20 06:14:26 +0530484 return rc;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800485}
486
487static int qpnp_adc_tm_is_valid(struct qpnp_adc_tm_chip *chip)
488{
489 struct qpnp_adc_tm_chip *adc_tm_chip = NULL;
490
491 list_for_each_entry(adc_tm_chip, &qpnp_adc_tm_device_list, list)
492 if (chip == adc_tm_chip)
493 return 0;
494
495 return -EINVAL;
496}
497
498static int32_t qpnp_adc_tm_rc_check_channel_en(struct qpnp_adc_tm_chip *chip)
499{
500 u8 adc_tm_ctl = 0, status_low = 0, status_high = 0;
501 int rc = 0, i = 0;
502 bool ldo_en = false;
503
504 for (i = 0; i < chip->max_channels_available; i++) {
505 rc = qpnp_adc_tm_read_reg(chip, QPNP_BTM_Mn_CTL(i),
506 &adc_tm_ctl, 1);
507 if (rc) {
508 pr_err("adc-tm-tm read ctl failed with %d\n", rc);
509 return rc;
510 }
511
512 adc_tm_ctl &= QPNP_BTM_Mn_MEAS_EN;
513 status_low = adc_tm_ctl & QPNP_BTM_Mn_LOW_THR_INT_EN;
514 status_high = adc_tm_ctl & QPNP_BTM_Mn_HIGH_THR_INT_EN;
515
516 /* Enable only if there are pending measurement requests */
517 if ((adc_tm_ctl && status_high) ||
518 (adc_tm_ctl && status_low)) {
519 qpnp_adc_tm_enable(chip);
520 ldo_en = true;
521
522 /* Request conversion */
523 rc = qpnp_adc_tm_write_reg(chip, QPNP_CONV_REQ,
524 QPNP_CONV_REQ_SET, 1);
525 if (rc < 0) {
526 pr_err("adc-tm request conversion failed\n");
527 return rc;
528 }
529 }
530 break;
531 }
532
533 if (!ldo_en) {
534 /* disable the vote if applicable */
535 if (chip->adc_vote_enable && chip->adc->hkadc_ldo &&
536 chip->adc->hkadc_ldo_ok) {
537 qpnp_adc_disable_voltage(chip->adc);
538 chip->adc_vote_enable = false;
539 }
540 }
541
542 return rc;
543}
544
545static int32_t qpnp_adc_tm_enable_if_channel_meas(
546 struct qpnp_adc_tm_chip *chip)
547{
Prasad Malisetty358dda32018-02-20 06:14:26 +0530548 u8 adc_tm_meas_en = 0, status_low = 0, status_high = 0;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800549 int rc = 0;
550
Prasad Malisetty358dda32018-02-20 06:14:26 +0530551 if (chip->adc_tm_hc) {
552 rc = qpnp_adc_tm_rc_check_channel_en(chip);
553 if (rc) {
554 pr_err("adc_tm channel check failed\n");
555 return rc;
556 }
557 } else {
558 /* Check if a measurement request is still required */
559 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_MULTI_MEAS_EN,
560 &adc_tm_meas_en, 1);
561 if (rc) {
562 pr_err("read status high failed with %d\n", rc);
563 return rc;
564 }
565 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_LOW_THR_INT_EN,
566 &status_low, 1);
567 if (rc) {
568 pr_err("read status low failed with %d\n", rc);
569 return rc;
570 }
571
572 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_HIGH_THR_INT_EN,
573 &status_high, 1);
574 if (rc) {
575 pr_err("read status high failed with %d\n", rc);
576 return rc;
577 }
578
579 /* Enable only if there are pending measurement requests */
580 if ((adc_tm_meas_en && status_high) ||
581 (adc_tm_meas_en && status_low)) {
582 qpnp_adc_tm_enable(chip);
583 /* Request conversion */
584 rc = qpnp_adc_tm_write_reg(chip, QPNP_CONV_REQ,
585 QPNP_CONV_REQ_SET, 1);
586 if (rc < 0) {
587 pr_err("adc-tm request conversion failed\n");
588 return rc;
589 }
590 } else {
591 /* disable the vote if applicable */
592 if (chip->adc_vote_enable && chip->adc->hkadc_ldo &&
593 chip->adc->hkadc_ldo_ok) {
594 qpnp_adc_disable_voltage(chip->adc);
595 chip->adc_vote_enable = false;
596 }
597 }
598 }
599 return rc;
600}
601
602static int32_t qpnp_adc_tm_mode_select(struct qpnp_adc_tm_chip *chip,
603 u8 mode_ctl)
604{
605 int rc;
606
607 mode_ctl |= (QPNP_ADC_TRIM_EN | QPNP_AMUX_TRIM_EN);
608
609 /* VADC_BTM current sets mode to recurring measurements */
610 rc = qpnp_adc_tm_write_reg(chip, QPNP_MODE_CTL, mode_ctl, 1);
611 if (rc < 0)
612 pr_err("adc-tm write mode selection err\n");
613
614 return rc;
615}
616
617static int32_t qpnp_adc_tm_req_sts_check(struct qpnp_adc_tm_chip *chip)
618{
619 u8 status1 = 0, mode_ctl = 0;
620 int rc, count = 0;
621
622 /* Re-enable the peripheral */
623 rc = qpnp_adc_tm_enable(chip);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800624 if (rc) {
Prasad Malisetty358dda32018-02-20 06:14:26 +0530625 pr_err("adc-tm re-enable peripheral failed\n");
626 return rc;
627 }
628
629 /* The VADC_TM bank needs to be disabled for new conversion request */
630 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_STATUS1, &status1, 1);
631 if (rc) {
632 pr_err("adc-tm read status1 failed\n");
633 return rc;
634 }
635
636 /* Disable the bank if a conversion is occurring */
637 while (status1 & QPNP_STATUS1_REQ_STS) {
638 if (count > QPNP_RETRY) {
639 pr_err("retry error=%d with 0x%x\n", count, status1);
640 break;
641 }
642 /*
643 * Wait time is based on the optimum sampling rate
644 * and adding enough time buffer to account for ADC conversions
645 * occurring on different peripheral banks
646 */
647 usleep_range(QPNP_MIN_TIME, QPNP_MAX_TIME);
648 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_STATUS1,
649 &status1, 1);
650 if (rc < 0) {
651 pr_err("adc-tm disable failed\n");
652 return rc;
653 }
654 count++;
655 }
656
657 if (!chip->adc_tm_hc) {
658 /* Change the mode back to recurring measurement mode */
659 mode_ctl = ADC_OP_MEASUREMENT_INTERVAL << QPNP_OP_MODE_SHIFT;
660 rc = qpnp_adc_tm_mode_select(chip, mode_ctl);
661 if (rc < 0) {
662 pr_err("adc-tm mode change to recurring failed\n");
663 return rc;
664 }
665 }
666
667 /* Disable the peripheral */
668 rc = qpnp_adc_tm_disable(chip);
669 if (rc < 0) {
670 pr_err("adc-tm peripheral disable failed\n");
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800671 return rc;
672 }
673
674 return rc;
675}
676
677static int32_t qpnp_adc_tm_get_btm_idx(struct qpnp_adc_tm_chip *chip,
678 uint32_t btm_chan, uint32_t *btm_chan_idx)
679{
680 int rc = 0, i;
681 bool chan_found = false;
682
Prasad Malisetty358dda32018-02-20 06:14:26 +0530683 if (!chip->adc_tm_hc) {
684 for (i = 0; i < QPNP_ADC_TM_CHAN_NONE; i++) {
685 if (adc_tm_data[i].btm_amux_chan == btm_chan) {
686 *btm_chan_idx = i;
687 chan_found = true;
688 }
689 }
690 } else {
691 for (i = 0; i < chip->max_channels_available; i++) {
692 if (chip->sensor[i].btm_channel_num == btm_chan) {
693 *btm_chan_idx = i;
694 chan_found = true;
695 break;
696 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800697 }
698 }
699
700 if (!chan_found)
701 return -EINVAL;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800702 return rc;
703}
704
705static int32_t qpnp_adc_tm_check_revision(struct qpnp_adc_tm_chip *chip,
706 uint32_t btm_chan_num)
707{
708 u8 rev, perph_subtype;
709 int rc = 0;
710
711 rc = qpnp_adc_tm_read_reg(chip, QPNP_REVISION3, &rev, 1);
712 if (rc) {
713 pr_err("adc-tm revision read failed\n");
714 return rc;
715 }
716
717 rc = qpnp_adc_tm_read_reg(chip, QPNP_PERPH_SUBTYPE, &perph_subtype, 1);
718 if (rc) {
719 pr_err("adc-tm perph_subtype read failed\n");
720 return rc;
721 }
722
723 if (perph_subtype == QPNP_PERPH_TYPE2) {
724 if ((rev < QPNP_REVISION_EIGHT_CHANNEL_SUPPORT) &&
725 (btm_chan_num > QPNP_ADC_TM_M4_ADC_CH_SEL_CTL)) {
726 pr_debug("Version does not support more than 5 channels\n");
727 return -EINVAL;
728 }
729 }
730
731 if (perph_subtype == QPNP_PERPH_SUBTYPE_TWO_CHANNEL_SUPPORT) {
732 if (btm_chan_num > QPNP_ADC_TM_M1_ADC_CH_SEL_CTL) {
733 pr_debug("Version does not support more than 2 channels\n");
734 return -EINVAL;
735 }
736 }
737
738 return rc;
739}
740
741static int32_t qpnp_adc_tm_timer_interval_select(
742 struct qpnp_adc_tm_chip *chip, uint32_t btm_chan,
743 struct qpnp_vadc_chan_properties *chan_prop)
744{
745 int rc, chan_idx = 0, i = 0;
746 bool chan_found = false;
747 u8 meas_interval_timer2 = 0, timer_interval_store = 0;
748 uint32_t btm_chan_idx = 0;
Jishnu Prakashd09bc692018-05-02 10:54:28 +0530749 bool is_pmic_5 = chip->adc->adc_prop->is_pmic_5;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800750
751 while (i < chip->max_channels_available) {
752 if (chip->sensor[i].btm_channel_num == btm_chan) {
753 chan_idx = i;
754 chan_found = true;
755 i++;
756 } else
757 i++;
758 }
759
760 if (!chan_found) {
761 pr_err("Channel not found\n");
762 return -EINVAL;
763 }
764
765 switch (chip->sensor[chan_idx].timer_select) {
766 case ADC_MEAS_TIMER_SELECT1:
Prasad Malisetty358dda32018-02-20 06:14:26 +0530767 if (!chip->adc_tm_hc)
768 rc = qpnp_adc_tm_write_reg(chip,
769 QPNP_ADC_TM_MEAS_INTERVAL_CTL,
770 chip->sensor[chan_idx].meas_interval, 1);
Jishnu Prakashd09bc692018-05-02 10:54:28 +0530771 else {
772 if (!is_pmic_5)
773 rc = qpnp_adc_tm_write_reg(chip,
774 QPNP_BTM_MEAS_INTERVAL_CTL,
775 chip->sensor[chan_idx].meas_interval,
776 1);
777 else
778 rc = qpnp_adc_tm_write_reg(chip,
779 QPNP_BTM_MEAS_INTERVAL_CTL_PM5,
780 chip->sensor[chan_idx].meas_interval,
781 1);
782 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800783 if (rc < 0) {
784 pr_err("timer1 configure failed\n");
785 return rc;
786 }
Prasad Malisetty358dda32018-02-20 06:14:26 +0530787 break;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800788 case ADC_MEAS_TIMER_SELECT2:
789 /* Thermal channels uses timer2, default to 1 second */
Prasad Malisetty358dda32018-02-20 06:14:26 +0530790 if (!chip->adc_tm_hc)
791 rc = qpnp_adc_tm_read_reg(chip,
792 QPNP_ADC_TM_MEAS_INTERVAL_CTL2,
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800793 &meas_interval_timer2, 1);
Jishnu Prakashd09bc692018-05-02 10:54:28 +0530794 else {
795 if (!is_pmic_5)
796 rc = qpnp_adc_tm_read_reg(chip,
Prasad Malisetty358dda32018-02-20 06:14:26 +0530797 QPNP_BTM_MEAS_INTERVAL_CTL2,
798 &meas_interval_timer2, 1);
Jishnu Prakashd09bc692018-05-02 10:54:28 +0530799 else
800 rc = qpnp_adc_tm_read_reg(chip,
801 QPNP_BTM_MEAS_INTERVAL_CTL2_PM5,
802 &meas_interval_timer2, 1);
803 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800804 if (rc < 0) {
805 pr_err("timer2 configure read failed\n");
806 return rc;
807 }
808 timer_interval_store = chip->sensor[chan_idx].meas_interval;
809 timer_interval_store <<= QPNP_ADC_TM_MEAS_INTERVAL_CTL2_SHIFT;
810 timer_interval_store &= QPNP_ADC_TM_MEAS_INTERVAL_CTL2_MASK;
811 meas_interval_timer2 |= timer_interval_store;
Prasad Malisetty358dda32018-02-20 06:14:26 +0530812 if (!chip->adc_tm_hc)
813 rc = qpnp_adc_tm_write_reg(chip,
814 QPNP_ADC_TM_MEAS_INTERVAL_CTL2,
815 meas_interval_timer2, 1);
Jishnu Prakashd09bc692018-05-02 10:54:28 +0530816 else {
817 if (!is_pmic_5)
818 rc = qpnp_adc_tm_write_reg(chip,
819 QPNP_BTM_MEAS_INTERVAL_CTL2,
820 meas_interval_timer2, 1);
821 else
822 rc = qpnp_adc_tm_write_reg(chip,
823 QPNP_BTM_MEAS_INTERVAL_CTL2_PM5,
824 meas_interval_timer2, 1);
825 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800826 if (rc < 0) {
827 pr_err("timer2 configure failed\n");
828 return rc;
829 }
830 break;
831 case ADC_MEAS_TIMER_SELECT3:
Prasad Malisetty358dda32018-02-20 06:14:26 +0530832 if (!chip->adc_tm_hc)
833 rc = qpnp_adc_tm_read_reg(chip,
834 QPNP_ADC_TM_MEAS_INTERVAL_CTL2,
835 &meas_interval_timer2, 1);
Jishnu Prakashd09bc692018-05-02 10:54:28 +0530836 else {
837 if (!is_pmic_5)
838 rc = qpnp_adc_tm_read_reg(chip,
839 QPNP_BTM_MEAS_INTERVAL_CTL2,
840 &meas_interval_timer2, 1);
841 else
842 rc = qpnp_adc_tm_read_reg(chip,
843 QPNP_BTM_MEAS_INTERVAL_CTL2_PM5,
844 &meas_interval_timer2, 1);
845 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800846 if (rc < 0) {
847 pr_err("timer3 read failed\n");
848 return rc;
849 }
850 timer_interval_store = chip->sensor[chan_idx].meas_interval;
851 timer_interval_store &= QPNP_ADC_TM_MEAS_INTERVAL_CTL3_MASK;
852 meas_interval_timer2 |= timer_interval_store;
Prasad Malisetty358dda32018-02-20 06:14:26 +0530853 if (!chip->adc_tm_hc)
854 rc = qpnp_adc_tm_write_reg(chip,
855 QPNP_ADC_TM_MEAS_INTERVAL_CTL2,
856 meas_interval_timer2, 1);
Jishnu Prakashd09bc692018-05-02 10:54:28 +0530857 else {
858 if (!is_pmic_5)
859 rc = qpnp_adc_tm_write_reg(chip,
860 QPNP_BTM_MEAS_INTERVAL_CTL2,
861 meas_interval_timer2, 1);
862 else
863 rc = qpnp_adc_tm_write_reg(chip,
864 QPNP_BTM_MEAS_INTERVAL_CTL2_PM5,
865 meas_interval_timer2, 1);
866 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800867 if (rc < 0) {
868 pr_err("timer3 configure failed\n");
869 return rc;
870 }
871 break;
872 default:
873 pr_err("Invalid timer selection\n");
874 return -EINVAL;
875 }
876
877 /* Select the timer to use for the corresponding channel */
878 rc = qpnp_adc_tm_get_btm_idx(chip, btm_chan, &btm_chan_idx);
879 if (rc < 0) {
880 pr_err("Invalid btm channel idx\n");
881 return rc;
882 }
Prasad Malisetty358dda32018-02-20 06:14:26 +0530883 if (!chip->adc_tm_hc)
884 rc = qpnp_adc_tm_write_reg(chip,
885 adc_tm_data[btm_chan_idx].meas_interval_ctl,
886 chip->sensor[chan_idx].timer_select, 1);
887 else
888 rc = qpnp_adc_tm_write_reg(chip,
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -0700889 QPNP_BTM_Mn_MEAS_INTERVAL_CTL(btm_chan_idx),
890 chip->sensor[chan_idx].timer_select, 1);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800891 if (rc < 0) {
892 pr_err("TM channel timer configure failed\n");
893 return rc;
894 }
895
896 pr_debug("timer select:%d, timer_value_within_select:%d, channel:%x\n",
897 chip->sensor[chan_idx].timer_select,
898 chip->sensor[chan_idx].meas_interval,
899 btm_chan);
900
901 return rc;
902}
903
904static int32_t qpnp_adc_tm_add_to_list(struct qpnp_adc_tm_chip *chip,
905 uint32_t dt_index,
906 struct qpnp_adc_tm_btm_param *param,
907 struct qpnp_vadc_chan_properties *chan_prop)
908{
909 struct qpnp_adc_thr_client_info *client_info = NULL;
910 bool client_info_exists = false;
911
912 list_for_each_entry(client_info,
913 &chip->sensor[dt_index].thr_list, list) {
914 if (client_info->btm_param == param) {
915 client_info->low_thr_requested = chan_prop->low_thr;
916 client_info->high_thr_requested = chan_prop->high_thr;
917 client_info->state_requested = param->state_request;
918 client_info->state_req_copy = param->state_request;
919 client_info->notify_low_thr = false;
920 client_info->notify_high_thr = false;
921 client_info_exists = true;
922 pr_debug("client found\n");
923 }
924 }
925
926 if (!client_info_exists) {
927 client_info = devm_kzalloc(chip->dev,
928 sizeof(struct qpnp_adc_thr_client_info), GFP_KERNEL);
929 if (!client_info)
930 return -ENOMEM;
931
932 pr_debug("new client\n");
933 client_info->btm_param = param;
934 client_info->low_thr_requested = chan_prop->low_thr;
935 client_info->high_thr_requested = chan_prop->high_thr;
936 client_info->state_requested = param->state_request;
937 client_info->state_req_copy = param->state_request;
938
939 list_add_tail(&client_info->list,
940 &chip->sensor[dt_index].thr_list);
941 }
942
943 return 0;
944}
945
946static int32_t qpnp_adc_tm_reg_update(struct qpnp_adc_tm_chip *chip,
947 uint16_t addr, u8 mask, bool state)
948{
949 u8 reg_value = 0;
950 int rc = 0;
951
952 rc = qpnp_adc_tm_read_reg(chip, addr, &reg_value, 1);
953 if (rc < 0) {
954 pr_err("read failed for addr:0x%x\n", addr);
955 return rc;
956 }
957
958 reg_value = reg_value & ~mask;
959 if (state)
960 reg_value |= mask;
961
962 pr_debug("state:%d, reg:0x%x with bits:0x%x and mask:0x%x\n",
963 state, addr, reg_value, ~mask);
964 rc = qpnp_adc_tm_write_reg(chip, addr, reg_value, 1);
965 if (rc < 0) {
966 pr_err("write failed for addr:%x\n", addr);
967 return rc;
968 }
969
970 return rc;
971}
972
Prasad Malisetty358dda32018-02-20 06:14:26 +0530973static int32_t qpnp_adc_tm_read_thr_value(struct qpnp_adc_tm_chip *chip,
974 uint32_t btm_chan)
975{
976 int rc = 0;
977 u8 data_lsb = 0, data_msb = 0;
978 uint32_t btm_chan_idx = 0;
979 int32_t low_thr = 0, high_thr = 0;
980
981 if (!chip->adc_tm_hc) {
982 pr_err("Not applicable for VADC HC peripheral\n");
983 return -EINVAL;
984 }
985
986 rc = qpnp_adc_tm_get_btm_idx(chip, btm_chan, &btm_chan_idx);
987 if (rc < 0) {
988 pr_err("Invalid btm channel idx\n");
989 return rc;
990 }
991
992 rc = qpnp_adc_tm_read_reg(chip,
993 adc_tm_data[btm_chan_idx].low_thr_lsb_addr,
994 &data_lsb, 1);
995 if (rc < 0) {
996 pr_err("low threshold lsb setting failed\n");
997 return rc;
998 }
999
1000 rc = qpnp_adc_tm_read_reg(chip,
1001 adc_tm_data[btm_chan_idx].low_thr_msb_addr,
1002 &data_msb, 1);
1003 if (rc < 0) {
1004 pr_err("low threshold msb setting failed\n");
1005 return rc;
1006 }
1007
1008 low_thr = (data_msb << 8) | data_lsb;
1009
1010 rc = qpnp_adc_tm_read_reg(chip,
1011 adc_tm_data[btm_chan_idx].high_thr_lsb_addr,
1012 &data_lsb, 1);
1013 if (rc < 0) {
1014 pr_err("high threshold lsb setting failed\n");
1015 return rc;
1016 }
1017
1018 rc = qpnp_adc_tm_read_reg(chip,
1019 adc_tm_data[btm_chan_idx].high_thr_msb_addr,
1020 &data_msb, 1);
1021 if (rc < 0) {
1022 pr_err("high threshold msb setting failed\n");
1023 return rc;
1024 }
1025
1026 high_thr = (data_msb << 8) | data_lsb;
1027
1028 pr_debug("configured thresholds high:0x%x and low:0x%x\n",
1029 high_thr, low_thr);
1030
1031 return rc;
1032}
1033
1034
1035
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001036static int32_t qpnp_adc_tm_thr_update(struct qpnp_adc_tm_chip *chip,
1037 uint32_t btm_chan, int32_t high_thr, int32_t low_thr)
1038{
1039 int rc = 0;
1040 uint32_t btm_chan_idx = 0;
1041
1042 rc = qpnp_adc_tm_get_btm_idx(chip, btm_chan, &btm_chan_idx);
1043 if (rc < 0) {
1044 pr_err("Invalid btm channel idx\n");
1045 return rc;
1046 }
1047
Prasad Malisetty358dda32018-02-20 06:14:26 +05301048 if (!chip->adc_tm_hc) {
1049 rc = qpnp_adc_tm_write_reg(chip,
1050 adc_tm_data[btm_chan_idx].low_thr_lsb_addr,
1051 QPNP_ADC_TM_THR_LSB_MASK(low_thr), 1);
1052 if (rc < 0) {
1053 pr_err("low threshold lsb setting failed\n");
1054 return rc;
1055 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001056
Prasad Malisetty358dda32018-02-20 06:14:26 +05301057 rc = qpnp_adc_tm_write_reg(chip,
1058 adc_tm_data[btm_chan_idx].low_thr_msb_addr,
1059 QPNP_ADC_TM_THR_MSB_MASK(low_thr), 1);
1060 if (rc < 0) {
1061 pr_err("low threshold msb setting failed\n");
1062 return rc;
1063 }
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001064
Prasad Malisetty358dda32018-02-20 06:14:26 +05301065 rc = qpnp_adc_tm_write_reg(chip,
1066 adc_tm_data[btm_chan_idx].high_thr_lsb_addr,
1067 QPNP_ADC_TM_THR_LSB_MASK(high_thr), 1);
1068 if (rc < 0) {
1069 pr_err("high threshold lsb setting failed\n");
1070 return rc;
1071 }
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001072
Prasad Malisetty358dda32018-02-20 06:14:26 +05301073 rc = qpnp_adc_tm_write_reg(chip,
1074 adc_tm_data[btm_chan_idx].high_thr_msb_addr,
1075 QPNP_ADC_TM_THR_MSB_MASK(high_thr), 1);
1076 if (rc < 0)
1077 pr_err("high threshold msb setting failed\n");
1078 } else {
1079 rc = qpnp_adc_tm_write_reg(chip,
1080 QPNP_BTM_Mn_LOW_THR0(btm_chan_idx),
1081 QPNP_ADC_TM_THR_LSB_MASK(low_thr), 1);
1082 if (rc < 0) {
1083 pr_err("low threshold lsb setting failed\n");
1084 return rc;
1085 }
1086
1087 rc = qpnp_adc_tm_write_reg(chip,
1088 QPNP_BTM_Mn_LOW_THR1(btm_chan_idx),
1089 QPNP_ADC_TM_THR_MSB_MASK(low_thr), 1);
1090 if (rc < 0) {
1091 pr_err("low threshold msb setting failed\n");
1092 return rc;
1093 }
1094
1095 rc = qpnp_adc_tm_write_reg(chip,
1096 QPNP_BTM_Mn_HIGH_THR0(btm_chan_idx),
1097 QPNP_ADC_TM_THR_LSB_MASK(high_thr), 1);
1098 if (rc < 0) {
1099 pr_err("high threshold lsb setting failed\n");
1100 return rc;
1101 }
1102
1103 rc = qpnp_adc_tm_write_reg(chip,
1104 QPNP_BTM_Mn_HIGH_THR1(btm_chan_idx),
1105 QPNP_ADC_TM_THR_MSB_MASK(high_thr), 1);
1106 if (rc < 0)
1107 pr_err("high threshold msb setting failed\n");
1108
1109 }
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001110
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001111 pr_debug("client requested high:%d and low:%d\n",
Prasad Malisetty358dda32018-02-20 06:14:26 +05301112 high_thr, low_thr);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001113
1114 return rc;
1115}
1116
1117static int32_t qpnp_adc_tm_manage_thresholds(struct qpnp_adc_tm_chip *chip,
1118 uint32_t dt_index, uint32_t btm_chan)
1119{
1120 struct qpnp_adc_thr_client_info *client_info = NULL;
1121 struct list_head *thr_list;
1122 int high_thr = 0, low_thr = 0, rc = 0;
1123
1124
1125 /*
1126 * high_thr/low_thr starting point and reset the high_thr_set and
1127 * low_thr_set back to reset since the thresholds will be
1128 * recomputed.
1129 */
1130 list_for_each(thr_list,
1131 &chip->sensor[dt_index].thr_list) {
1132 client_info = list_entry(thr_list,
1133 struct qpnp_adc_thr_client_info, list);
1134 high_thr = client_info->high_thr_requested;
1135 low_thr = client_info->low_thr_requested;
1136 client_info->high_thr_set = false;
1137 client_info->low_thr_set = false;
1138 }
1139
1140 pr_debug("init threshold is high:%d and low:%d\n", high_thr, low_thr);
1141
1142 /* Find the min of high_thr and max of low_thr */
1143 list_for_each(thr_list,
1144 &chip->sensor[dt_index].thr_list) {
1145 client_info = list_entry(thr_list,
1146 struct qpnp_adc_thr_client_info, list);
1147 if ((client_info->state_req_copy == ADC_TM_HIGH_THR_ENABLE) ||
1148 (client_info->state_req_copy ==
1149 ADC_TM_HIGH_LOW_THR_ENABLE))
1150 if (client_info->high_thr_requested < high_thr)
1151 high_thr = client_info->high_thr_requested;
1152
1153 if ((client_info->state_req_copy == ADC_TM_LOW_THR_ENABLE) ||
1154 (client_info->state_req_copy ==
1155 ADC_TM_HIGH_LOW_THR_ENABLE))
1156 if (client_info->low_thr_requested > low_thr)
1157 low_thr = client_info->low_thr_requested;
1158
1159 pr_debug("threshold compared is high:%d and low:%d\n",
1160 client_info->high_thr_requested,
1161 client_info->low_thr_requested);
1162 pr_debug("current threshold is high:%d and low:%d\n",
1163 high_thr, low_thr);
1164 }
1165
1166 /* Check which of the high_thr and low_thr got set */
1167 list_for_each(thr_list,
1168 &chip->sensor[dt_index].thr_list) {
1169 client_info = list_entry(thr_list,
1170 struct qpnp_adc_thr_client_info, list);
1171 if ((client_info->state_req_copy == ADC_TM_HIGH_THR_ENABLE) ||
1172 (client_info->state_req_copy ==
1173 ADC_TM_HIGH_LOW_THR_ENABLE))
1174 if (high_thr == client_info->high_thr_requested)
1175 client_info->high_thr_set = true;
1176
1177 if ((client_info->state_req_copy == ADC_TM_LOW_THR_ENABLE) ||
1178 (client_info->state_req_copy ==
1179 ADC_TM_HIGH_LOW_THR_ENABLE))
1180 if (low_thr == client_info->low_thr_requested)
1181 client_info->low_thr_set = true;
1182 }
1183
1184 rc = qpnp_adc_tm_thr_update(chip, btm_chan, high_thr, low_thr);
1185 if (rc < 0)
1186 pr_err("setting chan:%d threshold failed\n", btm_chan);
1187
1188 pr_debug("threshold written is high:%d and low:%d\n",
1189 high_thr, low_thr);
1190
1191 return 0;
1192}
1193
1194static int32_t qpnp_adc_tm_channel_configure(struct qpnp_adc_tm_chip *chip,
1195 uint32_t btm_chan,
1196 struct qpnp_vadc_chan_properties *chan_prop,
1197 uint32_t amux_channel)
1198{
1199 int rc = 0, i = 0, chan_idx = 0;
1200 bool chan_found = false, high_thr_set = false, low_thr_set = false;
1201 u8 sensor_mask = 0;
1202 struct qpnp_adc_thr_client_info *client_info = NULL;
1203 uint32_t btm_chan_idx = 0;
1204
1205 while (i < chip->max_channels_available) {
1206 if (chip->sensor[i].btm_channel_num == btm_chan) {
1207 chan_idx = i;
1208 chan_found = true;
1209 i++;
1210 } else
1211 i++;
1212 }
1213
1214 if (!chan_found) {
1215 pr_err("Channel not found\n");
1216 return -EINVAL;
1217 }
1218
1219 rc = qpnp_adc_tm_get_btm_idx(chip, btm_chan, &btm_chan_idx);
1220 if (rc < 0) {
1221 pr_err("Invalid btm channel idx\n");
1222 return rc;
1223 }
1224
1225 sensor_mask = 1 << chan_idx;
1226 if (!chip->sensor[chan_idx].thermal_node) {
1227 /* Update low and high notification thresholds */
1228 rc = qpnp_adc_tm_manage_thresholds(chip, chan_idx,
1229 btm_chan);
1230 if (rc < 0) {
1231 pr_err("setting chan:%d threshold failed\n", btm_chan);
1232 return rc;
1233 }
1234
1235 list_for_each_entry(client_info,
1236 &chip->sensor[chan_idx].thr_list, list) {
1237 if (client_info->high_thr_set == true)
1238 high_thr_set = true;
1239 if (client_info->low_thr_set == true)
1240 low_thr_set = true;
1241 }
1242
1243 if (low_thr_set) {
1244 pr_debug("low sensor mask:%x with state:%d\n",
1245 sensor_mask, chan_prop->state_request);
1246 /* Enable low threshold's interrupt */
Prasad Malisetty358dda32018-02-20 06:14:26 +05301247 if (!chip->adc_tm_hc)
1248 rc = qpnp_adc_tm_reg_update(chip,
1249 QPNP_ADC_TM_LOW_THR_INT_EN,
1250 sensor_mask, true);
1251 else
1252 rc = qpnp_adc_tm_reg_update(chip,
1253 QPNP_BTM_Mn_EN(btm_chan_idx),
1254 QPNP_BTM_Mn_LOW_THR_INT_EN, true);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001255 if (rc < 0) {
1256 pr_err("low thr enable err:%d\n", btm_chan);
1257 return rc;
1258 }
1259 }
1260
1261 if (high_thr_set) {
1262 /* Enable high threshold's interrupt */
1263 pr_debug("high sensor mask:%x\n", sensor_mask);
Prasad Malisetty358dda32018-02-20 06:14:26 +05301264 if (!chip->adc_tm_hc)
1265 rc = qpnp_adc_tm_reg_update(chip,
1266 QPNP_ADC_TM_HIGH_THR_INT_EN,
1267 sensor_mask, true);
1268 else
1269 rc = qpnp_adc_tm_reg_update(chip,
1270 QPNP_BTM_Mn_EN(btm_chan_idx),
1271 QPNP_BTM_Mn_HIGH_THR_INT_EN, true);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001272 if (rc < 0) {
1273 pr_err("high thr enable err:%d\n", btm_chan);
1274 return rc;
1275 }
1276 }
1277 }
1278
1279 /* Enable corresponding BTM channel measurement */
Prasad Malisetty358dda32018-02-20 06:14:26 +05301280 if (!chip->adc_tm_hc)
1281 rc = qpnp_adc_tm_reg_update(chip,
1282 QPNP_ADC_TM_MULTI_MEAS_EN, sensor_mask, true);
1283 else
1284 rc = qpnp_adc_tm_reg_update(chip, QPNP_BTM_Mn_EN(btm_chan_idx),
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001285 QPNP_BTM_Mn_MEAS_EN, true);
1286 if (rc < 0) {
1287 pr_err("multi measurement en failed\n");
1288 return rc;
1289 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001290 return rc;
1291}
1292
1293static int32_t qpnp_adc_tm_hc_configure(struct qpnp_adc_tm_chip *chip,
1294 struct qpnp_adc_amux_properties *chan_prop)
1295{
1296 u8 decimation = 0, fast_avg_ctl = 0;
1297 u8 buf[8];
1298 int rc = 0;
1299 uint32_t btm_chan = 0, cal_type = 0, btm_chan_idx = 0;
1300
1301 /* Disable bank */
1302 rc = qpnp_adc_tm_disable(chip);
1303 if (rc)
1304 return rc;
1305
1306 /* Decimation setup */
1307 decimation = chan_prop->decimation;
1308 rc = qpnp_adc_tm_write_reg(chip, QPNP_BTM_HC_ADC_DIG_PARAM,
1309 decimation, 1);
1310 if (rc < 0) {
1311 pr_err("adc-tm digital parameter setup err\n");
1312 return rc;
1313 }
1314
1315 /* Fast averaging setup/enable */
1316 rc = qpnp_adc_tm_read_reg(chip, QPNP_BTM_HC_FAST_AVG_CTL,
1317 &fast_avg_ctl, 1);
1318 if (rc < 0) {
1319 pr_err("adc-tm fast-avg enable read err\n");
1320 return rc;
1321 }
1322 fast_avg_ctl |= chan_prop->fast_avg_setup;
1323 rc = qpnp_adc_tm_write_reg(chip, QPNP_BTM_HC_FAST_AVG_CTL,
1324 fast_avg_ctl, 1);
1325 if (rc < 0) {
1326 pr_err("adc-tm fast-avg enable write err\n");
1327 return rc;
1328 }
1329
1330 /* Read block registers for respective BTM channel */
1331 btm_chan = chan_prop->chan_prop->tm_channel_select;
1332 rc = qpnp_adc_tm_get_btm_idx(chip, btm_chan, &btm_chan_idx);
1333 if (rc < 0) {
1334 pr_err("Invalid btm channel idx\n");
1335 return rc;
1336 }
1337
1338 rc = qpnp_adc_tm_read_reg(chip,
1339 QPNP_BTM_Mn_ADC_CH_SEL_CTL(btm_chan_idx), buf, 8);
1340 if (rc < 0) {
1341 pr_err("qpnp adc configure block read failed\n");
1342 return rc;
1343 }
1344
1345 /* Update ADC channel sel */
1346 rc = qpnp_adc_tm_write_reg(chip,
1347 QPNP_BTM_Mn_ADC_CH_SEL_CTL(btm_chan_idx),
1348 chan_prop->amux_channel, 1);
1349 if (rc < 0) {
1350 pr_err("adc-tm channel amux select failed\n");
1351 return rc;
1352 }
1353
1354 /* Manage thresholds */
1355 rc = qpnp_adc_tm_channel_configure(chip, btm_chan,
1356 chan_prop->chan_prop, chan_prop->amux_channel);
1357 if (rc < 0) {
1358 pr_err("adc-tm channel threshold configure failed\n");
1359 return rc;
1360 }
1361
1362 /* Measurement interval setup */
1363 rc = qpnp_adc_tm_timer_interval_select(chip, btm_chan,
1364 chan_prop->chan_prop);
1365 if (rc < 0) {
1366 pr_err("adc-tm timer select failed\n");
1367 return rc;
1368 }
1369
1370 /* Set calibration select, hw_settle delay */
1371 cal_type |= (chan_prop->calib_type << QPNP_BTM_CTL_CAL_SEL_MASK_SHIFT);
1372 buf[6] &= ~QPNP_BTM_CTL_HW_SETTLE_DELAY_MASK;
1373 buf[6] |= chan_prop->hw_settle_time;
1374 buf[6] &= ~QPNP_BTM_CTL_CAL_SEL;
1375 buf[6] |= cal_type;
1376 rc = qpnp_adc_tm_write_reg(chip, QPNP_BTM_Mn_CTL(btm_chan_idx),
1377 buf[6], 1);
1378 if (rc < 0) {
1379 pr_err("adc-tm hw-settle, calib sel failed\n");
1380 return rc;
1381 }
1382
1383 /* Enable bank */
1384 rc = qpnp_adc_tm_enable(chip);
1385 if (rc)
1386 return rc;
1387
1388 /* Request conversion */
1389 rc = qpnp_adc_tm_write_reg(chip, QPNP_CONV_REQ, QPNP_CONV_REQ_SET, 1);
1390 if (rc < 0) {
1391 pr_err("adc-tm request conversion failed\n");
1392 return rc;
1393 }
1394
1395 return 0;
1396}
1397
Prasad Malisetty358dda32018-02-20 06:14:26 +05301398static int32_t qpnp_adc_tm_configure(struct qpnp_adc_tm_chip *chip,
1399 struct qpnp_adc_amux_properties *chan_prop)
1400{
1401 u8 decimation = 0, op_cntrl = 0, mode_ctl = 0;
1402 int rc = 0;
1403 uint32_t btm_chan = 0;
1404
1405 /* Set measurement in single measurement mode */
1406 mode_ctl = ADC_OP_NORMAL_MODE << QPNP_OP_MODE_SHIFT;
1407 rc = qpnp_adc_tm_mode_select(chip, mode_ctl);
1408 if (rc < 0) {
1409 pr_err("adc-tm single mode select failed\n");
1410 return rc;
1411 }
1412
1413 /* Disable bank */
1414 rc = qpnp_adc_tm_disable(chip);
1415 if (rc)
1416 return rc;
1417
1418 /* Check if a conversion is in progress */
1419 rc = qpnp_adc_tm_req_sts_check(chip);
1420 if (rc < 0) {
1421 pr_err("adc-tm req_sts check failed\n");
1422 return rc;
1423 }
1424
1425 /* Configure AMUX channel select for the corresponding BTM channel*/
1426 btm_chan = chan_prop->chan_prop->tm_channel_select;
1427 rc = qpnp_adc_tm_write_reg(chip, btm_chan, chan_prop->amux_channel, 1);
1428 if (rc < 0) {
1429 pr_err("adc-tm channel selection err\n");
1430 return rc;
1431 }
1432
1433 /* Digital parameter setup */
1434 decimation |= chan_prop->decimation <<
1435 QPNP_ADC_DIG_DEC_RATIO_SEL_SHIFT;
1436 rc = qpnp_adc_tm_write_reg(chip, QPNP_ADC_DIG_PARAM, decimation, 1);
1437 if (rc < 0) {
1438 pr_err("adc-tm digital parameter setup err\n");
1439 return rc;
1440 }
1441
1442 /* Hardware setting time */
1443 rc = qpnp_adc_tm_write_reg(chip, QPNP_HW_SETTLE_DELAY,
1444 chan_prop->hw_settle_time, 1);
1445 if (rc < 0) {
1446 pr_err("adc-tm hw settling time setup err\n");
1447 return rc;
1448 }
1449
1450 /* Fast averaging setup/enable */
1451 rc = qpnp_adc_tm_fast_avg_en(chip, &chan_prop->fast_avg_setup);
1452 if (rc < 0) {
1453 pr_err("adc-tm fast-avg enable err\n");
1454 return rc;
1455 }
1456
1457 rc = qpnp_adc_tm_write_reg(chip, QPNP_FAST_AVG_CTL,
1458 chan_prop->fast_avg_setup, 1);
1459 if (rc < 0) {
1460 pr_err("adc-tm fast-avg setup err\n");
1461 return rc;
1462 }
1463
1464 /* Measurement interval setup */
1465 rc = qpnp_adc_tm_timer_interval_select(chip, btm_chan,
1466 chan_prop->chan_prop);
1467 if (rc < 0) {
1468 pr_err("adc-tm timer select failed\n");
1469 return rc;
1470 }
1471
1472 /* Channel configuration setup */
1473 rc = qpnp_adc_tm_channel_configure(chip, btm_chan,
1474 chan_prop->chan_prop, chan_prop->amux_channel);
1475 if (rc < 0) {
1476 pr_err("adc-tm channel configure failed\n");
1477 return rc;
1478 }
1479
1480 /* Recurring interval measurement enable */
1481 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_MEAS_INTERVAL_OP_CTL,
1482 &op_cntrl, 1);
1483 op_cntrl |= QPNP_ADC_MEAS_INTERVAL_OP;
1484 rc = qpnp_adc_tm_reg_update(chip, QPNP_ADC_MEAS_INTERVAL_OP_CTL,
1485 op_cntrl, true);
1486 if (rc < 0) {
1487 pr_err("adc-tm meas interval op configure failed\n");
1488 return rc;
1489 }
1490
1491 /* Enable bank */
1492 rc = qpnp_adc_tm_enable(chip);
1493 if (rc)
1494 return rc;
1495
1496 /* Request conversion */
1497 rc = qpnp_adc_tm_write_reg(chip, QPNP_CONV_REQ, QPNP_CONV_REQ_SET, 1);
1498 if (rc < 0) {
1499 pr_err("adc-tm request conversion failed\n");
1500 return rc;
1501 }
1502
1503 return 0;
1504}
1505
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001506static int qpnp_adc_tm_set_mode(struct qpnp_adc_tm_sensor *adc_tm,
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001507 enum thermal_device_mode mode)
1508{
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001509 struct qpnp_adc_tm_chip *chip = adc_tm->chip;
1510 int rc = 0, channel;
Prasad Malisetty358dda32018-02-20 06:14:26 +05301511 u8 sensor_mask = 0, mode_ctl = 0;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001512 uint32_t btm_chan_idx = 0, btm_chan = 0;
1513
1514 if (qpnp_adc_tm_is_valid(chip)) {
1515 pr_err("invalid device\n");
1516 return -ENODEV;
1517 }
1518
1519 if (qpnp_adc_tm_check_revision(chip, adc_tm->btm_channel_num))
1520 return -EINVAL;
1521
1522 mutex_lock(&chip->adc->adc_lock);
1523
1524 btm_chan = adc_tm->btm_channel_num;
1525 rc = qpnp_adc_tm_get_btm_idx(chip, btm_chan, &btm_chan_idx);
1526 if (rc < 0) {
1527 pr_err("Invalid btm channel idx\n");
1528 goto fail;
1529 }
1530
1531 if (mode == THERMAL_DEVICE_ENABLED) {
1532 chip->adc->amux_prop->amux_channel =
1533 adc_tm->vadc_channel_num;
1534 channel = adc_tm->sensor_num;
1535 chip->adc->amux_prop->decimation =
1536 chip->adc->adc_channels[channel].adc_decimation;
1537 chip->adc->amux_prop->hw_settle_time =
1538 chip->adc->adc_channels[channel].hw_settle_time;
1539 chip->adc->amux_prop->fast_avg_setup =
1540 chip->adc->adc_channels[channel].fast_avg_setup;
1541 chip->adc->amux_prop->mode_sel =
1542 ADC_OP_MEASUREMENT_INTERVAL << QPNP_OP_MODE_SHIFT;
1543 chip->adc->amux_prop->chan_prop->low_thr = adc_tm->low_thr;
1544 chip->adc->amux_prop->chan_prop->high_thr = adc_tm->high_thr;
1545 chip->adc->amux_prop->chan_prop->tm_channel_select =
1546 adc_tm->btm_channel_num;
1547 chip->adc->amux_prop->calib_type =
1548 chip->adc->adc_channels[channel].calib_type;
1549
Prasad Malisetty358dda32018-02-20 06:14:26 +05301550 if (!chip->adc_tm_hc) {
1551 rc = qpnp_adc_tm_configure(chip, chip->adc->amux_prop);
1552 if (rc) {
1553 pr_err("adc-tm configure failed with %d\n", rc);
1554 goto fail;
1555 }
1556 } else {
1557 rc = qpnp_adc_tm_hc_configure(chip,
1558 chip->adc->amux_prop);
1559 if (rc) {
1560 pr_err("hc configure failed with %d\n", rc);
1561 goto fail;
1562 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001563 }
1564 } else if (mode == THERMAL_DEVICE_DISABLED) {
1565 sensor_mask = 1 << adc_tm->sensor_num;
Prasad Malisetty358dda32018-02-20 06:14:26 +05301566 if (!chip->adc_tm_hc) {
1567 mode_ctl = ADC_OP_NORMAL_MODE << QPNP_OP_MODE_SHIFT;
1568 rc = qpnp_adc_tm_mode_select(chip, mode_ctl);
1569 if (rc < 0) {
1570 pr_err("adc-tm single mode select failed\n");
1571 goto fail;
1572 }
1573 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001574
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001575 /* Disable bank */
1576 rc = qpnp_adc_tm_disable(chip);
1577 if (rc < 0) {
1578 pr_err("adc-tm disable failed\n");
1579 goto fail;
1580 }
1581
Prasad Malisetty358dda32018-02-20 06:14:26 +05301582 if (!chip->adc_tm_hc) {
1583 /* Check if a conversion is in progress */
1584 rc = qpnp_adc_tm_req_sts_check(chip);
1585 if (rc < 0) {
1586 pr_err("adc-tm req_sts check failed\n");
1587 goto fail;
1588 }
1589 rc = qpnp_adc_tm_reg_update(chip,
1590 QPNP_ADC_TM_MULTI_MEAS_EN,
1591 sensor_mask, false);
1592 if (rc < 0) {
1593 pr_err("multi measurement update failed\n");
1594 goto fail;
1595 }
1596 } else {
1597 rc = qpnp_adc_tm_reg_update(chip,
1598 QPNP_BTM_Mn_EN(btm_chan_idx),
1599 QPNP_BTM_Mn_MEAS_EN, false);
1600 if (rc < 0) {
1601 pr_err("multi measurement disable failed\n");
1602 goto fail;
1603 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001604 }
1605
1606 rc = qpnp_adc_tm_enable_if_channel_meas(chip);
1607 if (rc < 0) {
1608 pr_err("re-enabling measurement failed\n");
1609 goto fail;
1610 }
1611 }
1612
1613 adc_tm->mode = mode;
1614
1615fail:
1616 mutex_unlock(&chip->adc->adc_lock);
1617
1618 return 0;
1619}
1620
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001621static int qpnp_adc_tm_activate_trip_type(struct qpnp_adc_tm_sensor *adc_tm,
1622 int trip, enum thermal_trip_activation_mode mode)
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001623{
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001624 struct qpnp_adc_tm_chip *chip = adc_tm->chip;
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001625 int rc = 0, sensor_mask = 0;
Prasad Malisetty358dda32018-02-20 06:14:26 +05301626 u8 thr_int_en = 0;
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001627 bool state = false;
1628 uint32_t btm_chan_idx = 0, btm_chan = 0;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001629
1630 if (qpnp_adc_tm_is_valid(chip))
1631 return -ENODEV;
1632
1633 if (qpnp_adc_tm_check_revision(chip, adc_tm->btm_channel_num))
1634 return -EINVAL;
1635
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001636 if (mode == THERMAL_TRIP_ACTIVATION_ENABLED)
1637 state = true;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001638
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001639 sensor_mask = 1 << adc_tm->sensor_num;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001640
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001641 pr_debug("Sensor number:%x with state:%d\n",
1642 adc_tm->sensor_num, state);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001643
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001644 btm_chan = adc_tm->btm_channel_num;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001645 rc = qpnp_adc_tm_get_btm_idx(chip, btm_chan, &btm_chan_idx);
1646 if (rc < 0) {
1647 pr_err("Invalid btm channel idx\n");
1648 return rc;
1649 }
1650
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001651 switch (trip) {
1652 case ADC_TM_TRIP_HIGH_WARM:
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001653 /* low_thr (lower voltage) for higher temp */
Prasad Malisetty358dda32018-02-20 06:14:26 +05301654 thr_int_en = adc_tm_data[btm_chan_idx].low_thr_int_chan_en;
1655 if (!chip->adc_tm_hc)
1656 rc = qpnp_adc_tm_reg_update(chip,
1657 QPNP_ADC_TM_LOW_THR_INT_EN,
1658 sensor_mask, state);
1659 else
1660 rc = qpnp_adc_tm_reg_update(chip,
1661 QPNP_BTM_Mn_EN(btm_chan_idx),
1662 QPNP_BTM_Mn_LOW_THR_INT_EN, state);
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001663 if (rc)
1664 pr_err("channel:%x failed\n", btm_chan);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001665 break;
1666 case ADC_TM_TRIP_LOW_COOL:
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001667 /* high_thr (higher voltage) for cooler temp */
Prasad Malisetty358dda32018-02-20 06:14:26 +05301668 thr_int_en = adc_tm_data[btm_chan_idx].high_thr_int_chan_en;
1669 if (!chip->adc_tm_hc)
1670 rc = qpnp_adc_tm_reg_update(chip,
1671 QPNP_ADC_TM_HIGH_THR_INT_EN,
1672 sensor_mask, state);
1673 else
1674 rc = qpnp_adc_tm_reg_update(chip,
1675 QPNP_BTM_Mn_EN(btm_chan_idx),
1676 QPNP_BTM_Mn_HIGH_THR_INT_EN, state);
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001677 if (rc)
1678 pr_err("channel:%x failed\n", btm_chan);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001679 break;
1680 default:
1681 return -EINVAL;
1682 }
1683
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001684 return rc;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001685}
1686
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001687static int qpnp_adc_tm_set_trip_temp(void *data, int low_temp, int high_temp)
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001688{
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001689 struct qpnp_adc_tm_sensor *adc_tm = data;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001690 struct qpnp_adc_tm_chip *chip = adc_tm->chip;
1691 struct qpnp_adc_tm_config tm_config;
1692 u8 trip_cool_thr0, trip_cool_thr1, trip_warm_thr0, trip_warm_thr1;
1693 uint16_t reg_low_thr_lsb, reg_low_thr_msb;
1694 uint16_t reg_high_thr_lsb, reg_high_thr_msb;
1695 int rc = 0;
1696 uint32_t btm_chan = 0, btm_chan_idx = 0;
1697
1698 if (qpnp_adc_tm_is_valid(chip))
1699 return -ENODEV;
1700
1701 if (qpnp_adc_tm_check_revision(chip, adc_tm->btm_channel_num))
1702 return -EINVAL;
1703
1704 tm_config.channel = adc_tm->vadc_channel_num;
1705 tm_config.high_thr_temp = tm_config.low_thr_temp = 0;
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001706 if (high_temp != INT_MAX)
1707 tm_config.high_thr_temp = high_temp;
1708 if (low_temp != INT_MIN)
1709 tm_config.low_thr_temp = low_temp;
1710
1711 if ((high_temp == INT_MAX) && (low_temp == INT_MIN)) {
1712 pr_err("No trips to set\n");
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001713 return -EINVAL;
1714 }
1715
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001716 pr_debug("requested a high - %d and low - %d\n",
1717 tm_config.high_thr_temp, tm_config.low_thr_temp);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001718 rc = qpnp_adc_tm_scale_therm_voltage_pu2(chip->vadc_dev,
1719 chip->adc->adc_prop, &tm_config);
1720 if (rc < 0) {
1721 pr_err("Failed to lookup the adc-tm thresholds\n");
1722 return rc;
1723 }
1724
1725 trip_warm_thr0 = ((tm_config.low_thr_voltage << 24) >> 24);
1726 trip_warm_thr1 = ((tm_config.low_thr_voltage << 16) >> 24);
1727 trip_cool_thr0 = ((tm_config.high_thr_voltage << 24) >> 24);
1728 trip_cool_thr1 = ((tm_config.high_thr_voltage << 16) >> 24);
1729
1730 pr_debug("low_thr:0x%llx, high_thr:0x%llx\n", tm_config.low_thr_voltage,
1731 tm_config.high_thr_voltage);
1732
1733 btm_chan = adc_tm->btm_channel_num;
1734 rc = qpnp_adc_tm_get_btm_idx(chip, btm_chan, &btm_chan_idx);
1735 if (rc < 0) {
1736 pr_err("Invalid btm channel idx\n");
1737 return rc;
1738 }
1739
Prasad Malisetty358dda32018-02-20 06:14:26 +05301740 if (!chip->adc_tm_hc) {
1741 reg_low_thr_lsb = adc_tm_data[btm_chan_idx].low_thr_lsb_addr;
1742 reg_low_thr_msb = adc_tm_data[btm_chan_idx].low_thr_msb_addr;
1743 reg_high_thr_lsb = adc_tm_data[btm_chan_idx].high_thr_lsb_addr;
1744 reg_high_thr_msb = adc_tm_data[btm_chan_idx].high_thr_msb_addr;
1745 } else {
1746 reg_low_thr_lsb = QPNP_BTM_Mn_LOW_THR0(btm_chan_idx);
1747 reg_low_thr_msb = QPNP_BTM_Mn_LOW_THR1(btm_chan_idx);
1748 reg_high_thr_lsb = QPNP_BTM_Mn_HIGH_THR0(btm_chan_idx);
1749 reg_high_thr_msb = QPNP_BTM_Mn_HIGH_THR1(btm_chan_idx);
1750 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001751
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001752 if (high_temp != INT_MAX) {
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001753 rc = qpnp_adc_tm_write_reg(chip, reg_low_thr_lsb,
1754 trip_cool_thr0, 1);
1755 if (rc) {
1756 pr_err("adc-tm_tm read threshold err\n");
1757 return rc;
1758 }
1759
1760 rc = qpnp_adc_tm_write_reg(chip, reg_low_thr_msb,
1761 trip_cool_thr1, 1);
1762 if (rc) {
1763 pr_err("adc-tm_tm read threshold err\n");
1764 return rc;
1765 }
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001766 adc_tm->low_thr = tm_config.high_thr_voltage;
1767
1768 rc = qpnp_adc_tm_activate_trip_type(adc_tm,
1769 ADC_TM_TRIP_HIGH_WARM,
1770 THERMAL_TRIP_ACTIVATION_ENABLED);
1771 if (rc) {
1772 pr_err("adc-tm warm activation failed\n");
1773 return rc;
1774 }
1775 } else {
1776 rc = qpnp_adc_tm_activate_trip_type(adc_tm,
1777 ADC_TM_TRIP_HIGH_WARM,
1778 THERMAL_TRIP_ACTIVATION_DISABLED);
1779 if (rc) {
1780 pr_err("adc-tm warm deactivation failed\n");
1781 return rc;
1782 }
1783 }
1784
1785 if (low_temp != INT_MIN) {
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001786 rc = qpnp_adc_tm_write_reg(chip, reg_high_thr_lsb,
1787 trip_warm_thr0, 1);
1788 if (rc) {
1789 pr_err("adc-tm_tm read threshold err\n");
1790 return rc;
1791 }
1792
1793 rc = qpnp_adc_tm_write_reg(chip, reg_high_thr_msb,
1794 trip_warm_thr1, 1);
1795 if (rc) {
1796 pr_err("adc-tm_tm read threshold err\n");
1797 return rc;
1798 }
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001799 adc_tm->high_thr = tm_config.low_thr_voltage;
1800
1801 rc = qpnp_adc_tm_activate_trip_type(adc_tm,
1802 ADC_TM_TRIP_LOW_COOL,
1803 THERMAL_TRIP_ACTIVATION_ENABLED);
1804 if (rc) {
1805 pr_err("adc-tm cool activation failed\n");
1806 return rc;
1807 }
1808 } else {
1809 rc = qpnp_adc_tm_activate_trip_type(adc_tm,
1810 ADC_TM_TRIP_LOW_COOL,
1811 THERMAL_TRIP_ACTIVATION_DISABLED);
1812 if (rc) {
1813 pr_err("adc-tm cool deactivation failed\n");
1814 return rc;
1815 }
1816 }
1817
1818 if ((high_temp != INT_MAX) || (low_temp != INT_MIN)) {
1819 rc = qpnp_adc_tm_set_mode(adc_tm, THERMAL_DEVICE_ENABLED);
1820 if (rc) {
1821 pr_err("sensor enabled failed\n");
1822 return rc;
1823 }
1824 } else {
1825 rc = qpnp_adc_tm_set_mode(adc_tm, THERMAL_DEVICE_DISABLED);
1826 if (rc) {
1827 pr_err("sensor disable failed\n");
1828 return rc;
1829 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001830 }
1831
1832 return 0;
1833}
1834
1835static void notify_battery_therm(struct qpnp_adc_tm_sensor *adc_tm)
1836{
1837 struct qpnp_adc_thr_client_info *client_info = NULL;
1838
1839 list_for_each_entry(client_info,
1840 &adc_tm->thr_list, list) {
1841 /* Batt therm's warm temperature translates to low voltage */
1842 if (client_info->notify_low_thr) {
1843 /* HIGH_STATE = WARM_TEMP for battery client */
1844 client_info->btm_param->threshold_notification(
1845 ADC_TM_WARM_STATE, client_info->btm_param->btm_ctx);
1846 client_info->notify_low_thr = false;
1847 }
1848
1849 /* Batt therm's cool temperature translates to high voltage */
1850 if (client_info->notify_high_thr) {
1851 /* LOW_STATE = COOL_TEMP for battery client */
1852 client_info->btm_param->threshold_notification(
1853 ADC_TM_COOL_STATE, client_info->btm_param->btm_ctx);
1854 client_info->notify_high_thr = false;
1855 }
1856 }
1857}
1858
1859static void notify_clients(struct qpnp_adc_tm_sensor *adc_tm)
1860{
1861 struct qpnp_adc_thr_client_info *client_info = NULL;
1862
1863 list_for_each_entry(client_info,
1864 &adc_tm->thr_list, list) {
1865 /* For non batt therm clients */
1866 if (client_info->notify_low_thr) {
1867 if (client_info->btm_param->threshold_notification
1868 != NULL) {
1869 pr_debug("notify kernel with low state\n");
1870 client_info->btm_param->threshold_notification(
1871 ADC_TM_LOW_STATE,
1872 client_info->btm_param->btm_ctx);
1873 client_info->notify_low_thr = false;
1874 }
1875 }
1876
1877 if (client_info->notify_high_thr) {
1878 if (client_info->btm_param->threshold_notification
1879 != NULL) {
1880 pr_debug("notify kernel with high state\n");
1881 client_info->btm_param->threshold_notification(
1882 ADC_TM_HIGH_STATE,
1883 client_info->btm_param->btm_ctx);
1884 client_info->notify_high_thr = false;
1885 }
1886 }
1887 }
1888}
1889
1890static void notify_adc_tm_fn(struct work_struct *work)
1891{
1892 struct qpnp_adc_tm_sensor *adc_tm = container_of(work,
1893 struct qpnp_adc_tm_sensor, work);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001894
1895 if (adc_tm->thermal_node) {
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001896 pr_debug("notifying uspace client\n");
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001897 of_thermal_handle_trip(adc_tm->tz_dev);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001898 } else {
1899 if (adc_tm->scale_type == SCALE_RBATT_THERM)
1900 notify_battery_therm(adc_tm);
1901 else
1902 notify_clients(adc_tm);
1903 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001904}
1905
Prasad Malisetty358dda32018-02-20 06:14:26 +05301906static int qpnp_adc_tm_recalib_request_check(struct qpnp_adc_tm_chip *chip,
1907 int sensor_num, u8 status_high, u8 *notify_check)
1908{
1909 int rc = 0;
1910 u8 sensor_mask = 0, mode_ctl = 0;
1911 int32_t old_thr = 0, new_thr = 0;
1912 uint32_t channel, btm_chan_num, scale_type;
1913 struct qpnp_vadc_result result;
1914 struct qpnp_adc_thr_client_info *client_info = NULL;
1915 struct list_head *thr_list;
1916 bool status = false;
1917
1918 if (!chip->adc_tm_recalib_check) {
1919 *notify_check = 1;
1920 return rc;
1921 }
1922
1923 list_for_each(thr_list, &chip->sensor[sensor_num].thr_list) {
1924 client_info = list_entry(thr_list,
1925 struct qpnp_adc_thr_client_info, list);
1926 channel = client_info->btm_param->channel;
1927 btm_chan_num = chip->sensor[sensor_num].btm_channel_num;
1928 sensor_mask = 1 << sensor_num;
1929
1930 rc = qpnp_vadc_read(chip->vadc_dev, channel, &result);
1931 if (rc < 0) {
1932 pr_err("failure to read vadc channel=%d\n",
1933 client_info->btm_param->channel);
1934 goto fail;
1935 }
1936 new_thr = result.physical;
1937
1938 if (status_high)
1939 old_thr = client_info->btm_param->high_thr;
1940 else
1941 old_thr = client_info->btm_param->low_thr;
1942
1943 if (new_thr > old_thr)
1944 status = (status_high) ? true : false;
1945 else
1946 status = (status_high) ? false : true;
1947
1948 pr_debug(
1949 "recalib:sen=%d, new_thr=%d, new_thr_adc_code=0x%x, old_thr=%d status=%d valid_status=%d\n",
1950 sensor_num, new_thr, result.adc_code,
1951 old_thr, status_high, status);
1952
1953 rc = qpnp_adc_tm_read_thr_value(chip, btm_chan_num);
1954 if (rc < 0) {
1955 pr_err("adc-tm thresholds read failed\n");
1956 goto fail;
1957 }
1958
1959 if (status) {
1960 *notify_check = 1;
1961 pr_debug("Client can be notify\n");
1962 return rc;
1963 }
1964
1965 pr_debug("Client can not be notify, restart measurement\n");
1966 /* Set measurement in single measurement mode */
1967 mode_ctl = ADC_OP_NORMAL_MODE << QPNP_OP_MODE_SHIFT;
1968 rc = qpnp_adc_tm_mode_select(chip, mode_ctl);
1969 if (rc < 0) {
1970 pr_err("adc-tm single mode select failed\n");
1971 goto fail;
1972 }
1973
1974 /* Disable bank */
1975 rc = qpnp_adc_tm_disable(chip);
1976 if (rc < 0) {
1977 pr_err("adc-tm disable failed\n");
1978 goto fail;
1979 }
1980
1981 /* Check if a conversion is in progress */
1982 rc = qpnp_adc_tm_req_sts_check(chip);
1983 if (rc < 0) {
1984 pr_err("adc-tm req_sts check failed\n");
1985 goto fail;
1986 }
1987
1988 rc = qpnp_adc_tm_reg_update(chip, QPNP_ADC_TM_LOW_THR_INT_EN,
1989 sensor_mask, false);
1990 if (rc < 0) {
1991 pr_err("low threshold int write failed\n");
1992 goto fail;
1993 }
1994
1995 rc = qpnp_adc_tm_reg_update(chip, QPNP_ADC_TM_HIGH_THR_INT_EN,
1996 sensor_mask, false);
1997 if (rc < 0) {
1998 pr_err("high threshold int enable failed\n");
1999 goto fail;
2000 }
2001
2002 rc = qpnp_adc_tm_reg_update(chip, QPNP_ADC_TM_MULTI_MEAS_EN,
2003 sensor_mask, false);
2004 if (rc < 0) {
2005 pr_err("multi measurement en failed\n");
2006 goto fail;
2007 }
2008
2009 /* restart measurement */
2010 scale_type = chip->sensor[sensor_num].scale_type;
2011 chip->adc->amux_prop->amux_channel = channel;
2012 chip->adc->amux_prop->decimation =
2013 chip->adc->adc_channels[sensor_num].adc_decimation;
2014 chip->adc->amux_prop->hw_settle_time =
2015 chip->adc->adc_channels[sensor_num].hw_settle_time;
2016 chip->adc->amux_prop->fast_avg_setup =
2017 chip->adc->adc_channels[sensor_num].fast_avg_setup;
2018 chip->adc->amux_prop->mode_sel =
2019 ADC_OP_MEASUREMENT_INTERVAL << QPNP_OP_MODE_SHIFT;
2020 adc_tm_rscale_fn[scale_type].chan(chip->vadc_dev,
2021 client_info->btm_param,
2022 &chip->adc->amux_prop->chan_prop->low_thr,
2023 &chip->adc->amux_prop->chan_prop->high_thr);
2024 qpnp_adc_tm_add_to_list(chip, sensor_num,
2025 client_info->btm_param,
2026 chip->adc->amux_prop->chan_prop);
2027 chip->adc->amux_prop->chan_prop->tm_channel_select =
2028 chip->sensor[sensor_num].btm_channel_num;
2029 chip->adc->amux_prop->chan_prop->state_request =
2030 client_info->btm_param->state_request;
2031
2032 rc = qpnp_adc_tm_configure(chip, chip->adc->amux_prop);
2033 if (rc) {
2034 pr_err("adc-tm configure failed with %d\n", rc);
2035 goto fail;
2036 }
2037 *notify_check = 0;
2038 pr_debug("BTM channel reconfigured for measuremnt\n");
2039 }
2040fail:
2041 return rc;
2042}
2043
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002044static int qpnp_adc_tm_disable_rearm_high_thresholds(
2045 struct qpnp_adc_tm_chip *chip, int sensor_num)
2046{
2047
2048 struct qpnp_adc_thr_client_info *client_info = NULL;
2049 struct list_head *thr_list;
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002050 uint32_t btm_chan_num = 0, btm_chan_idx = 0;
Prasad Malisetty358dda32018-02-20 06:14:26 +05302051 u8 sensor_mask = 0, notify_check = 0;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002052 int rc = 0;
2053
2054 btm_chan_num = chip->sensor[sensor_num].btm_channel_num;
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002055 rc = qpnp_adc_tm_get_btm_idx(chip, btm_chan_num, &btm_chan_idx);
2056 if (rc < 0) {
2057 pr_err("Invalid btm channel idx\n");
2058 return rc;
2059 }
2060
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002061 pr_debug("high:sen:%d, hs:0x%x, ls:0x%x, meas_en:0x%x\n",
2062 sensor_num, chip->th_info.adc_tm_high_enable,
2063 chip->th_info.adc_tm_low_enable,
2064 chip->th_info.qpnp_adc_tm_meas_en);
2065 if (!chip->sensor[sensor_num].thermal_node) {
2066 /*
2067 * For non thermal registered clients such as usb_id,
2068 * vbatt, pmic_therm
2069 */
2070 sensor_mask = 1 << sensor_num;
2071 pr_debug("non thermal node - mask:%x\n", sensor_mask);
Prasad Malisetty358dda32018-02-20 06:14:26 +05302072 if (!chip->adc_tm_hc) {
2073 rc = qpnp_adc_tm_recalib_request_check(chip,
2074 sensor_num, true, &notify_check);
2075 if (rc < 0 || !notify_check) {
2076 pr_debug("Calib recheck re-armed rc=%d\n", rc);
2077 chip->th_info.adc_tm_high_enable = 0;
2078 return rc;
2079 }
2080 } else {
2081 rc = qpnp_adc_tm_reg_update(chip,
2082 QPNP_BTM_Mn_EN(btm_chan_idx),
2083 QPNP_BTM_Mn_HIGH_THR_INT_EN, false);
2084 if (rc < 0) {
2085 pr_err("high threshold int update failed\n");
2086 return rc;
2087 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002088 }
Prasad Malisetty358dda32018-02-20 06:14:26 +05302089 } else {
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002090 /*
2091 * Uses the thermal sysfs registered device to disable
2092 * the corresponding high voltage threshold which
2093 * is triggered by low temp
2094 */
2095 sensor_mask = 1 << sensor_num;
2096 pr_debug("thermal node with mask:%x\n", sensor_mask);
2097 rc = qpnp_adc_tm_activate_trip_type(
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002098 &chip->sensor[sensor_num],
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002099 ADC_TM_TRIP_LOW_COOL,
2100 THERMAL_TRIP_ACTIVATION_DISABLED);
2101 if (rc < 0) {
2102 pr_err("notify error:%d\n", sensor_num);
2103 return rc;
2104 }
2105 }
2106 list_for_each(thr_list, &chip->sensor[sensor_num].thr_list) {
2107 client_info = list_entry(thr_list,
2108 struct qpnp_adc_thr_client_info, list);
2109 if (client_info->high_thr_set) {
2110 client_info->high_thr_set = false;
2111 client_info->notify_high_thr = true;
2112 if (client_info->state_req_copy ==
2113 ADC_TM_HIGH_LOW_THR_ENABLE)
2114 client_info->state_req_copy =
2115 ADC_TM_LOW_THR_ENABLE;
2116 else
2117 client_info->state_req_copy =
2118 ADC_TM_HIGH_THR_DISABLE;
2119 }
2120 }
2121 qpnp_adc_tm_manage_thresholds(chip, sensor_num, btm_chan_num);
2122
Prasad Malisetty358dda32018-02-20 06:14:26 +05302123 if (!chip->adc_tm_hc) {
2124 rc = qpnp_adc_tm_reg_update(chip,
2125 QPNP_ADC_TM_MULTI_MEAS_EN,
2126 sensor_mask, false);
2127 if (rc < 0) {
2128 pr_err("multi meas disable failed\n");
2129 return rc;
2130 }
2131 } else {
2132 rc = qpnp_adc_tm_reg_update(chip,
2133 QPNP_BTM_Mn_EN(sensor_num),
2134 QPNP_BTM_Mn_MEAS_EN, false);
2135 if (rc < 0) {
2136 pr_err("multi meas disable failed\n");
2137 return rc;
2138 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002139 }
2140
2141 rc = qpnp_adc_tm_enable_if_channel_meas(chip);
2142 if (rc < 0) {
2143 pr_err("re-enabling measurement failed\n");
2144 return rc;
2145 }
2146
Jishnu Prakash092c7ce2018-09-18 15:43:01 +05302147 queue_work(chip->sensor[sensor_num].req_wq,
2148 &chip->sensor[sensor_num].work);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002149
2150 return rc;
2151}
2152
2153static int qpnp_adc_tm_disable_rearm_low_thresholds(
2154 struct qpnp_adc_tm_chip *chip, int sensor_num)
2155{
2156 struct qpnp_adc_thr_client_info *client_info = NULL;
2157 struct list_head *thr_list;
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002158 uint32_t btm_chan_num = 0, btm_chan_idx = 0;
Prasad Malisetty358dda32018-02-20 06:14:26 +05302159 u8 sensor_mask = 0, notify_check = 0;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002160 int rc = 0;
2161
2162 btm_chan_num = chip->sensor[sensor_num].btm_channel_num;
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002163 rc = qpnp_adc_tm_get_btm_idx(chip, btm_chan_num, &btm_chan_idx);
2164 if (rc < 0) {
2165 pr_err("Invalid btm channel idx\n");
2166 return rc;
2167 }
2168
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002169 pr_debug("low:sen:%d, hs:0x%x, ls:0x%x, meas_en:0x%x\n",
2170 sensor_num, chip->th_info.adc_tm_high_enable,
2171 chip->th_info.adc_tm_low_enable,
2172 chip->th_info.qpnp_adc_tm_meas_en);
2173 if (!chip->sensor[sensor_num].thermal_node) {
2174 /*
2175 * For non thermal registered clients such as usb_id,
2176 * vbatt, pmic_therm
2177 */
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002178 sensor_mask = 1 << sensor_num;
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002179 pr_debug("non thermal node - mask:%x\n", sensor_mask);
Prasad Malisetty358dda32018-02-20 06:14:26 +05302180 if (!chip->adc_tm_hc) {
2181 rc = qpnp_adc_tm_recalib_request_check(chip,
2182 sensor_num, false, &notify_check);
2183 if (rc < 0 || !notify_check) {
2184 pr_debug("Calib recheck re-armed rc=%d\n", rc);
2185 chip->th_info.adc_tm_low_enable = 0;
2186 return rc;
2187 }
2188 } else {
2189 rc = qpnp_adc_tm_reg_update(chip,
2190 QPNP_BTM_Mn_EN(btm_chan_idx),
2191 QPNP_BTM_Mn_LOW_THR_INT_EN, false);
2192 if (rc < 0) {
2193 pr_err("low threshold int update failed\n");
2194 return rc;
2195 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002196 }
2197 } else {
2198 /*
2199 * Uses the thermal sysfs registered device to disable
2200 * the corresponding high voltage threshold which
2201 * is triggered by low temp
2202 */
2203 sensor_mask = 1 << sensor_num;
2204 pr_debug("thermal node with mask:%x\n", sensor_mask);
2205 rc = qpnp_adc_tm_activate_trip_type(
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002206 &chip->sensor[sensor_num],
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002207 ADC_TM_TRIP_HIGH_WARM,
2208 THERMAL_TRIP_ACTIVATION_DISABLED);
2209 if (rc < 0) {
2210 pr_err("notify error:%d\n", sensor_num);
2211 return rc;
2212 }
2213 }
2214 list_for_each(thr_list, &chip->sensor[sensor_num].thr_list) {
2215 client_info = list_entry(thr_list,
2216 struct qpnp_adc_thr_client_info, list);
2217 if (client_info->low_thr_set) {
2218 client_info->low_thr_set = false;
2219 client_info->notify_low_thr = true;
2220 if (client_info->state_req_copy ==
2221 ADC_TM_HIGH_LOW_THR_ENABLE)
2222 client_info->state_req_copy =
2223 ADC_TM_HIGH_THR_ENABLE;
2224 else
2225 client_info->state_req_copy =
2226 ADC_TM_LOW_THR_DISABLE;
2227 }
2228 }
2229 qpnp_adc_tm_manage_thresholds(chip, sensor_num, btm_chan_num);
2230
Prasad Malisetty358dda32018-02-20 06:14:26 +05302231 if (!chip->adc_tm_hc) {
2232 rc = qpnp_adc_tm_reg_update(chip,
2233 QPNP_ADC_TM_MULTI_MEAS_EN,
2234 sensor_mask, false);
2235 if (rc < 0) {
2236 pr_err("multi meas disable failed\n");
2237 return rc;
2238 }
2239 } else {
2240 rc = qpnp_adc_tm_reg_update(chip,
2241 QPNP_BTM_Mn_EN(sensor_num),
2242 QPNP_BTM_Mn_MEAS_EN, false);
2243 if (rc < 0) {
2244 pr_err("multi meas disable failed\n");
2245 return rc;
2246 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002247 }
2248
2249 rc = qpnp_adc_tm_enable_if_channel_meas(chip);
2250 if (rc < 0) {
2251 pr_err("re-enabling measurement failed\n");
2252 return rc;
2253 }
2254
Jishnu Prakash092c7ce2018-09-18 15:43:01 +05302255 queue_work(chip->sensor[sensor_num].req_wq,
2256 &chip->sensor[sensor_num].work);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002257
2258 return rc;
2259}
2260
2261static int qpnp_adc_tm_read_status(struct qpnp_adc_tm_chip *chip)
2262{
Jishnu Prakash71c39e32018-04-02 19:16:39 +05302263 int rc = 0, sensor_notify_num = 0, i = 0, sensor_num = 0;
2264 unsigned long flags;
2265
2266 if (qpnp_adc_tm_is_valid(chip))
2267 return -ENODEV;
2268
2269 mutex_lock(&chip->adc->adc_lock);
2270
2271 rc = qpnp_adc_tm_req_sts_check(chip);
2272 if (rc) {
2273 pr_err("adc-tm-tm req sts check failed with %d\n", rc);
2274 goto fail;
2275 }
2276
2277 if (chip->th_info.adc_tm_high_enable) {
2278 spin_lock_irqsave(&chip->th_info.adc_tm_high_lock, flags);
2279 sensor_notify_num = chip->th_info.adc_tm_high_enable;
2280 chip->th_info.adc_tm_high_enable = 0;
2281 spin_unlock_irqrestore(&chip->th_info.adc_tm_high_lock, flags);
2282 while (i < chip->max_channels_available) {
2283 if ((sensor_notify_num & 0x1) == 1) {
2284 sensor_num = i;
2285 rc = qpnp_adc_tm_disable_rearm_high_thresholds(
2286 chip, sensor_num);
2287 if (rc < 0) {
2288 pr_err("rearm threshold failed\n");
2289 goto fail;
2290 }
2291 }
2292 sensor_notify_num >>= 1;
2293 i++;
2294 }
2295 }
2296
2297 if (chip->th_info.adc_tm_low_enable) {
2298 spin_lock_irqsave(&chip->th_info.adc_tm_low_lock, flags);
2299 sensor_notify_num = chip->th_info.adc_tm_low_enable;
2300 chip->th_info.adc_tm_low_enable = 0;
2301 spin_unlock_irqrestore(&chip->th_info.adc_tm_low_lock, flags);
2302 i = 0;
2303 while (i < chip->max_channels_available) {
2304 if ((sensor_notify_num & 0x1) == 1) {
2305 sensor_num = i;
2306 rc = qpnp_adc_tm_disable_rearm_low_thresholds(
2307 chip, sensor_num);
2308 if (rc < 0) {
2309 pr_err("rearm threshold failed\n");
2310 goto fail;
2311 }
2312 }
2313 sensor_notify_num >>= 1;
2314 i++;
2315 }
2316 }
2317
2318fail:
2319 mutex_unlock(&chip->adc->adc_lock);
Jishnu Prakash71c39e32018-04-02 19:16:39 +05302320
2321 return rc;
2322}
2323
2324static int qpnp_adc_tm_hc_read_status(struct qpnp_adc_tm_chip *chip)
2325{
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002326 int rc = 0, sensor_num = 0;
2327
2328 if (qpnp_adc_tm_is_valid(chip))
2329 return -ENODEV;
2330
2331 pr_debug("%s\n", __func__);
2332
2333 mutex_lock(&chip->adc->adc_lock);
2334
Prasad Malisetty358dda32018-02-20 06:14:26 +05302335 if (!chip->adc_tm_hc) {
2336 rc = qpnp_adc_tm_req_sts_check(chip);
2337 if (rc) {
2338 pr_err("adc-tm-tm req sts check failed with %d\n", rc);
2339 goto fail;
2340 }
2341 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002342 while (sensor_num < chip->max_channels_available) {
2343 if (chip->sensor[sensor_num].high_thr_triggered) {
2344 rc = qpnp_adc_tm_disable_rearm_high_thresholds(
2345 chip, sensor_num);
2346 if (rc) {
2347 pr_err("rearm threshold failed\n");
2348 goto fail;
2349 }
2350 chip->sensor[sensor_num].high_thr_triggered = false;
2351 }
2352 sensor_num++;
2353 }
2354
2355 sensor_num = 0;
2356 while (sensor_num < chip->max_channels_available) {
2357 if (chip->sensor[sensor_num].low_thr_triggered) {
2358 rc = qpnp_adc_tm_disable_rearm_low_thresholds(
2359 chip, sensor_num);
2360 if (rc) {
2361 pr_err("rearm threshold failed\n");
2362 goto fail;
2363 }
2364 chip->sensor[sensor_num].low_thr_triggered = false;
2365 }
2366 sensor_num++;
2367 }
2368
2369fail:
2370 mutex_unlock(&chip->adc->adc_lock);
2371
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002372 return rc;
2373}
2374
2375static void qpnp_adc_tm_high_thr_work(struct work_struct *work)
2376{
2377 struct qpnp_adc_tm_chip *chip = container_of(work,
2378 struct qpnp_adc_tm_chip, trigger_high_thr_work);
2379 int rc;
2380
2381 /* disable the vote if applicable */
2382 if (chip->adc_vote_enable && chip->adc->hkadc_ldo &&
2383 chip->adc->hkadc_ldo_ok) {
2384 qpnp_adc_disable_voltage(chip->adc);
2385 chip->adc_vote_enable = false;
2386 }
2387
2388 pr_debug("thr:0x%x\n", chip->th_info.adc_tm_high_enable);
2389
Jishnu Prakash71c39e32018-04-02 19:16:39 +05302390 if (!chip->adc_tm_hc) {
2391 rc = qpnp_adc_tm_read_status(chip);
2392 if (rc < 0)
2393 pr_err("adc-tm high thr work failed\n");
2394 } else {
2395 rc = qpnp_adc_tm_hc_read_status(chip);
2396 if (rc < 0)
2397 pr_err("adc-tm-hc high thr work failed\n");
2398 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002399}
2400
Prasad Malisetty358dda32018-02-20 06:14:26 +05302401static irqreturn_t qpnp_adc_tm_high_thr_isr(int irq, void *data)
2402{
2403 struct qpnp_adc_tm_chip *chip = data;
2404 u8 mode_ctl = 0, status1 = 0, sensor_mask = 0;
2405 int rc = 0, sensor_notify_num = 0, i = 0, sensor_num = 0;
2406
2407 mode_ctl = ADC_OP_NORMAL_MODE << QPNP_OP_MODE_SHIFT;
2408 /* Set measurement in single measurement mode */
2409 qpnp_adc_tm_mode_select(chip, mode_ctl);
2410
2411 qpnp_adc_tm_disable(chip);
2412
2413 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_STATUS1, &status1, 1);
2414 if (rc) {
2415 pr_err("adc-tm read status1 failed\n");
2416 return IRQ_HANDLED;
2417 }
2418
2419 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_STATUS_HIGH,
2420 &chip->th_info.status_high, 1);
2421 if (rc) {
2422 pr_err("adc-tm-tm read status high failed with %d\n", rc);
2423 return IRQ_HANDLED;
2424 }
2425
2426 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_HIGH_THR_INT_EN,
2427 &chip->th_info.adc_tm_high_thr_set, 1);
2428 if (rc) {
2429 pr_err("adc-tm-tm read high thr failed with %d\n", rc);
2430 return IRQ_HANDLED;
2431 }
2432
2433 /* Check which interrupt threshold is lower and measure against the
2434 * enabled channel
2435 */
2436 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_MULTI_MEAS_EN,
2437 &chip->th_info.qpnp_adc_tm_meas_en, 1);
2438 if (rc) {
2439 pr_err("adc-tm-tm read status high failed with %d\n", rc);
2440 return IRQ_HANDLED;
2441 }
2442
2443 chip->th_info.adc_tm_high_enable = chip->th_info.qpnp_adc_tm_meas_en &
2444 chip->th_info.status_high;
2445 chip->th_info.adc_tm_high_enable &= chip->th_info.adc_tm_high_thr_set;
2446
2447 sensor_notify_num = chip->th_info.adc_tm_high_enable;
2448 while (i < chip->max_channels_available) {
2449 if ((sensor_notify_num & 0x1) == 1)
2450 sensor_num = i;
2451 sensor_notify_num >>= 1;
2452 i++;
2453 }
2454
2455 if (!chip->sensor[sensor_num].thermal_node) {
2456 sensor_mask = 1 << sensor_num;
2457 rc = qpnp_adc_tm_reg_update(chip,
2458 QPNP_ADC_TM_HIGH_THR_INT_EN,
2459 sensor_mask, false);
2460 if (rc < 0) {
2461 pr_err("high threshold int read failed\n");
2462 return IRQ_HANDLED;
2463 }
2464 } else {
2465 /*
2466 * Uses the thermal sysfs registered device to disable
2467 * the corresponding high voltage threshold which
2468 * is triggered by low temp
2469 */
2470 pr_debug("thermal node with mask:%x\n", sensor_mask);
2471 rc = qpnp_adc_tm_activate_trip_type(
2472 &chip->sensor[sensor_num],
2473 ADC_TM_TRIP_LOW_COOL,
2474 THERMAL_TRIP_ACTIVATION_DISABLED);
2475 if (rc < 0) {
2476 pr_err("notify error:%d\n", sensor_num);
2477 return IRQ_HANDLED;
2478 }
2479 }
2480
Prasad Malisetty358dda32018-02-20 06:14:26 +05302481 queue_work(chip->high_thr_wq, &chip->trigger_high_thr_work);
2482
2483 return IRQ_HANDLED;
2484}
2485
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002486static void qpnp_adc_tm_low_thr_work(struct work_struct *work)
2487{
2488 struct qpnp_adc_tm_chip *chip = container_of(work,
2489 struct qpnp_adc_tm_chip, trigger_low_thr_work);
2490 int rc;
2491
2492 /* disable the vote if applicable */
2493 if (chip->adc_vote_enable && chip->adc->hkadc_ldo &&
2494 chip->adc->hkadc_ldo_ok) {
2495 qpnp_adc_disable_voltage(chip->adc);
2496 chip->adc_vote_enable = false;
2497 }
2498
2499 pr_debug("thr:0x%x\n", chip->th_info.adc_tm_low_enable);
2500
Jishnu Prakash71c39e32018-04-02 19:16:39 +05302501 if (!chip->adc_tm_hc) {
2502 rc = qpnp_adc_tm_read_status(chip);
2503 if (rc < 0)
2504 pr_err("adc-tm low thr work failed\n");
2505 } else {
2506 rc = qpnp_adc_tm_hc_read_status(chip);
2507 if (rc < 0)
2508 pr_err("adc-tm-hc low thr work failed\n");
2509 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002510}
2511
Prasad Malisetty358dda32018-02-20 06:14:26 +05302512static irqreturn_t qpnp_adc_tm_low_thr_isr(int irq, void *data)
2513{
2514 struct qpnp_adc_tm_chip *chip = data;
2515 u8 mode_ctl = 0, status1 = 0, sensor_mask = 0;
2516 int rc = 0, sensor_notify_num = 0, i = 0, sensor_num = 0;
2517
2518 mode_ctl = ADC_OP_NORMAL_MODE << QPNP_OP_MODE_SHIFT;
2519 /* Set measurement in single measurement mode */
2520 qpnp_adc_tm_mode_select(chip, mode_ctl);
2521
2522 qpnp_adc_tm_disable(chip);
2523
2524 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_STATUS1, &status1, 1);
2525 if (rc) {
2526 pr_err("adc-tm read status1 failed\n");
2527 return IRQ_HANDLED;
2528 }
2529
2530 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_STATUS_LOW,
2531 &chip->th_info.status_low, 1);
2532 if (rc) {
2533 pr_err("adc-tm-tm read status low failed with %d\n", rc);
2534 return IRQ_HANDLED;
2535 }
2536
2537 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_LOW_THR_INT_EN,
2538 &chip->th_info.adc_tm_low_thr_set, 1);
2539 if (rc) {
2540 pr_err("adc-tm-tm read low thr failed with %d\n", rc);
2541 return IRQ_HANDLED;
2542 }
2543
2544 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_MULTI_MEAS_EN,
2545 &chip->th_info.qpnp_adc_tm_meas_en, 1);
2546 if (rc) {
2547 pr_err("adc-tm-tm read status high failed with %d\n", rc);
2548 return IRQ_HANDLED;
2549 }
2550
2551 chip->th_info.adc_tm_low_enable = chip->th_info.qpnp_adc_tm_meas_en &
2552 chip->th_info.status_low;
2553 chip->th_info.adc_tm_low_enable &= chip->th_info.adc_tm_low_thr_set;
2554
2555 sensor_notify_num = chip->th_info.adc_tm_low_enable;
2556 while (i < chip->max_channels_available) {
2557 if ((sensor_notify_num & 0x1) == 1)
2558 sensor_num = i;
2559 sensor_notify_num >>= 1;
2560 i++;
2561 }
2562
2563 if (!chip->sensor[sensor_num].thermal_node) {
2564 sensor_mask = 1 << sensor_num;
2565 rc = qpnp_adc_tm_reg_update(chip,
2566 QPNP_ADC_TM_LOW_THR_INT_EN,
2567 sensor_mask, false);
2568 if (rc < 0) {
2569 pr_err("low threshold int read failed\n");
2570 return IRQ_HANDLED;
2571 }
2572 } else {
2573 /*
2574 * Uses the thermal sysfs registered device to disable
2575 * the corresponding low voltage threshold which
2576 * is triggered by high temp
2577 */
2578 pr_debug("thermal node with mask:%x\n", sensor_mask);
2579 rc = qpnp_adc_tm_activate_trip_type(
2580 &chip->sensor[sensor_num],
2581 ADC_TM_TRIP_HIGH_WARM,
2582 THERMAL_TRIP_ACTIVATION_DISABLED);
2583 if (rc < 0) {
2584 pr_err("notify error:%d\n", sensor_num);
2585 return IRQ_HANDLED;
2586 }
2587 }
2588
Prasad Malisetty358dda32018-02-20 06:14:26 +05302589 queue_work(chip->low_thr_wq, &chip->trigger_low_thr_work);
2590
2591 return IRQ_HANDLED;
2592}
2593
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002594static int qpnp_adc_tm_rc_check_sensor_trip(struct qpnp_adc_tm_chip *chip,
2595 u8 status_low, u8 status_high, int i,
2596 int *sensor_low_notify_num, int *sensor_high_notify_num)
2597{
2598 int rc = 0;
2599 u8 ctl = 0, sensor_mask = 0;
2600
2601 if (((status_low & 0x1) == 1) || ((status_high & 0x1) == 1)) {
2602 rc = qpnp_adc_tm_read_reg(chip,
2603 QPNP_BTM_Mn_EN(i), &ctl, 1);
2604 if (rc) {
2605 pr_err("ctl read failed with %d\n", rc);
2606 return IRQ_HANDLED;
2607 }
2608
2609 if ((status_low & 0x1) && (ctl & QPNP_BTM_Mn_MEAS_EN)
2610 && (ctl & QPNP_BTM_Mn_LOW_THR_INT_EN)) {
2611 /* Mask the corresponding low threshold interrupt en */
2612 if (!chip->sensor[i].thermal_node) {
2613 rc = qpnp_adc_tm_reg_update(chip,
2614 QPNP_BTM_Mn_EN(i),
2615 QPNP_BTM_Mn_LOW_THR_INT_EN, false);
2616 if (rc < 0) {
2617 pr_err("low thr_int en failed\n");
2618 return IRQ_HANDLED;
2619 }
2620 } else {
2621 /*
2622 * Uses the thermal sysfs registered device to disable
2623 * the corresponding low voltage threshold which
2624 * is triggered by high temp
2625 */
2626 pr_debug("thermal node with mask:%x\n", sensor_mask);
2627 rc = qpnp_adc_tm_activate_trip_type(
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002628 &chip->sensor[i],
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002629 ADC_TM_TRIP_HIGH_WARM,
2630 THERMAL_TRIP_ACTIVATION_DISABLED);
2631 if (rc < 0) {
2632 pr_err("notify error:%d\n", i);
2633 return IRQ_HANDLED;
2634 }
2635 }
2636 *sensor_low_notify_num |= (status_low & 0x1);
2637 chip->sensor[i].low_thr_triggered = true;
2638 }
2639
2640 if ((status_high & 0x1) && (ctl & QPNP_BTM_Mn_MEAS_EN) &&
2641 (ctl & QPNP_BTM_Mn_HIGH_THR_INT_EN)) {
2642 /* Mask the corresponding high threshold interrupt en */
2643 if (!chip->sensor[i].thermal_node) {
2644 rc = qpnp_adc_tm_reg_update(chip,
2645 QPNP_BTM_Mn_EN(i),
2646 QPNP_BTM_Mn_HIGH_THR_INT_EN, false);
2647 if (rc < 0) {
2648 pr_err("high thr_int en failed\n");
2649 return IRQ_HANDLED;
2650 }
2651 } else {
2652 /*
2653 * Uses the thermal sysfs registered device to disable
2654 * the corresponding high voltage threshold which
2655 * is triggered by low temp
2656 */
2657 pr_debug("thermal node with mask:%x\n", i);
2658 rc = qpnp_adc_tm_activate_trip_type(
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002659 &chip->sensor[i],
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002660 ADC_TM_TRIP_LOW_COOL,
2661 THERMAL_TRIP_ACTIVATION_DISABLED);
2662 if (rc < 0) {
2663 pr_err("notify error:%d\n", i);
2664 return IRQ_HANDLED;
2665 }
2666 }
2667 *sensor_high_notify_num |= (status_high & 0x1);
2668 chip->sensor[i].high_thr_triggered = true;
2669 }
2670 }
2671
2672 return rc;
2673}
2674
2675static irqreturn_t qpnp_adc_tm_rc_thr_isr(int irq, void *data)
2676{
2677 struct qpnp_adc_tm_chip *chip = data;
2678 u8 status_low = 0, status_high = 0;
2679 int rc = 0, sensor_low_notify_num = 0, i = 0;
2680 int sensor_high_notify_num = 0;
2681
2682 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_STATUS_LOW,
2683 &status_low, 1);
2684 if (rc) {
2685 pr_err("adc-tm-tm read status low failed with %d\n", rc);
2686 return IRQ_HANDLED;
2687 }
2688
2689 if (status_low)
2690 chip->th_info.adc_tm_low_enable = status_low;
2691
2692 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_STATUS_HIGH,
2693 &status_high, 1);
2694 if (rc) {
2695 pr_err("adc-tm-tm read status high failed with %d\n", rc);
2696 return IRQ_HANDLED;
2697 }
2698
2699 if (status_high)
2700 chip->th_info.adc_tm_high_enable = status_high;
2701
2702 while (i < chip->max_channels_available) {
2703 rc = qpnp_adc_tm_rc_check_sensor_trip(chip,
2704 status_low, status_high, i,
2705 &sensor_low_notify_num,
2706 &sensor_high_notify_num);
2707 if (rc) {
2708 pr_err("Sensor trip read failed\n");
2709 return IRQ_HANDLED;
2710 }
2711 status_low >>= 1;
2712 status_high >>= 1;
2713 i++;
2714 }
2715
2716 if (sensor_low_notify_num) {
Jishnu Prakash092c7ce2018-09-18 15:43:01 +05302717 pm_wakeup_event(chip->dev,
2718 QPNP_ADC_WAKEUP_SRC_TIMEOUT_MS);
2719 queue_work(chip->low_thr_wq, &chip->trigger_low_thr_work);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002720 }
2721
2722 if (sensor_high_notify_num) {
Jishnu Prakash092c7ce2018-09-18 15:43:01 +05302723 pm_wakeup_event(chip->dev,
2724 QPNP_ADC_WAKEUP_SRC_TIMEOUT_MS);
2725 queue_work(chip->high_thr_wq,
2726 &chip->trigger_high_thr_work);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002727 }
2728
2729 return IRQ_HANDLED;
2730}
2731
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002732static int qpnp_adc_read_temp(void *data, int *temp)
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002733{
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002734 struct qpnp_adc_tm_sensor *adc_tm_sensor = data;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002735 struct qpnp_adc_tm_chip *chip = adc_tm_sensor->chip;
2736 struct qpnp_vadc_result result;
2737 int rc = 0;
2738
2739 rc = qpnp_vadc_read(chip->vadc_dev,
2740 adc_tm_sensor->vadc_channel_num, &result);
2741 if (rc)
2742 return rc;
2743
2744 *temp = result.physical;
2745
2746 return rc;
2747}
2748
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002749static struct thermal_zone_of_device_ops qpnp_adc_tm_thermal_ops = {
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002750 .get_temp = qpnp_adc_read_temp,
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002751 .set_trips = qpnp_adc_tm_set_trip_temp,
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002752};
2753
2754int32_t qpnp_adc_tm_channel_measure(struct qpnp_adc_tm_chip *chip,
2755 struct qpnp_adc_tm_btm_param *param)
2756{
2757 uint32_t channel, amux_prescaling, dt_index = 0, scale_type = 0;
2758 int rc = 0, i = 0, version = 0;
2759 bool chan_found = false;
2760
2761 if (qpnp_adc_tm_is_valid(chip)) {
2762 pr_err("chip not valid\n");
2763 return -ENODEV;
2764 }
2765
2766 if (param->threshold_notification == NULL) {
2767 pr_debug("No notification for high/low temp??\n");
2768 return -EINVAL;
2769 }
2770
2771 mutex_lock(&chip->adc->adc_lock);
2772
2773 channel = param->channel;
2774
2775 if (channel == VSYS) {
2776 version = qpnp_adc_get_revid_version(chip->dev);
2777 if (version == QPNP_REV_ID_PM8950_1_0) {
2778 pr_debug("Channel not supported\n");
2779 rc = -EINVAL;
2780 goto fail_unlock;
2781 }
2782 }
2783
2784 while (i < chip->max_channels_available) {
2785 if (chip->adc->adc_channels[i].channel_num ==
2786 channel) {
2787 dt_index = i;
2788 chan_found = true;
2789 i++;
2790 } else
2791 i++;
2792 }
2793
2794 if (!chan_found) {
2795 pr_err("not a valid ADC_TM channel\n");
2796 rc = -EINVAL;
2797 goto fail_unlock;
2798 }
2799
2800 rc = qpnp_adc_tm_check_revision(chip,
2801 chip->sensor[dt_index].btm_channel_num);
2802 if (rc < 0)
2803 goto fail_unlock;
2804
2805 scale_type = chip->adc->adc_channels[dt_index].adc_scale_fn;
2806 if (scale_type >= SCALE_RSCALE_NONE) {
2807 rc = -EBADF;
2808 goto fail_unlock;
2809 }
2810
2811
2812 amux_prescaling =
2813 chip->adc->adc_channels[dt_index].chan_path_prescaling;
2814
2815 if (amux_prescaling >= PATH_SCALING_NONE) {
2816 rc = -EINVAL;
2817 goto fail_unlock;
2818 }
2819
2820 pr_debug("channel:%d, scale_type:%d, dt_idx:%d",
2821 channel, scale_type, dt_index);
2822 param->gain_num = qpnp_vadc_amux_scaling_ratio[amux_prescaling].num;
2823 param->gain_den = qpnp_vadc_amux_scaling_ratio[amux_prescaling].den;
2824 param->adc_tm_hc = chip->adc_tm_hc;
Siddartha Mohanadossd9e74fe2017-10-13 15:27:55 -07002825 param->full_scale_code = chip->adc->adc_prop->full_scale_code;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002826 chip->adc->amux_prop->amux_channel = channel;
2827 chip->adc->amux_prop->decimation =
2828 chip->adc->adc_channels[dt_index].adc_decimation;
2829 chip->adc->amux_prop->hw_settle_time =
2830 chip->adc->adc_channels[dt_index].hw_settle_time;
2831 chip->adc->amux_prop->fast_avg_setup =
2832 chip->adc->adc_channels[dt_index].fast_avg_setup;
2833 chip->adc->amux_prop->mode_sel =
2834 ADC_OP_MEASUREMENT_INTERVAL << QPNP_OP_MODE_SHIFT;
2835 adc_tm_rscale_fn[scale_type].chan(chip->vadc_dev, param,
2836 &chip->adc->amux_prop->chan_prop->low_thr,
2837 &chip->adc->amux_prop->chan_prop->high_thr);
2838 qpnp_adc_tm_add_to_list(chip, dt_index, param,
2839 chip->adc->amux_prop->chan_prop);
2840 chip->adc->amux_prop->chan_prop->tm_channel_select =
2841 chip->sensor[dt_index].btm_channel_num;
2842 chip->adc->amux_prop->chan_prop->state_request =
2843 param->state_request;
2844 chip->adc->amux_prop->calib_type =
2845 chip->adc->adc_channels[dt_index].calib_type;
Prasad Malisetty358dda32018-02-20 06:14:26 +05302846 if (!chip->adc_tm_hc) {
2847 rc = qpnp_adc_tm_configure(chip, chip->adc->amux_prop);
2848 if (rc) {
2849 pr_err("adc-tm configure failed with %d\n", rc);
2850 goto fail_unlock;
2851 }
2852 } else {
2853 rc = qpnp_adc_tm_hc_configure(chip, chip->adc->amux_prop);
2854 if (rc) {
2855 pr_err("adc-tm hc configure failed with %d\n", rc);
2856 goto fail_unlock;
2857 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002858 }
2859
2860 chip->sensor[dt_index].scale_type = scale_type;
2861
2862fail_unlock:
2863 mutex_unlock(&chip->adc->adc_lock);
2864
2865 return rc;
2866}
2867EXPORT_SYMBOL(qpnp_adc_tm_channel_measure);
2868
2869int32_t qpnp_adc_tm_disable_chan_meas(struct qpnp_adc_tm_chip *chip,
2870 struct qpnp_adc_tm_btm_param *param)
2871{
2872 uint32_t channel, dt_index = 0, btm_chan_num;
Prasad Malisetty358dda32018-02-20 06:14:26 +05302873 u8 sensor_mask = 0, mode_ctl = 0;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002874 int rc = 0;
2875
2876 if (qpnp_adc_tm_is_valid(chip))
2877 return -ENODEV;
2878
2879 mutex_lock(&chip->adc->adc_lock);
2880
Prasad Malisetty358dda32018-02-20 06:14:26 +05302881 if (!chip->adc_tm_hc) {
2882 /* Set measurement in single measurement mode */
2883 mode_ctl = ADC_OP_NORMAL_MODE << QPNP_OP_MODE_SHIFT;
2884 rc = qpnp_adc_tm_mode_select(chip, mode_ctl);
2885 if (rc < 0) {
2886 pr_err("adc-tm single mode select failed\n");
2887 goto fail;
2888 }
2889 }
2890
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002891 /* Disable bank */
2892 rc = qpnp_adc_tm_disable(chip);
2893 if (rc < 0) {
2894 pr_err("adc-tm disable failed\n");
2895 goto fail;
2896 }
2897
Prasad Malisetty358dda32018-02-20 06:14:26 +05302898 if (!chip->adc_tm_hc) {
2899 /* Check if a conversion is in progress */
2900 rc = qpnp_adc_tm_req_sts_check(chip);
2901 if (rc < 0) {
2902 pr_err("adc-tm req_sts check failed\n");
2903 goto fail;
2904 }
2905 }
2906
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002907 channel = param->channel;
2908 while ((chip->adc->adc_channels[dt_index].channel_num
2909 != channel) && (dt_index < chip->max_channels_available))
2910 dt_index++;
2911
2912 if (dt_index >= chip->max_channels_available) {
2913 pr_err("not a valid ADC_TMN channel\n");
2914 rc = -EINVAL;
2915 goto fail;
2916 }
2917
2918 btm_chan_num = chip->sensor[dt_index].btm_channel_num;
2919
Prasad Malisetty358dda32018-02-20 06:14:26 +05302920 if (!chip->adc_tm_hc) {
2921 sensor_mask = 1 << chip->sensor[dt_index].sensor_num;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002922
Prasad Malisetty358dda32018-02-20 06:14:26 +05302923 rc = qpnp_adc_tm_reg_update(chip, QPNP_ADC_TM_LOW_THR_INT_EN,
2924 sensor_mask, false);
2925 if (rc < 0) {
2926 pr_err("high threshold int enable failed\n");
2927 goto fail;
2928 }
2929
2930 rc = qpnp_adc_tm_reg_update(chip, QPNP_ADC_TM_MULTI_MEAS_EN,
2931 sensor_mask, false);
2932 if (rc < 0) {
2933 pr_err("multi measurement en failed\n");
2934 goto fail;
2935 }
2936 } else {
2937 rc = qpnp_adc_tm_reg_update(chip, QPNP_BTM_Mn_EN(btm_chan_num),
2938 QPNP_BTM_Mn_HIGH_THR_INT_EN, false);
2939 if (rc < 0) {
2940 pr_err("high thr disable err:%d\n", btm_chan_num);
2941 return rc;
2942 }
2943
2944 rc = qpnp_adc_tm_reg_update(chip, QPNP_BTM_Mn_EN(btm_chan_num),
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002945 QPNP_BTM_Mn_LOW_THR_INT_EN, false);
Prasad Malisetty358dda32018-02-20 06:14:26 +05302946 if (rc < 0) {
2947 pr_err("low thr disable err:%d\n", btm_chan_num);
2948 return rc;
2949 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002950
Prasad Malisetty358dda32018-02-20 06:14:26 +05302951 rc = qpnp_adc_tm_reg_update(chip, QPNP_BTM_Mn_EN(btm_chan_num),
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002952 QPNP_BTM_Mn_MEAS_EN, false);
Prasad Malisetty358dda32018-02-20 06:14:26 +05302953 if (rc < 0) {
2954 pr_err("multi measurement disable failed\n");
2955 return rc;
2956 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002957 }
2958
2959 rc = qpnp_adc_tm_enable_if_channel_meas(chip);
2960 if (rc < 0)
2961 pr_err("re-enabling measurement failed\n");
2962
2963fail:
2964 mutex_unlock(&chip->adc->adc_lock);
2965
2966 return rc;
2967}
2968EXPORT_SYMBOL(qpnp_adc_tm_disable_chan_meas);
2969
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002970struct qpnp_adc_tm_chip *qpnp_get_adc_tm(struct device *dev, const char *name)
2971{
2972 struct qpnp_adc_tm_chip *chip;
2973 struct device_node *node = NULL;
2974 char prop_name[QPNP_MAX_PROP_NAME_LEN];
2975
2976 snprintf(prop_name, QPNP_MAX_PROP_NAME_LEN, "qcom,%s-adc_tm", name);
2977
2978 node = of_parse_phandle(dev->of_node, prop_name, 0);
2979 if (node == NULL)
2980 return ERR_PTR(-ENODEV);
2981
2982 list_for_each_entry(chip, &qpnp_adc_tm_device_list, list)
2983 if (chip->adc->pdev->dev.of_node == node)
2984 return chip;
2985
2986 return ERR_PTR(-EPROBE_DEFER);
2987}
2988EXPORT_SYMBOL(qpnp_get_adc_tm);
2989
Prasad Malisetty358dda32018-02-20 06:14:26 +05302990static int qpnp_adc_tm_initial_setup(struct qpnp_adc_tm_chip *chip)
2991{
2992 u8 thr_init = 0;
2993 int rc = 0;
2994
2995 rc = qpnp_adc_tm_write_reg(chip, QPNP_ADC_TM_HIGH_THR_INT_EN,
2996 thr_init, 1);
2997 if (rc < 0) {
2998 pr_err("high thr init failed\n");
2999 return rc;
3000 }
3001
3002 rc = qpnp_adc_tm_write_reg(chip, QPNP_ADC_TM_LOW_THR_INT_EN,
3003 thr_init, 1);
3004 if (rc < 0) {
3005 pr_err("low thr init failed\n");
3006 return rc;
3007 }
3008
3009 rc = qpnp_adc_tm_write_reg(chip, QPNP_ADC_TM_MULTI_MEAS_EN,
3010 thr_init, 1);
3011 if (rc < 0) {
3012 pr_err("multi meas en failed\n");
3013 return rc;
3014 }
3015
3016 return rc;
3017}
3018
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003019static const struct of_device_id qpnp_adc_tm_match_table[] = {
3020 { .compatible = "qcom,qpnp-adc-tm" },
3021 { .compatible = "qcom,qpnp-adc-tm-hc" },
Jishnu Prakashd09bc692018-05-02 10:54:28 +05303022 { .compatible = "qcom,qpnp-adc-tm-hc-pm5" },
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003023 {}
3024};
3025
3026static int qpnp_adc_tm_probe(struct platform_device *pdev)
3027{
3028 struct device_node *node = pdev->dev.of_node, *child;
3029 struct qpnp_adc_tm_chip *chip;
3030 struct qpnp_adc_drv *adc_qpnp;
3031 int32_t count_adc_channel_list = 0, rc, sen_idx = 0, i = 0;
3032 bool thermal_node = false;
3033 const struct of_device_id *id;
3034
3035 for_each_child_of_node(node, child)
3036 count_adc_channel_list++;
3037
3038 if (!count_adc_channel_list) {
3039 pr_err("No channel listing\n");
3040 return -EINVAL;
3041 }
3042
3043 id = of_match_node(qpnp_adc_tm_match_table, node);
3044 if (id == NULL) {
3045 pr_err("qpnp_adc_tm_match of_node prop not present\n");
3046 return -ENODEV;
3047 }
3048
3049 chip = devm_kzalloc(&pdev->dev, sizeof(struct qpnp_adc_tm_chip) +
3050 (count_adc_channel_list *
3051 sizeof(struct qpnp_adc_tm_sensor)),
3052 GFP_KERNEL);
3053 if (!chip)
3054 return -ENOMEM;
3055
Jishnu Prakash68b87242018-03-15 20:31:49 +05303056 list_add(&chip->list, &qpnp_adc_tm_device_list);
3057 chip->max_channels_available = count_adc_channel_list;
3058
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003059 adc_qpnp = devm_kzalloc(&pdev->dev, sizeof(struct qpnp_adc_drv),
3060 GFP_KERNEL);
3061 if (!adc_qpnp) {
3062 rc = -ENOMEM;
3063 goto fail;
3064 }
3065
3066 chip->dev = &(pdev->dev);
3067 chip->adc = adc_qpnp;
3068 chip->adc->regmap = dev_get_regmap(pdev->dev.parent, NULL);
3069 if (!chip->adc->regmap) {
3070 dev_err(&pdev->dev, "Couldn't get parent's regmap\n");
3071 rc = -EINVAL;
3072 goto fail;
3073 }
3074
Prasad Malisetty358dda32018-02-20 06:14:26 +05303075 if (of_device_is_compatible(node, "qcom,qpnp-adc-tm-hc")) {
3076 chip->adc_tm_hc = true;
3077 chip->adc->adc_hc = true;
3078 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003079
3080 rc = qpnp_adc_get_devicetree_data(pdev, chip->adc);
3081 if (rc) {
3082 dev_err(&pdev->dev, "failed to read device tree\n");
3083 goto fail;
3084 }
3085 mutex_init(&chip->adc->adc_lock);
3086
Prasad Malisetty358dda32018-02-20 06:14:26 +05303087 /* Register the ADC peripheral interrupt */
3088 if (!chip->adc_tm_hc) {
3089 chip->adc->adc_high_thr_irq = platform_get_irq_byname(pdev,
3090 "high-thr-en-set");
3091 if (chip->adc->adc_high_thr_irq < 0) {
3092 pr_err("Invalid irq\n");
3093 rc = -ENXIO;
3094 goto fail;
3095 }
3096
3097 chip->adc->adc_low_thr_irq = platform_get_irq_byname(pdev,
3098 "low-thr-en-set");
3099 if (chip->adc->adc_low_thr_irq < 0) {
3100 pr_err("Invalid irq\n");
3101 rc = -ENXIO;
3102 goto fail;
3103 }
3104 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003105 chip->vadc_dev = qpnp_get_vadc(&pdev->dev, "adc_tm");
3106 if (IS_ERR(chip->vadc_dev)) {
3107 rc = PTR_ERR(chip->vadc_dev);
3108 if (rc != -EPROBE_DEFER)
3109 pr_err("vadc property missing, rc=%d\n", rc);
3110 goto fail;
3111 }
3112
3113 chip->adc_tm_recalib_check = of_property_read_bool(node,
3114 "qcom,adc-tm-recalib-check");
3115
3116 for_each_child_of_node(node, child) {
3117 char name[25];
3118 int btm_channel_num, timer_select = 0;
3119
3120 rc = of_property_read_u32(child,
3121 "qcom,btm-channel-number", &btm_channel_num);
3122 if (rc) {
3123 pr_err("Invalid btm channel number\n");
3124 goto fail;
3125 }
3126 rc = of_property_read_u32(child,
3127 "qcom,meas-interval-timer-idx", &timer_select);
3128 if (rc) {
3129 pr_debug("Default to timer2 with interval of 1 sec\n");
3130 chip->sensor[sen_idx].timer_select =
3131 ADC_MEAS_TIMER_SELECT2;
3132 chip->sensor[sen_idx].meas_interval =
3133 ADC_MEAS2_INTERVAL_1S;
3134 } else {
3135 if (timer_select >= ADC_MEAS_TIMER_NUM) {
3136 pr_err("Invalid timer selection number\n");
3137 goto fail;
3138 }
3139 chip->sensor[sen_idx].timer_select = timer_select;
3140 if (timer_select == ADC_MEAS_TIMER_SELECT1)
3141 chip->sensor[sen_idx].meas_interval =
3142 ADC_MEAS1_INTERVAL_3P9MS;
3143 else if (timer_select == ADC_MEAS_TIMER_SELECT3)
3144 chip->sensor[sen_idx].meas_interval =
3145 ADC_MEAS3_INTERVAL_4S;
3146 else if (timer_select == ADC_MEAS_TIMER_SELECT2)
3147 chip->sensor[sen_idx].meas_interval =
3148 ADC_MEAS2_INTERVAL_1S;
3149 }
3150
3151 chip->sensor[sen_idx].btm_channel_num = btm_channel_num;
3152 chip->sensor[sen_idx].vadc_channel_num =
3153 chip->adc->adc_channels[sen_idx].channel_num;
3154 chip->sensor[sen_idx].sensor_num = sen_idx;
3155 chip->sensor[sen_idx].chip = chip;
3156 pr_debug("btm_chan:%x, vadc_chan:%x\n", btm_channel_num,
3157 chip->adc->adc_channels[sen_idx].channel_num);
3158 thermal_node = of_property_read_bool(child,
3159 "qcom,thermal-node");
3160 if (thermal_node) {
3161 /* Register with the thermal zone */
3162 pr_debug("thermal node%x\n", btm_channel_num);
3163 chip->sensor[sen_idx].mode = THERMAL_DEVICE_DISABLED;
3164 chip->sensor[sen_idx].thermal_node = true;
3165 snprintf(name, sizeof(name), "%s",
3166 chip->adc->adc_channels[sen_idx].name);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003167 chip->sensor[sen_idx].low_thr =
3168 QPNP_ADC_TM_M0_LOW_THR;
3169 chip->sensor[sen_idx].high_thr =
3170 QPNP_ADC_TM_M0_HIGH_THR;
3171 chip->sensor[sen_idx].tz_dev =
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07003172 devm_thermal_zone_of_sensor_register(
3173 chip->dev,
3174 chip->sensor[sen_idx].vadc_channel_num,
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003175 &chip->sensor[sen_idx],
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07003176 &qpnp_adc_tm_thermal_ops);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003177 if (IS_ERR(chip->sensor[sen_idx].tz_dev))
3178 pr_err("thermal device register failed.\n");
3179 }
3180 chip->sensor[sen_idx].req_wq = alloc_workqueue(
3181 "qpnp_adc_notify_wq", WQ_HIGHPRI, 0);
3182 if (!chip->sensor[sen_idx].req_wq) {
3183 pr_err("Requesting priority wq failed\n");
3184 goto fail;
3185 }
3186 INIT_WORK(&chip->sensor[sen_idx].work, notify_adc_tm_fn);
3187 INIT_LIST_HEAD(&chip->sensor[sen_idx].thr_list);
3188 sen_idx++;
3189 }
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07003190
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003191 chip->high_thr_wq = alloc_workqueue("qpnp_adc_tm_high_thr_wq",
3192 WQ_HIGHPRI, 0);
3193 if (!chip->high_thr_wq) {
3194 pr_err("Requesting high thr priority wq failed\n");
3195 goto fail;
3196 }
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07003197
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003198 chip->low_thr_wq = alloc_workqueue("qpnp_adc_tm_low_thr_wq",
3199 WQ_HIGHPRI, 0);
3200 if (!chip->low_thr_wq) {
3201 pr_err("Requesting low thr priority wq failed\n");
3202 goto fail;
3203 }
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07003204
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003205 chip->thr_wq = alloc_workqueue("qpnp_adc_tm_thr_wq",
3206 WQ_HIGHPRI, 0);
3207 if (!chip->thr_wq) {
3208 pr_err("Requesting thr priority wq failed\n");
3209 goto fail;
3210 }
3211
3212 INIT_WORK(&chip->trigger_high_thr_work, qpnp_adc_tm_high_thr_work);
3213 INIT_WORK(&chip->trigger_low_thr_work, qpnp_adc_tm_low_thr_work);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003214
Prasad Malisetty358dda32018-02-20 06:14:26 +05303215 if (!chip->adc_tm_hc) {
3216 rc = qpnp_adc_tm_initial_setup(chip);
3217 if (rc)
3218 goto fail;
3219 rc = devm_request_irq(&pdev->dev, chip->adc->adc_high_thr_irq,
3220 qpnp_adc_tm_high_thr_isr,
3221 IRQF_TRIGGER_RISING, "qpnp_adc_tm_high_interrupt", chip);
3222 if (rc) {
3223 dev_err(&pdev->dev, "failed to request adc irq\n");
3224 goto fail;
3225 } else {
3226 enable_irq_wake(chip->adc->adc_high_thr_irq);
3227 }
3228
3229 rc = devm_request_irq(&pdev->dev, chip->adc->adc_low_thr_irq,
3230 qpnp_adc_tm_low_thr_isr,
3231 IRQF_TRIGGER_RISING,
3232 "qpnp_adc_tm_low_interrupt", chip);
3233 if (rc) {
3234 dev_err(&pdev->dev, "failed to request adc irq\n");
3235 goto fail;
3236 } else {
3237 enable_irq_wake(chip->adc->adc_low_thr_irq);
3238 }
3239 } else {
3240 rc = devm_request_irq(&pdev->dev, chip->adc->adc_irq_eoc,
3241 qpnp_adc_tm_rc_thr_isr,
Jishnu Prakash04ee9ec2019-04-23 18:36:04 +05303242 IRQF_TRIGGER_RISING, "qpnp_adc_tm_interrupt", chip);
Prasad Malisetty358dda32018-02-20 06:14:26 +05303243 if (rc)
3244 dev_err(&pdev->dev, "failed to request adc irq\n");
3245 else
3246 enable_irq_wake(chip->adc->adc_irq_eoc);
3247 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003248
3249 chip->adc_vote_enable = false;
3250 dev_set_drvdata(&pdev->dev, chip);
Prasad Malisetty358dda32018-02-20 06:14:26 +05303251 spin_lock_init(&chip->th_info.adc_tm_low_lock);
3252 spin_lock_init(&chip->th_info.adc_tm_high_lock);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003253
3254 pr_debug("OK\n");
3255 return 0;
3256fail:
3257 for_each_child_of_node(node, child) {
3258 thermal_node = of_property_read_bool(child,
3259 "qcom,thermal-node");
3260 if (thermal_node) {
3261 thermal_zone_device_unregister(chip->sensor[i].tz_dev);
3262 if (chip->sensor[i].req_wq)
3263 destroy_workqueue(chip->sensor[sen_idx].req_wq);
3264 }
3265 }
3266 if (chip->high_thr_wq)
3267 destroy_workqueue(chip->high_thr_wq);
3268 if (chip->low_thr_wq)
3269 destroy_workqueue(chip->low_thr_wq);
Jishnu Prakash68b87242018-03-15 20:31:49 +05303270 list_del(&chip->list);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003271 dev_set_drvdata(&pdev->dev, NULL);
3272 return rc;
3273}
3274
3275static int qpnp_adc_tm_remove(struct platform_device *pdev)
3276{
3277 struct qpnp_adc_tm_chip *chip = dev_get_drvdata(&pdev->dev);
3278 struct device_node *node = pdev->dev.of_node, *child;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003279 int i = 0;
3280
3281 for_each_child_of_node(node, child) {
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07003282 if (chip->sensor[i].req_wq)
3283 destroy_workqueue(chip->sensor[i].req_wq);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003284 i++;
3285 }
3286
3287 if (chip->high_thr_wq)
3288 destroy_workqueue(chip->high_thr_wq);
3289 if (chip->low_thr_wq)
3290 destroy_workqueue(chip->low_thr_wq);
3291 if (chip->adc->hkadc_ldo && chip->adc->hkadc_ldo_ok)
3292 qpnp_adc_free_voltage_resource(chip->adc);
3293 dev_set_drvdata(&pdev->dev, NULL);
3294
3295 return 0;
3296}
3297
3298static void qpnp_adc_tm_shutdown(struct platform_device *pdev)
3299{
3300 struct qpnp_adc_tm_chip *chip = dev_get_drvdata(&pdev->dev);
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07003301 int rc = 0, i = 0;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003302
3303 /* Disable bank */
3304 rc = qpnp_adc_tm_disable(chip);
3305 if (rc < 0)
3306 pr_err("adc-tm disable failed\n");
3307
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07003308 for (i = 0; i < QPNP_BTM_CHANNELS; i++) {
3309 rc = qpnp_adc_tm_reg_update(chip,
3310 QPNP_BTM_Mn_EN(i),
3311 QPNP_BTM_Mn_MEAS_EN, false);
3312 if (rc < 0)
3313 pr_err("multi measurement disable failed\n");
3314 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003315}
3316
3317static int qpnp_adc_tm_suspend_noirq(struct device *dev)
3318{
3319 struct qpnp_adc_tm_chip *chip = dev_get_drvdata(dev);
Jishnu Prakash092c7ce2018-09-18 15:43:01 +05303320 struct device_node *node = dev->of_node, *child;
3321 int i = 0;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003322
Jishnu Prakash092c7ce2018-09-18 15:43:01 +05303323 flush_workqueue(chip->high_thr_wq);
3324 flush_workqueue(chip->low_thr_wq);
3325
3326 for_each_child_of_node(node, child) {
3327 if (chip->sensor[i].req_wq) {
3328 pr_debug("flushing queue for sensor %d\n", i);
3329 flush_workqueue(chip->sensor[i].req_wq);
3330 }
3331 i++;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003332 }
3333 return 0;
3334}
3335
3336static const struct dev_pm_ops qpnp_adc_tm_pm_ops = {
3337 .suspend_noirq = qpnp_adc_tm_suspend_noirq,
3338};
3339
3340static struct platform_driver qpnp_adc_tm_driver = {
3341 .driver = {
3342 .name = "qcom,qpnp-adc-tm",
3343 .of_match_table = qpnp_adc_tm_match_table,
3344 .pm = &qpnp_adc_tm_pm_ops,
3345 },
3346 .probe = qpnp_adc_tm_probe,
3347 .remove = qpnp_adc_tm_remove,
3348 .shutdown = qpnp_adc_tm_shutdown,
3349};
3350
3351static int __init qpnp_adc_tm_init(void)
3352{
3353 return platform_driver_register(&qpnp_adc_tm_driver);
3354}
3355module_init(qpnp_adc_tm_init);
3356
3357static void __exit qpnp_adc_tm_exit(void)
3358{
3359 platform_driver_unregister(&qpnp_adc_tm_driver);
3360}
3361module_exit(qpnp_adc_tm_exit);
3362
3363MODULE_DESCRIPTION("QPNP PMIC ADC Threshold Monitoring driver");
3364MODULE_LICENSE("GPL v2");