blob: f19ee607619ef1f660b49ad2a190f94f69f90bc0 [file] [log] [blame]
Siddartha Mohanadosscb813fd2017-12-20 15:06:42 -08001/* Copyright (c) 2012-2018, 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
194#define QPNP_ADC_TM_MEAS_INTERVAL_TIME_SHIFT 0x3
195#define QPNP_ADC_TM_MEAS_INTERVAL_CTL2_SHIFT 0x4
196#define QPNP_ADC_TM_MEAS_INTERVAL_CTL2_MASK 0xf0
197#define QPNP_ADC_TM_MEAS_INTERVAL_CTL3_MASK 0xf
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800198
199#define QPNP_BTM_Mn_ADC_CH_SEL_CTL(n) ((n * 8) + 0x60)
200#define QPNP_BTM_Mn_LOW_THR0(n) ((n * 8) + 0x61)
201#define QPNP_BTM_Mn_LOW_THR1(n) ((n * 8) + 0x62)
202#define QPNP_BTM_Mn_HIGH_THR0(n) ((n * 8) + 0x63)
203#define QPNP_BTM_Mn_HIGH_THR1(n) ((n * 8) + 0x64)
204#define QPNP_BTM_Mn_MEAS_INTERVAL_CTL(n) ((n * 8) + 0x65)
205#define QPNP_BTM_Mn_CTL(n) ((n * 8) + 0x66)
206#define QPNP_BTM_CTL_HW_SETTLE_DELAY_MASK 0xf
207#define QPNP_BTM_CTL_CAL_SEL 0x30
208#define QPNP_BTM_CTL_CAL_SEL_MASK_SHIFT 4
209#define QPNP_BTM_CTL_CAL_VAL 0x40
210
211#define QPNP_BTM_Mn_EN(n) ((n * 8) + 0x67)
212#define QPNP_BTM_Mn_MEAS_EN BIT(7)
213#define QPNP_BTM_Mn_HIGH_THR_INT_EN BIT(1)
214#define QPNP_BTM_Mn_LOW_THR_INT_EN BIT(0)
215
216#define QPNP_BTM_Mn_DATA0(n) ((n * 2) + 0xa0)
217#define QPNP_BTM_Mn_DATA1(n) ((n * 2) + 0xa1)
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -0700218#define QPNP_BTM_CHANNELS 8
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800219
220/* QPNP ADC TM HC end */
221
222struct qpnp_adc_thr_info {
223 u8 status_low;
224 u8 status_high;
225 u8 qpnp_adc_tm_meas_en;
226 u8 adc_tm_low_enable;
227 u8 adc_tm_high_enable;
228 u8 adc_tm_low_thr_set;
229 u8 adc_tm_high_thr_set;
Prasad Malisetty358dda32018-02-20 06:14:26 +0530230 spinlock_t adc_tm_low_lock;
231 spinlock_t adc_tm_high_lock;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800232};
233
234struct qpnp_adc_thr_client_info {
235 struct list_head list;
236 struct qpnp_adc_tm_btm_param *btm_param;
237 int32_t low_thr_requested;
238 int32_t high_thr_requested;
239 enum qpnp_state_request state_requested;
240 enum qpnp_state_request state_req_copy;
241 bool low_thr_set;
242 bool high_thr_set;
243 bool notify_low_thr;
244 bool notify_high_thr;
245};
246
247struct qpnp_adc_tm_sensor {
248 struct thermal_zone_device *tz_dev;
249 struct qpnp_adc_tm_chip *chip;
250 enum thermal_device_mode mode;
251 uint32_t sensor_num;
252 enum qpnp_adc_meas_timer_select timer_select;
253 uint32_t meas_interval;
254 uint32_t low_thr;
255 uint32_t high_thr;
256 uint32_t btm_channel_num;
257 uint32_t vadc_channel_num;
258 struct workqueue_struct *req_wq;
259 struct work_struct work;
260 bool thermal_node;
261 uint32_t scale_type;
262 struct list_head thr_list;
263 bool high_thr_triggered;
264 bool low_thr_triggered;
265};
266
267struct qpnp_adc_tm_chip {
268 struct device *dev;
269 struct qpnp_adc_drv *adc;
270 struct list_head list;
271 bool adc_tm_initialized;
272 bool adc_tm_recalib_check;
273 int max_channels_available;
274 atomic_t wq_cnt;
275 struct qpnp_vadc_chip *vadc_dev;
276 struct workqueue_struct *high_thr_wq;
277 struct workqueue_struct *low_thr_wq;
278 struct workqueue_struct *thr_wq;
279 struct work_struct trigger_high_thr_work;
280 struct work_struct trigger_low_thr_work;
281 struct work_struct trigger_thr_work;
282 bool adc_vote_enable;
283 struct qpnp_adc_thr_info th_info;
284 bool adc_tm_hc;
285 struct qpnp_adc_tm_sensor sensor[0];
286};
287
288LIST_HEAD(qpnp_adc_tm_device_list);
289
Prasad Malisetty358dda32018-02-20 06:14:26 +0530290struct qpnp_adc_tm_trip_reg_type {
291 enum qpnp_adc_tm_channel_select btm_amux_chan;
292 uint16_t low_thr_lsb_addr;
293 uint16_t low_thr_msb_addr;
294 uint16_t high_thr_lsb_addr;
295 uint16_t high_thr_msb_addr;
296 u8 multi_meas_en;
297 u8 low_thr_int_chan_en;
298 u8 high_thr_int_chan_en;
299 u8 meas_interval_ctl;
300};
301
302static struct qpnp_adc_tm_trip_reg_type adc_tm_data[] = {
303 [QPNP_ADC_TM_CHAN0] = {QPNP_ADC_TM_M0_ADC_CH_SEL_CTL,
304 QPNP_M0_LOW_THR_LSB,
305 QPNP_M0_LOW_THR_MSB, QPNP_M0_HIGH_THR_LSB,
306 QPNP_M0_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M0,
307 QPNP_ADC_TM_LOW_THR_INT_EN_M0, QPNP_ADC_TM_HIGH_THR_INT_EN_M0,
308 QPNP_ADC_TM_M0_MEAS_INTERVAL_CTL},
309 [QPNP_ADC_TM_CHAN1] = {QPNP_ADC_TM_M1_ADC_CH_SEL_CTL,
310 QPNP_M1_LOW_THR_LSB,
311 QPNP_M1_LOW_THR_MSB, QPNP_M1_HIGH_THR_LSB,
312 QPNP_M1_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M1,
313 QPNP_ADC_TM_LOW_THR_INT_EN_M1, QPNP_ADC_TM_HIGH_THR_INT_EN_M1,
314 QPNP_ADC_TM_M1_MEAS_INTERVAL_CTL},
315 [QPNP_ADC_TM_CHAN2] = {QPNP_ADC_TM_M2_ADC_CH_SEL_CTL,
316 QPNP_M2_LOW_THR_LSB,
317 QPNP_M2_LOW_THR_MSB, QPNP_M2_HIGH_THR_LSB,
318 QPNP_M2_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M2,
319 QPNP_ADC_TM_LOW_THR_INT_EN_M2, QPNP_ADC_TM_HIGH_THR_INT_EN_M2,
320 QPNP_ADC_TM_M2_MEAS_INTERVAL_CTL},
321 [QPNP_ADC_TM_CHAN3] = {QPNP_ADC_TM_M3_ADC_CH_SEL_CTL,
322 QPNP_M3_LOW_THR_LSB,
323 QPNP_M3_LOW_THR_MSB, QPNP_M3_HIGH_THR_LSB,
324 QPNP_M3_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M3,
325 QPNP_ADC_TM_LOW_THR_INT_EN_M3, QPNP_ADC_TM_HIGH_THR_INT_EN_M3,
326 QPNP_ADC_TM_M3_MEAS_INTERVAL_CTL},
327 [QPNP_ADC_TM_CHAN4] = {QPNP_ADC_TM_M4_ADC_CH_SEL_CTL,
328 QPNP_M4_LOW_THR_LSB,
329 QPNP_M4_LOW_THR_MSB, QPNP_M4_HIGH_THR_LSB,
330 QPNP_M4_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M4,
331 QPNP_ADC_TM_LOW_THR_INT_EN_M4, QPNP_ADC_TM_HIGH_THR_INT_EN_M4,
332 QPNP_ADC_TM_M4_MEAS_INTERVAL_CTL},
333 [QPNP_ADC_TM_CHAN5] = {QPNP_ADC_TM_M5_ADC_CH_SEL_CTL,
334 QPNP_M5_LOW_THR_LSB,
335 QPNP_M5_LOW_THR_MSB, QPNP_M5_HIGH_THR_LSB,
336 QPNP_M5_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M5,
337 QPNP_ADC_TM_LOW_THR_INT_EN_M5, QPNP_ADC_TM_HIGH_THR_INT_EN_M5,
338 QPNP_ADC_TM_M5_MEAS_INTERVAL_CTL},
339 [QPNP_ADC_TM_CHAN6] = {QPNP_ADC_TM_M6_ADC_CH_SEL_CTL,
340 QPNP_M6_LOW_THR_LSB,
341 QPNP_M6_LOW_THR_MSB, QPNP_M6_HIGH_THR_LSB,
342 QPNP_M6_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M6,
343 QPNP_ADC_TM_LOW_THR_INT_EN_M6, QPNP_ADC_TM_HIGH_THR_INT_EN_M6,
344 QPNP_ADC_TM_M6_MEAS_INTERVAL_CTL},
345 [QPNP_ADC_TM_CHAN7] = {QPNP_ADC_TM_M7_ADC_CH_SEL_CTL,
346 QPNP_M7_LOW_THR_LSB,
347 QPNP_M7_LOW_THR_MSB, QPNP_M7_HIGH_THR_LSB,
348 QPNP_M7_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M7,
349 QPNP_ADC_TM_LOW_THR_INT_EN_M7, QPNP_ADC_TM_HIGH_THR_INT_EN_M7,
350 QPNP_ADC_TM_M7_MEAS_INTERVAL_CTL},
351};
352
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800353static struct qpnp_adc_tm_reverse_scale_fn adc_tm_rscale_fn[] = {
354 [SCALE_R_VBATT] = {qpnp_adc_vbatt_rscaler},
355 [SCALE_RBATT_THERM] = {qpnp_adc_btm_scaler},
356 [SCALE_R_USB_ID] = {qpnp_adc_usb_scaler},
357 [SCALE_RPMIC_THERM] = {qpnp_adc_scale_millidegc_pmic_voltage_thr},
358 [SCALE_R_SMB_BATT_THERM] = {qpnp_adc_smb_btm_rscaler},
359 [SCALE_R_ABSOLUTE] = {qpnp_adc_absolute_rthr},
360 [SCALE_QRD_SKUH_RBATT_THERM] = {qpnp_adc_qrd_skuh_btm_scaler},
361 [SCALE_QRD_SKUT1_RBATT_THERM] = {qpnp_adc_qrd_skut1_btm_scaler},
362};
363
364static int32_t qpnp_adc_tm_read_reg(struct qpnp_adc_tm_chip *chip,
365 int16_t reg, u8 *data, int len)
366{
367 int rc = 0;
368
369 rc = regmap_bulk_read(chip->adc->regmap, (chip->adc->offset + reg),
370 data, len);
371 if (rc < 0)
372 pr_err("adc-tm read reg %d failed with %d\n", reg, rc);
373
374 return rc;
375}
376
377static int32_t qpnp_adc_tm_write_reg(struct qpnp_adc_tm_chip *chip,
378 int16_t reg, u8 data, int len)
379{
380 int rc = 0;
381 u8 *buf;
382
383 buf = &data;
384
385 rc = regmap_bulk_write(chip->adc->regmap, (chip->adc->offset + reg),
386 buf, len);
387 if (rc < 0)
388 pr_err("adc-tm write reg %d failed with %d\n", reg, rc);
389
390 return rc;
391}
392
Prasad Malisetty358dda32018-02-20 06:14:26 +0530393static int32_t qpnp_adc_tm_fast_avg_en(struct qpnp_adc_tm_chip *chip,
394 uint32_t *fast_avg_sample)
395{
396 int rc = 0, version = 0;
397 u8 fast_avg_en = 0;
398
399 version = qpnp_adc_get_revid_version(chip->dev);
400 if (!((version == QPNP_REV_ID_8916_1_0) ||
401 (version == QPNP_REV_ID_8916_1_1) ||
402 (version == QPNP_REV_ID_8916_2_0))) {
403 pr_debug("fast-avg-en not required for this version\n");
404 return rc;
405 }
406
407 fast_avg_en = QPNP_FAST_AVG_ENABLED;
408 rc = qpnp_adc_tm_write_reg(chip, QPNP_FAST_AVG_EN, fast_avg_en, 1);
409 if (rc < 0) {
410 pr_err("adc-tm fast-avg enable err\n");
411 return rc;
412 }
413
414 if (*fast_avg_sample >= 3)
415 *fast_avg_sample = 2;
416
417 return rc;
418}
419
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800420static int qpnp_adc_tm_check_vreg_vote(struct qpnp_adc_tm_chip *chip)
421{
422 int rc = 0;
423
424 if (!chip->adc_vote_enable) {
425 if (chip->adc->hkadc_ldo && chip->adc->hkadc_ldo_ok) {
426 rc = qpnp_adc_enable_voltage(chip->adc);
427 if (rc) {
428 pr_err("failed enabling VADC LDO\n");
429 return rc;
430 }
431 chip->adc_vote_enable = true;
432 }
433 }
434
435 return rc;
436}
437
438static int32_t qpnp_adc_tm_enable(struct qpnp_adc_tm_chip *chip)
439{
440 int rc = 0;
441 u8 data = 0;
442
443 rc = qpnp_adc_tm_check_vreg_vote(chip);
444 if (rc) {
445 pr_err("ADC TM VREG enable failed:%d\n", rc);
446 return rc;
447 }
448
449 data = QPNP_ADC_TM_EN;
450 rc = qpnp_adc_tm_write_reg(chip, QPNP_EN_CTL1, data, 1);
451 if (rc < 0) {
452 pr_err("adc-tm enable failed\n");
453 return rc;
454 }
455
Prasad Malisetty358dda32018-02-20 06:14:26 +0530456 if (chip->adc_tm_hc) {
457 data = QPNP_ADC_CONV_REQ_EN;
458 rc = qpnp_adc_tm_write_reg(chip, QPNP_BTM_CONV_REQ, data, 1);
459 if (rc < 0) {
460 pr_err("adc-tm enable failed\n");
461 return rc;
462 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800463 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800464 return rc;
465}
466
467static int32_t qpnp_adc_tm_disable(struct qpnp_adc_tm_chip *chip)
468{
Prasad Malisetty358dda32018-02-20 06:14:26 +0530469 u8 data = 0;
470 int rc = 0;
471
Rama Krishna Phani A66e48b42018-03-13 18:29:08 +0530472 if (!chip->adc_tm_hc) {
473 rc = qpnp_adc_tm_write_reg(chip, QPNP_EN_CTL1, data, 1);
Prasad Malisetty358dda32018-02-20 06:14:26 +0530474 if (rc < 0) {
Rama Krishna Phani A66e48b42018-03-13 18:29:08 +0530475 pr_err("adc-tm disable failed\n");
Prasad Malisetty358dda32018-02-20 06:14:26 +0530476 return rc;
477 }
478 }
479
Prasad Malisetty358dda32018-02-20 06:14:26 +0530480 return rc;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800481}
482
483static int qpnp_adc_tm_is_valid(struct qpnp_adc_tm_chip *chip)
484{
485 struct qpnp_adc_tm_chip *adc_tm_chip = NULL;
486
487 list_for_each_entry(adc_tm_chip, &qpnp_adc_tm_device_list, list)
488 if (chip == adc_tm_chip)
489 return 0;
490
491 return -EINVAL;
492}
493
494static int32_t qpnp_adc_tm_rc_check_channel_en(struct qpnp_adc_tm_chip *chip)
495{
496 u8 adc_tm_ctl = 0, status_low = 0, status_high = 0;
497 int rc = 0, i = 0;
498 bool ldo_en = false;
499
500 for (i = 0; i < chip->max_channels_available; i++) {
501 rc = qpnp_adc_tm_read_reg(chip, QPNP_BTM_Mn_CTL(i),
502 &adc_tm_ctl, 1);
503 if (rc) {
504 pr_err("adc-tm-tm read ctl failed with %d\n", rc);
505 return rc;
506 }
507
508 adc_tm_ctl &= QPNP_BTM_Mn_MEAS_EN;
509 status_low = adc_tm_ctl & QPNP_BTM_Mn_LOW_THR_INT_EN;
510 status_high = adc_tm_ctl & QPNP_BTM_Mn_HIGH_THR_INT_EN;
511
512 /* Enable only if there are pending measurement requests */
513 if ((adc_tm_ctl && status_high) ||
514 (adc_tm_ctl && status_low)) {
515 qpnp_adc_tm_enable(chip);
516 ldo_en = true;
517
518 /* Request conversion */
519 rc = qpnp_adc_tm_write_reg(chip, QPNP_CONV_REQ,
520 QPNP_CONV_REQ_SET, 1);
521 if (rc < 0) {
522 pr_err("adc-tm request conversion failed\n");
523 return rc;
524 }
525 }
526 break;
527 }
528
529 if (!ldo_en) {
530 /* disable the vote if applicable */
531 if (chip->adc_vote_enable && chip->adc->hkadc_ldo &&
532 chip->adc->hkadc_ldo_ok) {
533 qpnp_adc_disable_voltage(chip->adc);
534 chip->adc_vote_enable = false;
535 }
536 }
537
538 return rc;
539}
540
541static int32_t qpnp_adc_tm_enable_if_channel_meas(
542 struct qpnp_adc_tm_chip *chip)
543{
Prasad Malisetty358dda32018-02-20 06:14:26 +0530544 u8 adc_tm_meas_en = 0, status_low = 0, status_high = 0;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800545 int rc = 0;
546
Prasad Malisetty358dda32018-02-20 06:14:26 +0530547 if (chip->adc_tm_hc) {
548 rc = qpnp_adc_tm_rc_check_channel_en(chip);
549 if (rc) {
550 pr_err("adc_tm channel check failed\n");
551 return rc;
552 }
553 } else {
554 /* Check if a measurement request is still required */
555 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_MULTI_MEAS_EN,
556 &adc_tm_meas_en, 1);
557 if (rc) {
558 pr_err("read status high failed with %d\n", rc);
559 return rc;
560 }
561 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_LOW_THR_INT_EN,
562 &status_low, 1);
563 if (rc) {
564 pr_err("read status low failed with %d\n", rc);
565 return rc;
566 }
567
568 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_HIGH_THR_INT_EN,
569 &status_high, 1);
570 if (rc) {
571 pr_err("read status high failed with %d\n", rc);
572 return rc;
573 }
574
575 /* Enable only if there are pending measurement requests */
576 if ((adc_tm_meas_en && status_high) ||
577 (adc_tm_meas_en && status_low)) {
578 qpnp_adc_tm_enable(chip);
579 /* Request conversion */
580 rc = qpnp_adc_tm_write_reg(chip, QPNP_CONV_REQ,
581 QPNP_CONV_REQ_SET, 1);
582 if (rc < 0) {
583 pr_err("adc-tm request conversion failed\n");
584 return rc;
585 }
586 } else {
587 /* disable the vote if applicable */
588 if (chip->adc_vote_enable && chip->adc->hkadc_ldo &&
589 chip->adc->hkadc_ldo_ok) {
590 qpnp_adc_disable_voltage(chip->adc);
591 chip->adc_vote_enable = false;
592 }
593 }
594 }
595 return rc;
596}
597
598static int32_t qpnp_adc_tm_mode_select(struct qpnp_adc_tm_chip *chip,
599 u8 mode_ctl)
600{
601 int rc;
602
603 mode_ctl |= (QPNP_ADC_TRIM_EN | QPNP_AMUX_TRIM_EN);
604
605 /* VADC_BTM current sets mode to recurring measurements */
606 rc = qpnp_adc_tm_write_reg(chip, QPNP_MODE_CTL, mode_ctl, 1);
607 if (rc < 0)
608 pr_err("adc-tm write mode selection err\n");
609
610 return rc;
611}
612
613static int32_t qpnp_adc_tm_req_sts_check(struct qpnp_adc_tm_chip *chip)
614{
615 u8 status1 = 0, mode_ctl = 0;
616 int rc, count = 0;
617
618 /* Re-enable the peripheral */
619 rc = qpnp_adc_tm_enable(chip);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800620 if (rc) {
Prasad Malisetty358dda32018-02-20 06:14:26 +0530621 pr_err("adc-tm re-enable peripheral failed\n");
622 return rc;
623 }
624
625 /* The VADC_TM bank needs to be disabled for new conversion request */
626 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_STATUS1, &status1, 1);
627 if (rc) {
628 pr_err("adc-tm read status1 failed\n");
629 return rc;
630 }
631
632 /* Disable the bank if a conversion is occurring */
633 while (status1 & QPNP_STATUS1_REQ_STS) {
634 if (count > QPNP_RETRY) {
635 pr_err("retry error=%d with 0x%x\n", count, status1);
636 break;
637 }
638 /*
639 * Wait time is based on the optimum sampling rate
640 * and adding enough time buffer to account for ADC conversions
641 * occurring on different peripheral banks
642 */
643 usleep_range(QPNP_MIN_TIME, QPNP_MAX_TIME);
644 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_STATUS1,
645 &status1, 1);
646 if (rc < 0) {
647 pr_err("adc-tm disable failed\n");
648 return rc;
649 }
650 count++;
651 }
652
653 if (!chip->adc_tm_hc) {
654 /* Change the mode back to recurring measurement mode */
655 mode_ctl = ADC_OP_MEASUREMENT_INTERVAL << QPNP_OP_MODE_SHIFT;
656 rc = qpnp_adc_tm_mode_select(chip, mode_ctl);
657 if (rc < 0) {
658 pr_err("adc-tm mode change to recurring failed\n");
659 return rc;
660 }
661 }
662
663 /* Disable the peripheral */
664 rc = qpnp_adc_tm_disable(chip);
665 if (rc < 0) {
666 pr_err("adc-tm peripheral disable failed\n");
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800667 return rc;
668 }
669
670 return rc;
671}
672
673static int32_t qpnp_adc_tm_get_btm_idx(struct qpnp_adc_tm_chip *chip,
674 uint32_t btm_chan, uint32_t *btm_chan_idx)
675{
676 int rc = 0, i;
677 bool chan_found = false;
678
Prasad Malisetty358dda32018-02-20 06:14:26 +0530679 if (!chip->adc_tm_hc) {
680 for (i = 0; i < QPNP_ADC_TM_CHAN_NONE; i++) {
681 if (adc_tm_data[i].btm_amux_chan == btm_chan) {
682 *btm_chan_idx = i;
683 chan_found = true;
684 }
685 }
686 } else {
687 for (i = 0; i < chip->max_channels_available; i++) {
688 if (chip->sensor[i].btm_channel_num == btm_chan) {
689 *btm_chan_idx = i;
690 chan_found = true;
691 break;
692 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800693 }
694 }
695
696 if (!chan_found)
697 return -EINVAL;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800698 return rc;
699}
700
701static int32_t qpnp_adc_tm_check_revision(struct qpnp_adc_tm_chip *chip,
702 uint32_t btm_chan_num)
703{
704 u8 rev, perph_subtype;
705 int rc = 0;
706
707 rc = qpnp_adc_tm_read_reg(chip, QPNP_REVISION3, &rev, 1);
708 if (rc) {
709 pr_err("adc-tm revision read failed\n");
710 return rc;
711 }
712
713 rc = qpnp_adc_tm_read_reg(chip, QPNP_PERPH_SUBTYPE, &perph_subtype, 1);
714 if (rc) {
715 pr_err("adc-tm perph_subtype read failed\n");
716 return rc;
717 }
718
719 if (perph_subtype == QPNP_PERPH_TYPE2) {
720 if ((rev < QPNP_REVISION_EIGHT_CHANNEL_SUPPORT) &&
721 (btm_chan_num > QPNP_ADC_TM_M4_ADC_CH_SEL_CTL)) {
722 pr_debug("Version does not support more than 5 channels\n");
723 return -EINVAL;
724 }
725 }
726
727 if (perph_subtype == QPNP_PERPH_SUBTYPE_TWO_CHANNEL_SUPPORT) {
728 if (btm_chan_num > QPNP_ADC_TM_M1_ADC_CH_SEL_CTL) {
729 pr_debug("Version does not support more than 2 channels\n");
730 return -EINVAL;
731 }
732 }
733
734 return rc;
735}
736
737static int32_t qpnp_adc_tm_timer_interval_select(
738 struct qpnp_adc_tm_chip *chip, uint32_t btm_chan,
739 struct qpnp_vadc_chan_properties *chan_prop)
740{
741 int rc, chan_idx = 0, i = 0;
742 bool chan_found = false;
743 u8 meas_interval_timer2 = 0, timer_interval_store = 0;
744 uint32_t btm_chan_idx = 0;
745
746 while (i < chip->max_channels_available) {
747 if (chip->sensor[i].btm_channel_num == btm_chan) {
748 chan_idx = i;
749 chan_found = true;
750 i++;
751 } else
752 i++;
753 }
754
755 if (!chan_found) {
756 pr_err("Channel not found\n");
757 return -EINVAL;
758 }
759
760 switch (chip->sensor[chan_idx].timer_select) {
761 case ADC_MEAS_TIMER_SELECT1:
Prasad Malisetty358dda32018-02-20 06:14:26 +0530762 if (!chip->adc_tm_hc)
763 rc = qpnp_adc_tm_write_reg(chip,
764 QPNP_ADC_TM_MEAS_INTERVAL_CTL,
765 chip->sensor[chan_idx].meas_interval, 1);
766 else
767 rc = qpnp_adc_tm_write_reg(chip,
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800768 QPNP_BTM_MEAS_INTERVAL_CTL,
769 chip->sensor[chan_idx].meas_interval, 1);
770 if (rc < 0) {
771 pr_err("timer1 configure failed\n");
772 return rc;
773 }
Prasad Malisetty358dda32018-02-20 06:14:26 +0530774 break;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800775 case ADC_MEAS_TIMER_SELECT2:
776 /* Thermal channels uses timer2, default to 1 second */
Prasad Malisetty358dda32018-02-20 06:14:26 +0530777 if (!chip->adc_tm_hc)
778 rc = qpnp_adc_tm_read_reg(chip,
779 QPNP_ADC_TM_MEAS_INTERVAL_CTL2,
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800780 &meas_interval_timer2, 1);
Prasad Malisetty358dda32018-02-20 06:14:26 +0530781 else
782 rc = qpnp_adc_tm_read_reg(chip,
783 QPNP_BTM_MEAS_INTERVAL_CTL2,
784 &meas_interval_timer2, 1);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800785 if (rc < 0) {
786 pr_err("timer2 configure read failed\n");
787 return rc;
788 }
789 timer_interval_store = chip->sensor[chan_idx].meas_interval;
790 timer_interval_store <<= QPNP_ADC_TM_MEAS_INTERVAL_CTL2_SHIFT;
791 timer_interval_store &= QPNP_ADC_TM_MEAS_INTERVAL_CTL2_MASK;
792 meas_interval_timer2 |= timer_interval_store;
Prasad Malisetty358dda32018-02-20 06:14:26 +0530793 if (!chip->adc_tm_hc)
794 rc = qpnp_adc_tm_write_reg(chip,
795 QPNP_ADC_TM_MEAS_INTERVAL_CTL2,
796 meas_interval_timer2, 1);
797 else
798 rc = qpnp_adc_tm_write_reg(chip,
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800799 QPNP_BTM_MEAS_INTERVAL_CTL2,
800 meas_interval_timer2, 1);
801 if (rc < 0) {
802 pr_err("timer2 configure failed\n");
803 return rc;
804 }
805 break;
806 case ADC_MEAS_TIMER_SELECT3:
Prasad Malisetty358dda32018-02-20 06:14:26 +0530807 if (!chip->adc_tm_hc)
808 rc = qpnp_adc_tm_read_reg(chip,
809 QPNP_ADC_TM_MEAS_INTERVAL_CTL2,
810 &meas_interval_timer2, 1);
811 else
812 rc = qpnp_adc_tm_read_reg(chip,
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800813 QPNP_BTM_MEAS_INTERVAL_CTL2,
814 &meas_interval_timer2, 1);
815 if (rc < 0) {
816 pr_err("timer3 read failed\n");
817 return rc;
818 }
819 timer_interval_store = chip->sensor[chan_idx].meas_interval;
820 timer_interval_store &= QPNP_ADC_TM_MEAS_INTERVAL_CTL3_MASK;
821 meas_interval_timer2 |= timer_interval_store;
Prasad Malisetty358dda32018-02-20 06:14:26 +0530822 if (!chip->adc_tm_hc)
823 rc = qpnp_adc_tm_write_reg(chip,
824 QPNP_ADC_TM_MEAS_INTERVAL_CTL2,
825 meas_interval_timer2, 1);
826 else
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800827 rc = qpnp_adc_tm_write_reg(chip,
828 QPNP_BTM_MEAS_INTERVAL_CTL2,
829 meas_interval_timer2, 1);
830 if (rc < 0) {
831 pr_err("timer3 configure failed\n");
832 return rc;
833 }
834 break;
835 default:
836 pr_err("Invalid timer selection\n");
837 return -EINVAL;
838 }
839
840 /* Select the timer to use for the corresponding channel */
841 rc = qpnp_adc_tm_get_btm_idx(chip, btm_chan, &btm_chan_idx);
842 if (rc < 0) {
843 pr_err("Invalid btm channel idx\n");
844 return rc;
845 }
Prasad Malisetty358dda32018-02-20 06:14:26 +0530846 if (!chip->adc_tm_hc)
847 rc = qpnp_adc_tm_write_reg(chip,
848 adc_tm_data[btm_chan_idx].meas_interval_ctl,
849 chip->sensor[chan_idx].timer_select, 1);
850 else
851 rc = qpnp_adc_tm_write_reg(chip,
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -0700852 QPNP_BTM_Mn_MEAS_INTERVAL_CTL(btm_chan_idx),
853 chip->sensor[chan_idx].timer_select, 1);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800854 if (rc < 0) {
855 pr_err("TM channel timer configure failed\n");
856 return rc;
857 }
858
859 pr_debug("timer select:%d, timer_value_within_select:%d, channel:%x\n",
860 chip->sensor[chan_idx].timer_select,
861 chip->sensor[chan_idx].meas_interval,
862 btm_chan);
863
864 return rc;
865}
866
867static int32_t qpnp_adc_tm_add_to_list(struct qpnp_adc_tm_chip *chip,
868 uint32_t dt_index,
869 struct qpnp_adc_tm_btm_param *param,
870 struct qpnp_vadc_chan_properties *chan_prop)
871{
872 struct qpnp_adc_thr_client_info *client_info = NULL;
873 bool client_info_exists = false;
874
875 list_for_each_entry(client_info,
876 &chip->sensor[dt_index].thr_list, list) {
877 if (client_info->btm_param == param) {
878 client_info->low_thr_requested = chan_prop->low_thr;
879 client_info->high_thr_requested = chan_prop->high_thr;
880 client_info->state_requested = param->state_request;
881 client_info->state_req_copy = param->state_request;
882 client_info->notify_low_thr = false;
883 client_info->notify_high_thr = false;
884 client_info_exists = true;
885 pr_debug("client found\n");
886 }
887 }
888
889 if (!client_info_exists) {
890 client_info = devm_kzalloc(chip->dev,
891 sizeof(struct qpnp_adc_thr_client_info), GFP_KERNEL);
892 if (!client_info)
893 return -ENOMEM;
894
895 pr_debug("new client\n");
896 client_info->btm_param = param;
897 client_info->low_thr_requested = chan_prop->low_thr;
898 client_info->high_thr_requested = chan_prop->high_thr;
899 client_info->state_requested = param->state_request;
900 client_info->state_req_copy = param->state_request;
901
902 list_add_tail(&client_info->list,
903 &chip->sensor[dt_index].thr_list);
904 }
905
906 return 0;
907}
908
909static int32_t qpnp_adc_tm_reg_update(struct qpnp_adc_tm_chip *chip,
910 uint16_t addr, u8 mask, bool state)
911{
912 u8 reg_value = 0;
913 int rc = 0;
914
915 rc = qpnp_adc_tm_read_reg(chip, addr, &reg_value, 1);
916 if (rc < 0) {
917 pr_err("read failed for addr:0x%x\n", addr);
918 return rc;
919 }
920
921 reg_value = reg_value & ~mask;
922 if (state)
923 reg_value |= mask;
924
925 pr_debug("state:%d, reg:0x%x with bits:0x%x and mask:0x%x\n",
926 state, addr, reg_value, ~mask);
927 rc = qpnp_adc_tm_write_reg(chip, addr, reg_value, 1);
928 if (rc < 0) {
929 pr_err("write failed for addr:%x\n", addr);
930 return rc;
931 }
932
933 return rc;
934}
935
Prasad Malisetty358dda32018-02-20 06:14:26 +0530936static int32_t qpnp_adc_tm_read_thr_value(struct qpnp_adc_tm_chip *chip,
937 uint32_t btm_chan)
938{
939 int rc = 0;
940 u8 data_lsb = 0, data_msb = 0;
941 uint32_t btm_chan_idx = 0;
942 int32_t low_thr = 0, high_thr = 0;
943
944 if (!chip->adc_tm_hc) {
945 pr_err("Not applicable for VADC HC peripheral\n");
946 return -EINVAL;
947 }
948
949 rc = qpnp_adc_tm_get_btm_idx(chip, btm_chan, &btm_chan_idx);
950 if (rc < 0) {
951 pr_err("Invalid btm channel idx\n");
952 return rc;
953 }
954
955 rc = qpnp_adc_tm_read_reg(chip,
956 adc_tm_data[btm_chan_idx].low_thr_lsb_addr,
957 &data_lsb, 1);
958 if (rc < 0) {
959 pr_err("low threshold lsb setting failed\n");
960 return rc;
961 }
962
963 rc = qpnp_adc_tm_read_reg(chip,
964 adc_tm_data[btm_chan_idx].low_thr_msb_addr,
965 &data_msb, 1);
966 if (rc < 0) {
967 pr_err("low threshold msb setting failed\n");
968 return rc;
969 }
970
971 low_thr = (data_msb << 8) | data_lsb;
972
973 rc = qpnp_adc_tm_read_reg(chip,
974 adc_tm_data[btm_chan_idx].high_thr_lsb_addr,
975 &data_lsb, 1);
976 if (rc < 0) {
977 pr_err("high threshold lsb setting failed\n");
978 return rc;
979 }
980
981 rc = qpnp_adc_tm_read_reg(chip,
982 adc_tm_data[btm_chan_idx].high_thr_msb_addr,
983 &data_msb, 1);
984 if (rc < 0) {
985 pr_err("high threshold msb setting failed\n");
986 return rc;
987 }
988
989 high_thr = (data_msb << 8) | data_lsb;
990
991 pr_debug("configured thresholds high:0x%x and low:0x%x\n",
992 high_thr, low_thr);
993
994 return rc;
995}
996
997
998
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800999static int32_t qpnp_adc_tm_thr_update(struct qpnp_adc_tm_chip *chip,
1000 uint32_t btm_chan, int32_t high_thr, int32_t low_thr)
1001{
1002 int rc = 0;
1003 uint32_t btm_chan_idx = 0;
1004
1005 rc = qpnp_adc_tm_get_btm_idx(chip, btm_chan, &btm_chan_idx);
1006 if (rc < 0) {
1007 pr_err("Invalid btm channel idx\n");
1008 return rc;
1009 }
1010
Prasad Malisetty358dda32018-02-20 06:14:26 +05301011 if (!chip->adc_tm_hc) {
1012 rc = qpnp_adc_tm_write_reg(chip,
1013 adc_tm_data[btm_chan_idx].low_thr_lsb_addr,
1014 QPNP_ADC_TM_THR_LSB_MASK(low_thr), 1);
1015 if (rc < 0) {
1016 pr_err("low threshold lsb setting failed\n");
1017 return rc;
1018 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001019
Prasad Malisetty358dda32018-02-20 06:14:26 +05301020 rc = qpnp_adc_tm_write_reg(chip,
1021 adc_tm_data[btm_chan_idx].low_thr_msb_addr,
1022 QPNP_ADC_TM_THR_MSB_MASK(low_thr), 1);
1023 if (rc < 0) {
1024 pr_err("low threshold msb setting failed\n");
1025 return rc;
1026 }
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001027
Prasad Malisetty358dda32018-02-20 06:14:26 +05301028 rc = qpnp_adc_tm_write_reg(chip,
1029 adc_tm_data[btm_chan_idx].high_thr_lsb_addr,
1030 QPNP_ADC_TM_THR_LSB_MASK(high_thr), 1);
1031 if (rc < 0) {
1032 pr_err("high threshold lsb setting failed\n");
1033 return rc;
1034 }
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001035
Prasad Malisetty358dda32018-02-20 06:14:26 +05301036 rc = qpnp_adc_tm_write_reg(chip,
1037 adc_tm_data[btm_chan_idx].high_thr_msb_addr,
1038 QPNP_ADC_TM_THR_MSB_MASK(high_thr), 1);
1039 if (rc < 0)
1040 pr_err("high threshold msb setting failed\n");
1041 } else {
1042 rc = qpnp_adc_tm_write_reg(chip,
1043 QPNP_BTM_Mn_LOW_THR0(btm_chan_idx),
1044 QPNP_ADC_TM_THR_LSB_MASK(low_thr), 1);
1045 if (rc < 0) {
1046 pr_err("low threshold lsb setting failed\n");
1047 return rc;
1048 }
1049
1050 rc = qpnp_adc_tm_write_reg(chip,
1051 QPNP_BTM_Mn_LOW_THR1(btm_chan_idx),
1052 QPNP_ADC_TM_THR_MSB_MASK(low_thr), 1);
1053 if (rc < 0) {
1054 pr_err("low threshold msb setting failed\n");
1055 return rc;
1056 }
1057
1058 rc = qpnp_adc_tm_write_reg(chip,
1059 QPNP_BTM_Mn_HIGH_THR0(btm_chan_idx),
1060 QPNP_ADC_TM_THR_LSB_MASK(high_thr), 1);
1061 if (rc < 0) {
1062 pr_err("high threshold lsb setting failed\n");
1063 return rc;
1064 }
1065
1066 rc = qpnp_adc_tm_write_reg(chip,
1067 QPNP_BTM_Mn_HIGH_THR1(btm_chan_idx),
1068 QPNP_ADC_TM_THR_MSB_MASK(high_thr), 1);
1069 if (rc < 0)
1070 pr_err("high threshold msb setting failed\n");
1071
1072 }
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001073
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001074 pr_debug("client requested high:%d and low:%d\n",
Prasad Malisetty358dda32018-02-20 06:14:26 +05301075 high_thr, low_thr);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001076
1077 return rc;
1078}
1079
1080static int32_t qpnp_adc_tm_manage_thresholds(struct qpnp_adc_tm_chip *chip,
1081 uint32_t dt_index, uint32_t btm_chan)
1082{
1083 struct qpnp_adc_thr_client_info *client_info = NULL;
1084 struct list_head *thr_list;
1085 int high_thr = 0, low_thr = 0, rc = 0;
1086
1087
1088 /*
1089 * high_thr/low_thr starting point and reset the high_thr_set and
1090 * low_thr_set back to reset since the thresholds will be
1091 * recomputed.
1092 */
1093 list_for_each(thr_list,
1094 &chip->sensor[dt_index].thr_list) {
1095 client_info = list_entry(thr_list,
1096 struct qpnp_adc_thr_client_info, list);
1097 high_thr = client_info->high_thr_requested;
1098 low_thr = client_info->low_thr_requested;
1099 client_info->high_thr_set = false;
1100 client_info->low_thr_set = false;
1101 }
1102
1103 pr_debug("init threshold is high:%d and low:%d\n", high_thr, low_thr);
1104
1105 /* Find the min of high_thr and max of low_thr */
1106 list_for_each(thr_list,
1107 &chip->sensor[dt_index].thr_list) {
1108 client_info = list_entry(thr_list,
1109 struct qpnp_adc_thr_client_info, list);
1110 if ((client_info->state_req_copy == ADC_TM_HIGH_THR_ENABLE) ||
1111 (client_info->state_req_copy ==
1112 ADC_TM_HIGH_LOW_THR_ENABLE))
1113 if (client_info->high_thr_requested < high_thr)
1114 high_thr = client_info->high_thr_requested;
1115
1116 if ((client_info->state_req_copy == ADC_TM_LOW_THR_ENABLE) ||
1117 (client_info->state_req_copy ==
1118 ADC_TM_HIGH_LOW_THR_ENABLE))
1119 if (client_info->low_thr_requested > low_thr)
1120 low_thr = client_info->low_thr_requested;
1121
1122 pr_debug("threshold compared is high:%d and low:%d\n",
1123 client_info->high_thr_requested,
1124 client_info->low_thr_requested);
1125 pr_debug("current threshold is high:%d and low:%d\n",
1126 high_thr, low_thr);
1127 }
1128
1129 /* Check which of the high_thr and low_thr got set */
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 if ((client_info->state_req_copy == ADC_TM_HIGH_THR_ENABLE) ||
1135 (client_info->state_req_copy ==
1136 ADC_TM_HIGH_LOW_THR_ENABLE))
1137 if (high_thr == client_info->high_thr_requested)
1138 client_info->high_thr_set = true;
1139
1140 if ((client_info->state_req_copy == ADC_TM_LOW_THR_ENABLE) ||
1141 (client_info->state_req_copy ==
1142 ADC_TM_HIGH_LOW_THR_ENABLE))
1143 if (low_thr == client_info->low_thr_requested)
1144 client_info->low_thr_set = true;
1145 }
1146
1147 rc = qpnp_adc_tm_thr_update(chip, btm_chan, high_thr, low_thr);
1148 if (rc < 0)
1149 pr_err("setting chan:%d threshold failed\n", btm_chan);
1150
1151 pr_debug("threshold written is high:%d and low:%d\n",
1152 high_thr, low_thr);
1153
1154 return 0;
1155}
1156
1157static int32_t qpnp_adc_tm_channel_configure(struct qpnp_adc_tm_chip *chip,
1158 uint32_t btm_chan,
1159 struct qpnp_vadc_chan_properties *chan_prop,
1160 uint32_t amux_channel)
1161{
1162 int rc = 0, i = 0, chan_idx = 0;
1163 bool chan_found = false, high_thr_set = false, low_thr_set = false;
1164 u8 sensor_mask = 0;
1165 struct qpnp_adc_thr_client_info *client_info = NULL;
1166 uint32_t btm_chan_idx = 0;
1167
1168 while (i < chip->max_channels_available) {
1169 if (chip->sensor[i].btm_channel_num == btm_chan) {
1170 chan_idx = i;
1171 chan_found = true;
1172 i++;
1173 } else
1174 i++;
1175 }
1176
1177 if (!chan_found) {
1178 pr_err("Channel not found\n");
1179 return -EINVAL;
1180 }
1181
1182 rc = qpnp_adc_tm_get_btm_idx(chip, btm_chan, &btm_chan_idx);
1183 if (rc < 0) {
1184 pr_err("Invalid btm channel idx\n");
1185 return rc;
1186 }
1187
1188 sensor_mask = 1 << chan_idx;
1189 if (!chip->sensor[chan_idx].thermal_node) {
1190 /* Update low and high notification thresholds */
1191 rc = qpnp_adc_tm_manage_thresholds(chip, chan_idx,
1192 btm_chan);
1193 if (rc < 0) {
1194 pr_err("setting chan:%d threshold failed\n", btm_chan);
1195 return rc;
1196 }
1197
1198 list_for_each_entry(client_info,
1199 &chip->sensor[chan_idx].thr_list, list) {
1200 if (client_info->high_thr_set == true)
1201 high_thr_set = true;
1202 if (client_info->low_thr_set == true)
1203 low_thr_set = true;
1204 }
1205
1206 if (low_thr_set) {
1207 pr_debug("low sensor mask:%x with state:%d\n",
1208 sensor_mask, chan_prop->state_request);
1209 /* Enable low threshold's interrupt */
Prasad Malisetty358dda32018-02-20 06:14:26 +05301210 if (!chip->adc_tm_hc)
1211 rc = qpnp_adc_tm_reg_update(chip,
1212 QPNP_ADC_TM_LOW_THR_INT_EN,
1213 sensor_mask, true);
1214 else
1215 rc = qpnp_adc_tm_reg_update(chip,
1216 QPNP_BTM_Mn_EN(btm_chan_idx),
1217 QPNP_BTM_Mn_LOW_THR_INT_EN, true);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001218 if (rc < 0) {
1219 pr_err("low thr enable err:%d\n", btm_chan);
1220 return rc;
1221 }
1222 }
1223
1224 if (high_thr_set) {
1225 /* Enable high threshold's interrupt */
1226 pr_debug("high sensor mask:%x\n", sensor_mask);
Prasad Malisetty358dda32018-02-20 06:14:26 +05301227 if (!chip->adc_tm_hc)
1228 rc = qpnp_adc_tm_reg_update(chip,
1229 QPNP_ADC_TM_HIGH_THR_INT_EN,
1230 sensor_mask, true);
1231 else
1232 rc = qpnp_adc_tm_reg_update(chip,
1233 QPNP_BTM_Mn_EN(btm_chan_idx),
1234 QPNP_BTM_Mn_HIGH_THR_INT_EN, true);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001235 if (rc < 0) {
1236 pr_err("high thr enable err:%d\n", btm_chan);
1237 return rc;
1238 }
1239 }
1240 }
1241
1242 /* Enable corresponding BTM channel measurement */
Prasad Malisetty358dda32018-02-20 06:14:26 +05301243 if (!chip->adc_tm_hc)
1244 rc = qpnp_adc_tm_reg_update(chip,
1245 QPNP_ADC_TM_MULTI_MEAS_EN, sensor_mask, true);
1246 else
1247 rc = qpnp_adc_tm_reg_update(chip, QPNP_BTM_Mn_EN(btm_chan_idx),
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001248 QPNP_BTM_Mn_MEAS_EN, true);
1249 if (rc < 0) {
1250 pr_err("multi measurement en failed\n");
1251 return rc;
1252 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001253 return rc;
1254}
1255
1256static int32_t qpnp_adc_tm_hc_configure(struct qpnp_adc_tm_chip *chip,
1257 struct qpnp_adc_amux_properties *chan_prop)
1258{
1259 u8 decimation = 0, fast_avg_ctl = 0;
1260 u8 buf[8];
1261 int rc = 0;
1262 uint32_t btm_chan = 0, cal_type = 0, btm_chan_idx = 0;
1263
1264 /* Disable bank */
1265 rc = qpnp_adc_tm_disable(chip);
1266 if (rc)
1267 return rc;
1268
1269 /* Decimation setup */
1270 decimation = chan_prop->decimation;
1271 rc = qpnp_adc_tm_write_reg(chip, QPNP_BTM_HC_ADC_DIG_PARAM,
1272 decimation, 1);
1273 if (rc < 0) {
1274 pr_err("adc-tm digital parameter setup err\n");
1275 return rc;
1276 }
1277
1278 /* Fast averaging setup/enable */
1279 rc = qpnp_adc_tm_read_reg(chip, QPNP_BTM_HC_FAST_AVG_CTL,
1280 &fast_avg_ctl, 1);
1281 if (rc < 0) {
1282 pr_err("adc-tm fast-avg enable read err\n");
1283 return rc;
1284 }
1285 fast_avg_ctl |= chan_prop->fast_avg_setup;
1286 rc = qpnp_adc_tm_write_reg(chip, QPNP_BTM_HC_FAST_AVG_CTL,
1287 fast_avg_ctl, 1);
1288 if (rc < 0) {
1289 pr_err("adc-tm fast-avg enable write err\n");
1290 return rc;
1291 }
1292
1293 /* Read block registers for respective BTM channel */
1294 btm_chan = chan_prop->chan_prop->tm_channel_select;
1295 rc = qpnp_adc_tm_get_btm_idx(chip, btm_chan, &btm_chan_idx);
1296 if (rc < 0) {
1297 pr_err("Invalid btm channel idx\n");
1298 return rc;
1299 }
1300
1301 rc = qpnp_adc_tm_read_reg(chip,
1302 QPNP_BTM_Mn_ADC_CH_SEL_CTL(btm_chan_idx), buf, 8);
1303 if (rc < 0) {
1304 pr_err("qpnp adc configure block read failed\n");
1305 return rc;
1306 }
1307
1308 /* Update ADC channel sel */
1309 rc = qpnp_adc_tm_write_reg(chip,
1310 QPNP_BTM_Mn_ADC_CH_SEL_CTL(btm_chan_idx),
1311 chan_prop->amux_channel, 1);
1312 if (rc < 0) {
1313 pr_err("adc-tm channel amux select failed\n");
1314 return rc;
1315 }
1316
1317 /* Manage thresholds */
1318 rc = qpnp_adc_tm_channel_configure(chip, btm_chan,
1319 chan_prop->chan_prop, chan_prop->amux_channel);
1320 if (rc < 0) {
1321 pr_err("adc-tm channel threshold configure failed\n");
1322 return rc;
1323 }
1324
1325 /* Measurement interval setup */
1326 rc = qpnp_adc_tm_timer_interval_select(chip, btm_chan,
1327 chan_prop->chan_prop);
1328 if (rc < 0) {
1329 pr_err("adc-tm timer select failed\n");
1330 return rc;
1331 }
1332
1333 /* Set calibration select, hw_settle delay */
1334 cal_type |= (chan_prop->calib_type << QPNP_BTM_CTL_CAL_SEL_MASK_SHIFT);
1335 buf[6] &= ~QPNP_BTM_CTL_HW_SETTLE_DELAY_MASK;
1336 buf[6] |= chan_prop->hw_settle_time;
1337 buf[6] &= ~QPNP_BTM_CTL_CAL_SEL;
1338 buf[6] |= cal_type;
1339 rc = qpnp_adc_tm_write_reg(chip, QPNP_BTM_Mn_CTL(btm_chan_idx),
1340 buf[6], 1);
1341 if (rc < 0) {
1342 pr_err("adc-tm hw-settle, calib sel failed\n");
1343 return rc;
1344 }
1345
1346 /* Enable bank */
1347 rc = qpnp_adc_tm_enable(chip);
1348 if (rc)
1349 return rc;
1350
1351 /* Request conversion */
1352 rc = qpnp_adc_tm_write_reg(chip, QPNP_CONV_REQ, QPNP_CONV_REQ_SET, 1);
1353 if (rc < 0) {
1354 pr_err("adc-tm request conversion failed\n");
1355 return rc;
1356 }
1357
1358 return 0;
1359}
1360
Prasad Malisetty358dda32018-02-20 06:14:26 +05301361static int32_t qpnp_adc_tm_configure(struct qpnp_adc_tm_chip *chip,
1362 struct qpnp_adc_amux_properties *chan_prop)
1363{
1364 u8 decimation = 0, op_cntrl = 0, mode_ctl = 0;
1365 int rc = 0;
1366 uint32_t btm_chan = 0;
1367
1368 /* Set measurement in single measurement mode */
1369 mode_ctl = ADC_OP_NORMAL_MODE << QPNP_OP_MODE_SHIFT;
1370 rc = qpnp_adc_tm_mode_select(chip, mode_ctl);
1371 if (rc < 0) {
1372 pr_err("adc-tm single mode select failed\n");
1373 return rc;
1374 }
1375
1376 /* Disable bank */
1377 rc = qpnp_adc_tm_disable(chip);
1378 if (rc)
1379 return rc;
1380
1381 /* Check if a conversion is in progress */
1382 rc = qpnp_adc_tm_req_sts_check(chip);
1383 if (rc < 0) {
1384 pr_err("adc-tm req_sts check failed\n");
1385 return rc;
1386 }
1387
1388 /* Configure AMUX channel select for the corresponding BTM channel*/
1389 btm_chan = chan_prop->chan_prop->tm_channel_select;
1390 rc = qpnp_adc_tm_write_reg(chip, btm_chan, chan_prop->amux_channel, 1);
1391 if (rc < 0) {
1392 pr_err("adc-tm channel selection err\n");
1393 return rc;
1394 }
1395
1396 /* Digital parameter setup */
1397 decimation |= chan_prop->decimation <<
1398 QPNP_ADC_DIG_DEC_RATIO_SEL_SHIFT;
1399 rc = qpnp_adc_tm_write_reg(chip, QPNP_ADC_DIG_PARAM, decimation, 1);
1400 if (rc < 0) {
1401 pr_err("adc-tm digital parameter setup err\n");
1402 return rc;
1403 }
1404
1405 /* Hardware setting time */
1406 rc = qpnp_adc_tm_write_reg(chip, QPNP_HW_SETTLE_DELAY,
1407 chan_prop->hw_settle_time, 1);
1408 if (rc < 0) {
1409 pr_err("adc-tm hw settling time setup err\n");
1410 return rc;
1411 }
1412
1413 /* Fast averaging setup/enable */
1414 rc = qpnp_adc_tm_fast_avg_en(chip, &chan_prop->fast_avg_setup);
1415 if (rc < 0) {
1416 pr_err("adc-tm fast-avg enable err\n");
1417 return rc;
1418 }
1419
1420 rc = qpnp_adc_tm_write_reg(chip, QPNP_FAST_AVG_CTL,
1421 chan_prop->fast_avg_setup, 1);
1422 if (rc < 0) {
1423 pr_err("adc-tm fast-avg setup err\n");
1424 return rc;
1425 }
1426
1427 /* Measurement interval setup */
1428 rc = qpnp_adc_tm_timer_interval_select(chip, btm_chan,
1429 chan_prop->chan_prop);
1430 if (rc < 0) {
1431 pr_err("adc-tm timer select failed\n");
1432 return rc;
1433 }
1434
1435 /* Channel configuration setup */
1436 rc = qpnp_adc_tm_channel_configure(chip, btm_chan,
1437 chan_prop->chan_prop, chan_prop->amux_channel);
1438 if (rc < 0) {
1439 pr_err("adc-tm channel configure failed\n");
1440 return rc;
1441 }
1442
1443 /* Recurring interval measurement enable */
1444 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_MEAS_INTERVAL_OP_CTL,
1445 &op_cntrl, 1);
1446 op_cntrl |= QPNP_ADC_MEAS_INTERVAL_OP;
1447 rc = qpnp_adc_tm_reg_update(chip, QPNP_ADC_MEAS_INTERVAL_OP_CTL,
1448 op_cntrl, true);
1449 if (rc < 0) {
1450 pr_err("adc-tm meas interval op configure failed\n");
1451 return rc;
1452 }
1453
1454 /* Enable bank */
1455 rc = qpnp_adc_tm_enable(chip);
1456 if (rc)
1457 return rc;
1458
1459 /* Request conversion */
1460 rc = qpnp_adc_tm_write_reg(chip, QPNP_CONV_REQ, QPNP_CONV_REQ_SET, 1);
1461 if (rc < 0) {
1462 pr_err("adc-tm request conversion failed\n");
1463 return rc;
1464 }
1465
1466 return 0;
1467}
1468
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001469static int qpnp_adc_tm_set_mode(struct qpnp_adc_tm_sensor *adc_tm,
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001470 enum thermal_device_mode mode)
1471{
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001472 struct qpnp_adc_tm_chip *chip = adc_tm->chip;
1473 int rc = 0, channel;
Prasad Malisetty358dda32018-02-20 06:14:26 +05301474 u8 sensor_mask = 0, mode_ctl = 0;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001475 uint32_t btm_chan_idx = 0, btm_chan = 0;
1476
1477 if (qpnp_adc_tm_is_valid(chip)) {
1478 pr_err("invalid device\n");
1479 return -ENODEV;
1480 }
1481
1482 if (qpnp_adc_tm_check_revision(chip, adc_tm->btm_channel_num))
1483 return -EINVAL;
1484
1485 mutex_lock(&chip->adc->adc_lock);
1486
1487 btm_chan = adc_tm->btm_channel_num;
1488 rc = qpnp_adc_tm_get_btm_idx(chip, btm_chan, &btm_chan_idx);
1489 if (rc < 0) {
1490 pr_err("Invalid btm channel idx\n");
1491 goto fail;
1492 }
1493
1494 if (mode == THERMAL_DEVICE_ENABLED) {
1495 chip->adc->amux_prop->amux_channel =
1496 adc_tm->vadc_channel_num;
1497 channel = adc_tm->sensor_num;
1498 chip->adc->amux_prop->decimation =
1499 chip->adc->adc_channels[channel].adc_decimation;
1500 chip->adc->amux_prop->hw_settle_time =
1501 chip->adc->adc_channels[channel].hw_settle_time;
1502 chip->adc->amux_prop->fast_avg_setup =
1503 chip->adc->adc_channels[channel].fast_avg_setup;
1504 chip->adc->amux_prop->mode_sel =
1505 ADC_OP_MEASUREMENT_INTERVAL << QPNP_OP_MODE_SHIFT;
1506 chip->adc->amux_prop->chan_prop->low_thr = adc_tm->low_thr;
1507 chip->adc->amux_prop->chan_prop->high_thr = adc_tm->high_thr;
1508 chip->adc->amux_prop->chan_prop->tm_channel_select =
1509 adc_tm->btm_channel_num;
1510 chip->adc->amux_prop->calib_type =
1511 chip->adc->adc_channels[channel].calib_type;
1512
Prasad Malisetty358dda32018-02-20 06:14:26 +05301513 if (!chip->adc_tm_hc) {
1514 rc = qpnp_adc_tm_configure(chip, chip->adc->amux_prop);
1515 if (rc) {
1516 pr_err("adc-tm configure failed with %d\n", rc);
1517 goto fail;
1518 }
1519 } else {
1520 rc = qpnp_adc_tm_hc_configure(chip,
1521 chip->adc->amux_prop);
1522 if (rc) {
1523 pr_err("hc configure failed with %d\n", rc);
1524 goto fail;
1525 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001526 }
1527 } else if (mode == THERMAL_DEVICE_DISABLED) {
1528 sensor_mask = 1 << adc_tm->sensor_num;
Prasad Malisetty358dda32018-02-20 06:14:26 +05301529 if (!chip->adc_tm_hc) {
1530 mode_ctl = ADC_OP_NORMAL_MODE << QPNP_OP_MODE_SHIFT;
1531 rc = qpnp_adc_tm_mode_select(chip, mode_ctl);
1532 if (rc < 0) {
1533 pr_err("adc-tm single mode select failed\n");
1534 goto fail;
1535 }
1536 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001537
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001538 /* Disable bank */
1539 rc = qpnp_adc_tm_disable(chip);
1540 if (rc < 0) {
1541 pr_err("adc-tm disable failed\n");
1542 goto fail;
1543 }
1544
Prasad Malisetty358dda32018-02-20 06:14:26 +05301545 if (!chip->adc_tm_hc) {
1546 /* Check if a conversion is in progress */
1547 rc = qpnp_adc_tm_req_sts_check(chip);
1548 if (rc < 0) {
1549 pr_err("adc-tm req_sts check failed\n");
1550 goto fail;
1551 }
1552 rc = qpnp_adc_tm_reg_update(chip,
1553 QPNP_ADC_TM_MULTI_MEAS_EN,
1554 sensor_mask, false);
1555 if (rc < 0) {
1556 pr_err("multi measurement update failed\n");
1557 goto fail;
1558 }
1559 } else {
1560 rc = qpnp_adc_tm_reg_update(chip,
1561 QPNP_BTM_Mn_EN(btm_chan_idx),
1562 QPNP_BTM_Mn_MEAS_EN, false);
1563 if (rc < 0) {
1564 pr_err("multi measurement disable failed\n");
1565 goto fail;
1566 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001567 }
1568
1569 rc = qpnp_adc_tm_enable_if_channel_meas(chip);
1570 if (rc < 0) {
1571 pr_err("re-enabling measurement failed\n");
1572 goto fail;
1573 }
1574 }
1575
1576 adc_tm->mode = mode;
1577
1578fail:
1579 mutex_unlock(&chip->adc->adc_lock);
1580
1581 return 0;
1582}
1583
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001584static int qpnp_adc_tm_activate_trip_type(struct qpnp_adc_tm_sensor *adc_tm,
1585 int trip, enum thermal_trip_activation_mode mode)
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001586{
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001587 struct qpnp_adc_tm_chip *chip = adc_tm->chip;
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001588 int rc = 0, sensor_mask = 0;
Prasad Malisetty358dda32018-02-20 06:14:26 +05301589 u8 thr_int_en = 0;
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001590 bool state = false;
1591 uint32_t btm_chan_idx = 0, btm_chan = 0;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001592
1593 if (qpnp_adc_tm_is_valid(chip))
1594 return -ENODEV;
1595
1596 if (qpnp_adc_tm_check_revision(chip, adc_tm->btm_channel_num))
1597 return -EINVAL;
1598
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001599 if (mode == THERMAL_TRIP_ACTIVATION_ENABLED)
1600 state = true;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001601
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001602 sensor_mask = 1 << adc_tm->sensor_num;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001603
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001604 pr_debug("Sensor number:%x with state:%d\n",
1605 adc_tm->sensor_num, state);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001606
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001607 btm_chan = adc_tm->btm_channel_num;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001608 rc = qpnp_adc_tm_get_btm_idx(chip, btm_chan, &btm_chan_idx);
1609 if (rc < 0) {
1610 pr_err("Invalid btm channel idx\n");
1611 return rc;
1612 }
1613
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001614 switch (trip) {
1615 case ADC_TM_TRIP_HIGH_WARM:
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001616 /* low_thr (lower voltage) for higher temp */
Prasad Malisetty358dda32018-02-20 06:14:26 +05301617 thr_int_en = adc_tm_data[btm_chan_idx].low_thr_int_chan_en;
1618 if (!chip->adc_tm_hc)
1619 rc = qpnp_adc_tm_reg_update(chip,
1620 QPNP_ADC_TM_LOW_THR_INT_EN,
1621 sensor_mask, state);
1622 else
1623 rc = qpnp_adc_tm_reg_update(chip,
1624 QPNP_BTM_Mn_EN(btm_chan_idx),
1625 QPNP_BTM_Mn_LOW_THR_INT_EN, state);
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001626 if (rc)
1627 pr_err("channel:%x failed\n", btm_chan);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001628 break;
1629 case ADC_TM_TRIP_LOW_COOL:
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001630 /* high_thr (higher voltage) for cooler temp */
Prasad Malisetty358dda32018-02-20 06:14:26 +05301631 thr_int_en = adc_tm_data[btm_chan_idx].high_thr_int_chan_en;
1632 if (!chip->adc_tm_hc)
1633 rc = qpnp_adc_tm_reg_update(chip,
1634 QPNP_ADC_TM_HIGH_THR_INT_EN,
1635 sensor_mask, state);
1636 else
1637 rc = qpnp_adc_tm_reg_update(chip,
1638 QPNP_BTM_Mn_EN(btm_chan_idx),
1639 QPNP_BTM_Mn_HIGH_THR_INT_EN, state);
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001640 if (rc)
1641 pr_err("channel:%x failed\n", btm_chan);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001642 break;
1643 default:
1644 return -EINVAL;
1645 }
1646
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001647 return rc;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001648}
1649
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001650static int qpnp_adc_tm_set_trip_temp(void *data, int low_temp, int high_temp)
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001651{
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001652 struct qpnp_adc_tm_sensor *adc_tm = data;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001653 struct qpnp_adc_tm_chip *chip = adc_tm->chip;
1654 struct qpnp_adc_tm_config tm_config;
1655 u8 trip_cool_thr0, trip_cool_thr1, trip_warm_thr0, trip_warm_thr1;
1656 uint16_t reg_low_thr_lsb, reg_low_thr_msb;
1657 uint16_t reg_high_thr_lsb, reg_high_thr_msb;
1658 int rc = 0;
1659 uint32_t btm_chan = 0, btm_chan_idx = 0;
1660
1661 if (qpnp_adc_tm_is_valid(chip))
1662 return -ENODEV;
1663
1664 if (qpnp_adc_tm_check_revision(chip, adc_tm->btm_channel_num))
1665 return -EINVAL;
1666
1667 tm_config.channel = adc_tm->vadc_channel_num;
1668 tm_config.high_thr_temp = tm_config.low_thr_temp = 0;
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001669 if (high_temp != INT_MAX)
1670 tm_config.high_thr_temp = high_temp;
1671 if (low_temp != INT_MIN)
1672 tm_config.low_thr_temp = low_temp;
1673
1674 if ((high_temp == INT_MAX) && (low_temp == INT_MIN)) {
1675 pr_err("No trips to set\n");
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001676 return -EINVAL;
1677 }
1678
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001679 pr_debug("requested a high - %d and low - %d\n",
1680 tm_config.high_thr_temp, tm_config.low_thr_temp);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001681 rc = qpnp_adc_tm_scale_therm_voltage_pu2(chip->vadc_dev,
1682 chip->adc->adc_prop, &tm_config);
1683 if (rc < 0) {
1684 pr_err("Failed to lookup the adc-tm thresholds\n");
1685 return rc;
1686 }
1687
1688 trip_warm_thr0 = ((tm_config.low_thr_voltage << 24) >> 24);
1689 trip_warm_thr1 = ((tm_config.low_thr_voltage << 16) >> 24);
1690 trip_cool_thr0 = ((tm_config.high_thr_voltage << 24) >> 24);
1691 trip_cool_thr1 = ((tm_config.high_thr_voltage << 16) >> 24);
1692
1693 pr_debug("low_thr:0x%llx, high_thr:0x%llx\n", tm_config.low_thr_voltage,
1694 tm_config.high_thr_voltage);
1695
1696 btm_chan = adc_tm->btm_channel_num;
1697 rc = qpnp_adc_tm_get_btm_idx(chip, btm_chan, &btm_chan_idx);
1698 if (rc < 0) {
1699 pr_err("Invalid btm channel idx\n");
1700 return rc;
1701 }
1702
Prasad Malisetty358dda32018-02-20 06:14:26 +05301703 if (!chip->adc_tm_hc) {
1704 reg_low_thr_lsb = adc_tm_data[btm_chan_idx].low_thr_lsb_addr;
1705 reg_low_thr_msb = adc_tm_data[btm_chan_idx].low_thr_msb_addr;
1706 reg_high_thr_lsb = adc_tm_data[btm_chan_idx].high_thr_lsb_addr;
1707 reg_high_thr_msb = adc_tm_data[btm_chan_idx].high_thr_msb_addr;
1708 } else {
1709 reg_low_thr_lsb = QPNP_BTM_Mn_LOW_THR0(btm_chan_idx);
1710 reg_low_thr_msb = QPNP_BTM_Mn_LOW_THR1(btm_chan_idx);
1711 reg_high_thr_lsb = QPNP_BTM_Mn_HIGH_THR0(btm_chan_idx);
1712 reg_high_thr_msb = QPNP_BTM_Mn_HIGH_THR1(btm_chan_idx);
1713 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001714
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001715 if (high_temp != INT_MAX) {
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001716 rc = qpnp_adc_tm_write_reg(chip, reg_low_thr_lsb,
1717 trip_cool_thr0, 1);
1718 if (rc) {
1719 pr_err("adc-tm_tm read threshold err\n");
1720 return rc;
1721 }
1722
1723 rc = qpnp_adc_tm_write_reg(chip, reg_low_thr_msb,
1724 trip_cool_thr1, 1);
1725 if (rc) {
1726 pr_err("adc-tm_tm read threshold err\n");
1727 return rc;
1728 }
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001729 adc_tm->low_thr = tm_config.high_thr_voltage;
1730
1731 rc = qpnp_adc_tm_activate_trip_type(adc_tm,
1732 ADC_TM_TRIP_HIGH_WARM,
1733 THERMAL_TRIP_ACTIVATION_ENABLED);
1734 if (rc) {
1735 pr_err("adc-tm warm activation failed\n");
1736 return rc;
1737 }
1738 } else {
1739 rc = qpnp_adc_tm_activate_trip_type(adc_tm,
1740 ADC_TM_TRIP_HIGH_WARM,
1741 THERMAL_TRIP_ACTIVATION_DISABLED);
1742 if (rc) {
1743 pr_err("adc-tm warm deactivation failed\n");
1744 return rc;
1745 }
1746 }
1747
1748 if (low_temp != INT_MIN) {
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001749 rc = qpnp_adc_tm_write_reg(chip, reg_high_thr_lsb,
1750 trip_warm_thr0, 1);
1751 if (rc) {
1752 pr_err("adc-tm_tm read threshold err\n");
1753 return rc;
1754 }
1755
1756 rc = qpnp_adc_tm_write_reg(chip, reg_high_thr_msb,
1757 trip_warm_thr1, 1);
1758 if (rc) {
1759 pr_err("adc-tm_tm read threshold err\n");
1760 return rc;
1761 }
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001762 adc_tm->high_thr = tm_config.low_thr_voltage;
1763
1764 rc = qpnp_adc_tm_activate_trip_type(adc_tm,
1765 ADC_TM_TRIP_LOW_COOL,
1766 THERMAL_TRIP_ACTIVATION_ENABLED);
1767 if (rc) {
1768 pr_err("adc-tm cool activation failed\n");
1769 return rc;
1770 }
1771 } else {
1772 rc = qpnp_adc_tm_activate_trip_type(adc_tm,
1773 ADC_TM_TRIP_LOW_COOL,
1774 THERMAL_TRIP_ACTIVATION_DISABLED);
1775 if (rc) {
1776 pr_err("adc-tm cool deactivation failed\n");
1777 return rc;
1778 }
1779 }
1780
1781 if ((high_temp != INT_MAX) || (low_temp != INT_MIN)) {
1782 rc = qpnp_adc_tm_set_mode(adc_tm, THERMAL_DEVICE_ENABLED);
1783 if (rc) {
1784 pr_err("sensor enabled failed\n");
1785 return rc;
1786 }
1787 } else {
1788 rc = qpnp_adc_tm_set_mode(adc_tm, THERMAL_DEVICE_DISABLED);
1789 if (rc) {
1790 pr_err("sensor disable failed\n");
1791 return rc;
1792 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001793 }
1794
1795 return 0;
1796}
1797
1798static void notify_battery_therm(struct qpnp_adc_tm_sensor *adc_tm)
1799{
1800 struct qpnp_adc_thr_client_info *client_info = NULL;
1801
1802 list_for_each_entry(client_info,
1803 &adc_tm->thr_list, list) {
1804 /* Batt therm's warm temperature translates to low voltage */
1805 if (client_info->notify_low_thr) {
1806 /* HIGH_STATE = WARM_TEMP for battery client */
1807 client_info->btm_param->threshold_notification(
1808 ADC_TM_WARM_STATE, client_info->btm_param->btm_ctx);
1809 client_info->notify_low_thr = false;
1810 }
1811
1812 /* Batt therm's cool temperature translates to high voltage */
1813 if (client_info->notify_high_thr) {
1814 /* LOW_STATE = COOL_TEMP for battery client */
1815 client_info->btm_param->threshold_notification(
1816 ADC_TM_COOL_STATE, client_info->btm_param->btm_ctx);
1817 client_info->notify_high_thr = false;
1818 }
1819 }
1820}
1821
1822static void notify_clients(struct qpnp_adc_tm_sensor *adc_tm)
1823{
1824 struct qpnp_adc_thr_client_info *client_info = NULL;
1825
1826 list_for_each_entry(client_info,
1827 &adc_tm->thr_list, list) {
1828 /* For non batt therm clients */
1829 if (client_info->notify_low_thr) {
1830 if (client_info->btm_param->threshold_notification
1831 != NULL) {
1832 pr_debug("notify kernel with low state\n");
1833 client_info->btm_param->threshold_notification(
1834 ADC_TM_LOW_STATE,
1835 client_info->btm_param->btm_ctx);
1836 client_info->notify_low_thr = false;
1837 }
1838 }
1839
1840 if (client_info->notify_high_thr) {
1841 if (client_info->btm_param->threshold_notification
1842 != NULL) {
1843 pr_debug("notify kernel with high state\n");
1844 client_info->btm_param->threshold_notification(
1845 ADC_TM_HIGH_STATE,
1846 client_info->btm_param->btm_ctx);
1847 client_info->notify_high_thr = false;
1848 }
1849 }
1850 }
1851}
1852
1853static void notify_adc_tm_fn(struct work_struct *work)
1854{
1855 struct qpnp_adc_tm_sensor *adc_tm = container_of(work,
1856 struct qpnp_adc_tm_sensor, work);
1857 struct qpnp_adc_tm_chip *chip = adc_tm->chip;
1858
1859 if (adc_tm->thermal_node) {
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001860 pr_debug("notifying uspace client\n");
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001861 of_thermal_handle_trip(adc_tm->tz_dev);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001862 } else {
1863 if (adc_tm->scale_type == SCALE_RBATT_THERM)
1864 notify_battery_therm(adc_tm);
1865 else
1866 notify_clients(adc_tm);
1867 }
1868
1869 atomic_dec(&chip->wq_cnt);
1870}
1871
Prasad Malisetty358dda32018-02-20 06:14:26 +05301872static int qpnp_adc_tm_recalib_request_check(struct qpnp_adc_tm_chip *chip,
1873 int sensor_num, u8 status_high, u8 *notify_check)
1874{
1875 int rc = 0;
1876 u8 sensor_mask = 0, mode_ctl = 0;
1877 int32_t old_thr = 0, new_thr = 0;
1878 uint32_t channel, btm_chan_num, scale_type;
1879 struct qpnp_vadc_result result;
1880 struct qpnp_adc_thr_client_info *client_info = NULL;
1881 struct list_head *thr_list;
1882 bool status = false;
1883
1884 if (!chip->adc_tm_recalib_check) {
1885 *notify_check = 1;
1886 return rc;
1887 }
1888
1889 list_for_each(thr_list, &chip->sensor[sensor_num].thr_list) {
1890 client_info = list_entry(thr_list,
1891 struct qpnp_adc_thr_client_info, list);
1892 channel = client_info->btm_param->channel;
1893 btm_chan_num = chip->sensor[sensor_num].btm_channel_num;
1894 sensor_mask = 1 << sensor_num;
1895
1896 rc = qpnp_vadc_read(chip->vadc_dev, channel, &result);
1897 if (rc < 0) {
1898 pr_err("failure to read vadc channel=%d\n",
1899 client_info->btm_param->channel);
1900 goto fail;
1901 }
1902 new_thr = result.physical;
1903
1904 if (status_high)
1905 old_thr = client_info->btm_param->high_thr;
1906 else
1907 old_thr = client_info->btm_param->low_thr;
1908
1909 if (new_thr > old_thr)
1910 status = (status_high) ? true : false;
1911 else
1912 status = (status_high) ? false : true;
1913
1914 pr_debug(
1915 "recalib:sen=%d, new_thr=%d, new_thr_adc_code=0x%x, old_thr=%d status=%d valid_status=%d\n",
1916 sensor_num, new_thr, result.adc_code,
1917 old_thr, status_high, status);
1918
1919 rc = qpnp_adc_tm_read_thr_value(chip, btm_chan_num);
1920 if (rc < 0) {
1921 pr_err("adc-tm thresholds read failed\n");
1922 goto fail;
1923 }
1924
1925 if (status) {
1926 *notify_check = 1;
1927 pr_debug("Client can be notify\n");
1928 return rc;
1929 }
1930
1931 pr_debug("Client can not be notify, restart measurement\n");
1932 /* Set measurement in single measurement mode */
1933 mode_ctl = ADC_OP_NORMAL_MODE << QPNP_OP_MODE_SHIFT;
1934 rc = qpnp_adc_tm_mode_select(chip, mode_ctl);
1935 if (rc < 0) {
1936 pr_err("adc-tm single mode select failed\n");
1937 goto fail;
1938 }
1939
1940 /* Disable bank */
1941 rc = qpnp_adc_tm_disable(chip);
1942 if (rc < 0) {
1943 pr_err("adc-tm disable failed\n");
1944 goto fail;
1945 }
1946
1947 /* Check if a conversion is in progress */
1948 rc = qpnp_adc_tm_req_sts_check(chip);
1949 if (rc < 0) {
1950 pr_err("adc-tm req_sts check failed\n");
1951 goto fail;
1952 }
1953
1954 rc = qpnp_adc_tm_reg_update(chip, QPNP_ADC_TM_LOW_THR_INT_EN,
1955 sensor_mask, false);
1956 if (rc < 0) {
1957 pr_err("low threshold int write failed\n");
1958 goto fail;
1959 }
1960
1961 rc = qpnp_adc_tm_reg_update(chip, QPNP_ADC_TM_HIGH_THR_INT_EN,
1962 sensor_mask, false);
1963 if (rc < 0) {
1964 pr_err("high threshold int enable failed\n");
1965 goto fail;
1966 }
1967
1968 rc = qpnp_adc_tm_reg_update(chip, QPNP_ADC_TM_MULTI_MEAS_EN,
1969 sensor_mask, false);
1970 if (rc < 0) {
1971 pr_err("multi measurement en failed\n");
1972 goto fail;
1973 }
1974
1975 /* restart measurement */
1976 scale_type = chip->sensor[sensor_num].scale_type;
1977 chip->adc->amux_prop->amux_channel = channel;
1978 chip->adc->amux_prop->decimation =
1979 chip->adc->adc_channels[sensor_num].adc_decimation;
1980 chip->adc->amux_prop->hw_settle_time =
1981 chip->adc->adc_channels[sensor_num].hw_settle_time;
1982 chip->adc->amux_prop->fast_avg_setup =
1983 chip->adc->adc_channels[sensor_num].fast_avg_setup;
1984 chip->adc->amux_prop->mode_sel =
1985 ADC_OP_MEASUREMENT_INTERVAL << QPNP_OP_MODE_SHIFT;
1986 adc_tm_rscale_fn[scale_type].chan(chip->vadc_dev,
1987 client_info->btm_param,
1988 &chip->adc->amux_prop->chan_prop->low_thr,
1989 &chip->adc->amux_prop->chan_prop->high_thr);
1990 qpnp_adc_tm_add_to_list(chip, sensor_num,
1991 client_info->btm_param,
1992 chip->adc->amux_prop->chan_prop);
1993 chip->adc->amux_prop->chan_prop->tm_channel_select =
1994 chip->sensor[sensor_num].btm_channel_num;
1995 chip->adc->amux_prop->chan_prop->state_request =
1996 client_info->btm_param->state_request;
1997
1998 rc = qpnp_adc_tm_configure(chip, chip->adc->amux_prop);
1999 if (rc) {
2000 pr_err("adc-tm configure failed with %d\n", rc);
2001 goto fail;
2002 }
2003 *notify_check = 0;
2004 pr_debug("BTM channel reconfigured for measuremnt\n");
2005 }
2006fail:
2007 return rc;
2008}
2009
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002010static int qpnp_adc_tm_disable_rearm_high_thresholds(
2011 struct qpnp_adc_tm_chip *chip, int sensor_num)
2012{
2013
2014 struct qpnp_adc_thr_client_info *client_info = NULL;
2015 struct list_head *thr_list;
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002016 uint32_t btm_chan_num = 0, btm_chan_idx = 0;
Prasad Malisetty358dda32018-02-20 06:14:26 +05302017 u8 sensor_mask = 0, notify_check = 0;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002018 int rc = 0;
2019
2020 btm_chan_num = chip->sensor[sensor_num].btm_channel_num;
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002021 rc = qpnp_adc_tm_get_btm_idx(chip, btm_chan_num, &btm_chan_idx);
2022 if (rc < 0) {
2023 pr_err("Invalid btm channel idx\n");
2024 return rc;
2025 }
2026
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002027 pr_debug("high:sen:%d, hs:0x%x, ls:0x%x, meas_en:0x%x\n",
2028 sensor_num, chip->th_info.adc_tm_high_enable,
2029 chip->th_info.adc_tm_low_enable,
2030 chip->th_info.qpnp_adc_tm_meas_en);
2031 if (!chip->sensor[sensor_num].thermal_node) {
2032 /*
2033 * For non thermal registered clients such as usb_id,
2034 * vbatt, pmic_therm
2035 */
2036 sensor_mask = 1 << sensor_num;
2037 pr_debug("non thermal node - mask:%x\n", sensor_mask);
Prasad Malisetty358dda32018-02-20 06:14:26 +05302038 if (!chip->adc_tm_hc) {
2039 rc = qpnp_adc_tm_recalib_request_check(chip,
2040 sensor_num, true, &notify_check);
2041 if (rc < 0 || !notify_check) {
2042 pr_debug("Calib recheck re-armed rc=%d\n", rc);
2043 chip->th_info.adc_tm_high_enable = 0;
2044 return rc;
2045 }
2046 } else {
2047 rc = qpnp_adc_tm_reg_update(chip,
2048 QPNP_BTM_Mn_EN(btm_chan_idx),
2049 QPNP_BTM_Mn_HIGH_THR_INT_EN, false);
2050 if (rc < 0) {
2051 pr_err("high threshold int update failed\n");
2052 return rc;
2053 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002054 }
Prasad Malisetty358dda32018-02-20 06:14:26 +05302055 } else {
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002056 /*
2057 * Uses the thermal sysfs registered device to disable
2058 * the corresponding high voltage threshold which
2059 * is triggered by low temp
2060 */
2061 sensor_mask = 1 << sensor_num;
2062 pr_debug("thermal node with mask:%x\n", sensor_mask);
2063 rc = qpnp_adc_tm_activate_trip_type(
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002064 &chip->sensor[sensor_num],
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002065 ADC_TM_TRIP_LOW_COOL,
2066 THERMAL_TRIP_ACTIVATION_DISABLED);
2067 if (rc < 0) {
2068 pr_err("notify error:%d\n", sensor_num);
2069 return rc;
2070 }
2071 }
2072 list_for_each(thr_list, &chip->sensor[sensor_num].thr_list) {
2073 client_info = list_entry(thr_list,
2074 struct qpnp_adc_thr_client_info, list);
2075 if (client_info->high_thr_set) {
2076 client_info->high_thr_set = false;
2077 client_info->notify_high_thr = true;
2078 if (client_info->state_req_copy ==
2079 ADC_TM_HIGH_LOW_THR_ENABLE)
2080 client_info->state_req_copy =
2081 ADC_TM_LOW_THR_ENABLE;
2082 else
2083 client_info->state_req_copy =
2084 ADC_TM_HIGH_THR_DISABLE;
2085 }
2086 }
2087 qpnp_adc_tm_manage_thresholds(chip, sensor_num, btm_chan_num);
2088
Prasad Malisetty358dda32018-02-20 06:14:26 +05302089 if (!chip->adc_tm_hc) {
2090 rc = qpnp_adc_tm_reg_update(chip,
2091 QPNP_ADC_TM_MULTI_MEAS_EN,
2092 sensor_mask, false);
2093 if (rc < 0) {
2094 pr_err("multi meas disable failed\n");
2095 return rc;
2096 }
2097 } else {
2098 rc = qpnp_adc_tm_reg_update(chip,
2099 QPNP_BTM_Mn_EN(sensor_num),
2100 QPNP_BTM_Mn_MEAS_EN, false);
2101 if (rc < 0) {
2102 pr_err("multi meas disable failed\n");
2103 return rc;
2104 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002105 }
2106
2107 rc = qpnp_adc_tm_enable_if_channel_meas(chip);
2108 if (rc < 0) {
2109 pr_err("re-enabling measurement failed\n");
2110 return rc;
2111 }
2112
Siddartha Mohanadoss336fff42017-12-11 16:51:00 -08002113 if (!queue_work(chip->sensor[sensor_num].req_wq,
2114 &chip->sensor[sensor_num].work)) {
2115 /* The item is already queued, reduce the count */
2116 atomic_dec(&chip->wq_cnt);
2117 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002118
2119 return rc;
2120}
2121
2122static int qpnp_adc_tm_disable_rearm_low_thresholds(
2123 struct qpnp_adc_tm_chip *chip, int sensor_num)
2124{
2125 struct qpnp_adc_thr_client_info *client_info = NULL;
2126 struct list_head *thr_list;
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002127 uint32_t btm_chan_num = 0, btm_chan_idx = 0;
Prasad Malisetty358dda32018-02-20 06:14:26 +05302128 u8 sensor_mask = 0, notify_check = 0;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002129 int rc = 0;
2130
2131 btm_chan_num = chip->sensor[sensor_num].btm_channel_num;
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002132 rc = qpnp_adc_tm_get_btm_idx(chip, btm_chan_num, &btm_chan_idx);
2133 if (rc < 0) {
2134 pr_err("Invalid btm channel idx\n");
2135 return rc;
2136 }
2137
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002138 pr_debug("low:sen:%d, hs:0x%x, ls:0x%x, meas_en:0x%x\n",
2139 sensor_num, chip->th_info.adc_tm_high_enable,
2140 chip->th_info.adc_tm_low_enable,
2141 chip->th_info.qpnp_adc_tm_meas_en);
2142 if (!chip->sensor[sensor_num].thermal_node) {
2143 /*
2144 * For non thermal registered clients such as usb_id,
2145 * vbatt, pmic_therm
2146 */
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002147 sensor_mask = 1 << sensor_num;
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002148 pr_debug("non thermal node - mask:%x\n", sensor_mask);
Prasad Malisetty358dda32018-02-20 06:14:26 +05302149 if (!chip->adc_tm_hc) {
2150 rc = qpnp_adc_tm_recalib_request_check(chip,
2151 sensor_num, false, &notify_check);
2152 if (rc < 0 || !notify_check) {
2153 pr_debug("Calib recheck re-armed rc=%d\n", rc);
2154 chip->th_info.adc_tm_low_enable = 0;
2155 return rc;
2156 }
2157 } else {
2158 rc = qpnp_adc_tm_reg_update(chip,
2159 QPNP_BTM_Mn_EN(btm_chan_idx),
2160 QPNP_BTM_Mn_LOW_THR_INT_EN, false);
2161 if (rc < 0) {
2162 pr_err("low threshold int update failed\n");
2163 return rc;
2164 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002165 }
2166 } else {
2167 /*
2168 * Uses the thermal sysfs registered device to disable
2169 * the corresponding high voltage threshold which
2170 * is triggered by low temp
2171 */
2172 sensor_mask = 1 << sensor_num;
2173 pr_debug("thermal node with mask:%x\n", sensor_mask);
2174 rc = qpnp_adc_tm_activate_trip_type(
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002175 &chip->sensor[sensor_num],
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002176 ADC_TM_TRIP_HIGH_WARM,
2177 THERMAL_TRIP_ACTIVATION_DISABLED);
2178 if (rc < 0) {
2179 pr_err("notify error:%d\n", sensor_num);
2180 return rc;
2181 }
2182 }
2183 list_for_each(thr_list, &chip->sensor[sensor_num].thr_list) {
2184 client_info = list_entry(thr_list,
2185 struct qpnp_adc_thr_client_info, list);
2186 if (client_info->low_thr_set) {
2187 client_info->low_thr_set = false;
2188 client_info->notify_low_thr = true;
2189 if (client_info->state_req_copy ==
2190 ADC_TM_HIGH_LOW_THR_ENABLE)
2191 client_info->state_req_copy =
2192 ADC_TM_HIGH_THR_ENABLE;
2193 else
2194 client_info->state_req_copy =
2195 ADC_TM_LOW_THR_DISABLE;
2196 }
2197 }
2198 qpnp_adc_tm_manage_thresholds(chip, sensor_num, btm_chan_num);
2199
Prasad Malisetty358dda32018-02-20 06:14:26 +05302200 if (!chip->adc_tm_hc) {
2201 rc = qpnp_adc_tm_reg_update(chip,
2202 QPNP_ADC_TM_MULTI_MEAS_EN,
2203 sensor_mask, false);
2204 if (rc < 0) {
2205 pr_err("multi meas disable failed\n");
2206 return rc;
2207 }
2208 } else {
2209 rc = qpnp_adc_tm_reg_update(chip,
2210 QPNP_BTM_Mn_EN(sensor_num),
2211 QPNP_BTM_Mn_MEAS_EN, false);
2212 if (rc < 0) {
2213 pr_err("multi meas disable failed\n");
2214 return rc;
2215 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002216 }
2217
2218 rc = qpnp_adc_tm_enable_if_channel_meas(chip);
2219 if (rc < 0) {
2220 pr_err("re-enabling measurement failed\n");
2221 return rc;
2222 }
2223
Siddartha Mohanadoss336fff42017-12-11 16:51:00 -08002224 if (!queue_work(chip->sensor[sensor_num].req_wq,
2225 &chip->sensor[sensor_num].work)) {
2226 /* The item is already queued, reduce the count */
2227 atomic_dec(&chip->wq_cnt);
2228 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002229
2230 return rc;
2231}
2232
2233static int qpnp_adc_tm_read_status(struct qpnp_adc_tm_chip *chip)
2234{
2235 int rc = 0, sensor_num = 0;
2236
2237 if (qpnp_adc_tm_is_valid(chip))
2238 return -ENODEV;
2239
2240 pr_debug("%s\n", __func__);
2241
2242 mutex_lock(&chip->adc->adc_lock);
2243
Prasad Malisetty358dda32018-02-20 06:14:26 +05302244 if (!chip->adc_tm_hc) {
2245 rc = qpnp_adc_tm_req_sts_check(chip);
2246 if (rc) {
2247 pr_err("adc-tm-tm req sts check failed with %d\n", rc);
2248 goto fail;
2249 }
2250 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002251 while (sensor_num < chip->max_channels_available) {
2252 if (chip->sensor[sensor_num].high_thr_triggered) {
2253 rc = qpnp_adc_tm_disable_rearm_high_thresholds(
2254 chip, sensor_num);
2255 if (rc) {
2256 pr_err("rearm threshold failed\n");
2257 goto fail;
2258 }
2259 chip->sensor[sensor_num].high_thr_triggered = false;
2260 }
2261 sensor_num++;
2262 }
2263
2264 sensor_num = 0;
2265 while (sensor_num < chip->max_channels_available) {
2266 if (chip->sensor[sensor_num].low_thr_triggered) {
2267 rc = qpnp_adc_tm_disable_rearm_low_thresholds(
2268 chip, sensor_num);
2269 if (rc) {
2270 pr_err("rearm threshold failed\n");
2271 goto fail;
2272 }
2273 chip->sensor[sensor_num].low_thr_triggered = false;
2274 }
2275 sensor_num++;
2276 }
2277
2278fail:
2279 mutex_unlock(&chip->adc->adc_lock);
2280
2281 if (rc < 0 || (!chip->th_info.adc_tm_high_enable &&
2282 !chip->th_info.adc_tm_low_enable))
2283 atomic_dec(&chip->wq_cnt);
2284
2285 return rc;
2286}
2287
2288static void qpnp_adc_tm_high_thr_work(struct work_struct *work)
2289{
2290 struct qpnp_adc_tm_chip *chip = container_of(work,
2291 struct qpnp_adc_tm_chip, trigger_high_thr_work);
2292 int rc;
2293
2294 /* disable the vote if applicable */
2295 if (chip->adc_vote_enable && chip->adc->hkadc_ldo &&
2296 chip->adc->hkadc_ldo_ok) {
2297 qpnp_adc_disable_voltage(chip->adc);
2298 chip->adc_vote_enable = false;
2299 }
2300
2301 pr_debug("thr:0x%x\n", chip->th_info.adc_tm_high_enable);
2302
2303 rc = qpnp_adc_tm_read_status(chip);
2304 if (rc < 0)
2305 pr_err("adc-tm high thr work failed\n");
2306}
2307
Prasad Malisetty358dda32018-02-20 06:14:26 +05302308static irqreturn_t qpnp_adc_tm_high_thr_isr(int irq, void *data)
2309{
2310 struct qpnp_adc_tm_chip *chip = data;
2311 u8 mode_ctl = 0, status1 = 0, sensor_mask = 0;
2312 int rc = 0, sensor_notify_num = 0, i = 0, sensor_num = 0;
2313
2314 mode_ctl = ADC_OP_NORMAL_MODE << QPNP_OP_MODE_SHIFT;
2315 /* Set measurement in single measurement mode */
2316 qpnp_adc_tm_mode_select(chip, mode_ctl);
2317
2318 qpnp_adc_tm_disable(chip);
2319
2320 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_STATUS1, &status1, 1);
2321 if (rc) {
2322 pr_err("adc-tm read status1 failed\n");
2323 return IRQ_HANDLED;
2324 }
2325
2326 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_STATUS_HIGH,
2327 &chip->th_info.status_high, 1);
2328 if (rc) {
2329 pr_err("adc-tm-tm read status high failed with %d\n", rc);
2330 return IRQ_HANDLED;
2331 }
2332
2333 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_HIGH_THR_INT_EN,
2334 &chip->th_info.adc_tm_high_thr_set, 1);
2335 if (rc) {
2336 pr_err("adc-tm-tm read high thr failed with %d\n", rc);
2337 return IRQ_HANDLED;
2338 }
2339
2340 /* Check which interrupt threshold is lower and measure against the
2341 * enabled channel
2342 */
2343 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_MULTI_MEAS_EN,
2344 &chip->th_info.qpnp_adc_tm_meas_en, 1);
2345 if (rc) {
2346 pr_err("adc-tm-tm read status high failed with %d\n", rc);
2347 return IRQ_HANDLED;
2348 }
2349
2350 chip->th_info.adc_tm_high_enable = chip->th_info.qpnp_adc_tm_meas_en &
2351 chip->th_info.status_high;
2352 chip->th_info.adc_tm_high_enable &= chip->th_info.adc_tm_high_thr_set;
2353
2354 sensor_notify_num = chip->th_info.adc_tm_high_enable;
2355 while (i < chip->max_channels_available) {
2356 if ((sensor_notify_num & 0x1) == 1)
2357 sensor_num = i;
2358 sensor_notify_num >>= 1;
2359 i++;
2360 }
2361
2362 if (!chip->sensor[sensor_num].thermal_node) {
2363 sensor_mask = 1 << sensor_num;
2364 rc = qpnp_adc_tm_reg_update(chip,
2365 QPNP_ADC_TM_HIGH_THR_INT_EN,
2366 sensor_mask, false);
2367 if (rc < 0) {
2368 pr_err("high threshold int read failed\n");
2369 return IRQ_HANDLED;
2370 }
2371 } else {
2372 /*
2373 * Uses the thermal sysfs registered device to disable
2374 * the corresponding high voltage threshold which
2375 * is triggered by low temp
2376 */
2377 pr_debug("thermal node with mask:%x\n", sensor_mask);
2378 rc = qpnp_adc_tm_activate_trip_type(
2379 &chip->sensor[sensor_num],
2380 ADC_TM_TRIP_LOW_COOL,
2381 THERMAL_TRIP_ACTIVATION_DISABLED);
2382 if (rc < 0) {
2383 pr_err("notify error:%d\n", sensor_num);
2384 return IRQ_HANDLED;
2385 }
2386 }
2387
2388 atomic_inc(&chip->wq_cnt);
2389 queue_work(chip->high_thr_wq, &chip->trigger_high_thr_work);
2390
2391 return IRQ_HANDLED;
2392}
2393
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002394static void qpnp_adc_tm_low_thr_work(struct work_struct *work)
2395{
2396 struct qpnp_adc_tm_chip *chip = container_of(work,
2397 struct qpnp_adc_tm_chip, trigger_low_thr_work);
2398 int rc;
2399
2400 /* disable the vote if applicable */
2401 if (chip->adc_vote_enable && chip->adc->hkadc_ldo &&
2402 chip->adc->hkadc_ldo_ok) {
2403 qpnp_adc_disable_voltage(chip->adc);
2404 chip->adc_vote_enable = false;
2405 }
2406
2407 pr_debug("thr:0x%x\n", chip->th_info.adc_tm_low_enable);
2408
2409 rc = qpnp_adc_tm_read_status(chip);
2410 if (rc < 0)
2411 pr_err("adc-tm low thr work failed\n");
2412}
2413
Prasad Malisetty358dda32018-02-20 06:14:26 +05302414static irqreturn_t qpnp_adc_tm_low_thr_isr(int irq, void *data)
2415{
2416 struct qpnp_adc_tm_chip *chip = data;
2417 u8 mode_ctl = 0, status1 = 0, sensor_mask = 0;
2418 int rc = 0, sensor_notify_num = 0, i = 0, sensor_num = 0;
2419
2420 mode_ctl = ADC_OP_NORMAL_MODE << QPNP_OP_MODE_SHIFT;
2421 /* Set measurement in single measurement mode */
2422 qpnp_adc_tm_mode_select(chip, mode_ctl);
2423
2424 qpnp_adc_tm_disable(chip);
2425
2426 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_STATUS1, &status1, 1);
2427 if (rc) {
2428 pr_err("adc-tm read status1 failed\n");
2429 return IRQ_HANDLED;
2430 }
2431
2432 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_STATUS_LOW,
2433 &chip->th_info.status_low, 1);
2434 if (rc) {
2435 pr_err("adc-tm-tm read status low failed with %d\n", rc);
2436 return IRQ_HANDLED;
2437 }
2438
2439 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_LOW_THR_INT_EN,
2440 &chip->th_info.adc_tm_low_thr_set, 1);
2441 if (rc) {
2442 pr_err("adc-tm-tm read low thr failed with %d\n", rc);
2443 return IRQ_HANDLED;
2444 }
2445
2446 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_MULTI_MEAS_EN,
2447 &chip->th_info.qpnp_adc_tm_meas_en, 1);
2448 if (rc) {
2449 pr_err("adc-tm-tm read status high failed with %d\n", rc);
2450 return IRQ_HANDLED;
2451 }
2452
2453 chip->th_info.adc_tm_low_enable = chip->th_info.qpnp_adc_tm_meas_en &
2454 chip->th_info.status_low;
2455 chip->th_info.adc_tm_low_enable &= chip->th_info.adc_tm_low_thr_set;
2456
2457 sensor_notify_num = chip->th_info.adc_tm_low_enable;
2458 while (i < chip->max_channels_available) {
2459 if ((sensor_notify_num & 0x1) == 1)
2460 sensor_num = i;
2461 sensor_notify_num >>= 1;
2462 i++;
2463 }
2464
2465 if (!chip->sensor[sensor_num].thermal_node) {
2466 sensor_mask = 1 << sensor_num;
2467 rc = qpnp_adc_tm_reg_update(chip,
2468 QPNP_ADC_TM_LOW_THR_INT_EN,
2469 sensor_mask, false);
2470 if (rc < 0) {
2471 pr_err("low threshold int read failed\n");
2472 return IRQ_HANDLED;
2473 }
2474 } else {
2475 /*
2476 * Uses the thermal sysfs registered device to disable
2477 * the corresponding low voltage threshold which
2478 * is triggered by high temp
2479 */
2480 pr_debug("thermal node with mask:%x\n", sensor_mask);
2481 rc = qpnp_adc_tm_activate_trip_type(
2482 &chip->sensor[sensor_num],
2483 ADC_TM_TRIP_HIGH_WARM,
2484 THERMAL_TRIP_ACTIVATION_DISABLED);
2485 if (rc < 0) {
2486 pr_err("notify error:%d\n", sensor_num);
2487 return IRQ_HANDLED;
2488 }
2489 }
2490
2491 atomic_inc(&chip->wq_cnt);
2492 queue_work(chip->low_thr_wq, &chip->trigger_low_thr_work);
2493
2494 return IRQ_HANDLED;
2495}
2496
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002497static int qpnp_adc_tm_rc_check_sensor_trip(struct qpnp_adc_tm_chip *chip,
2498 u8 status_low, u8 status_high, int i,
2499 int *sensor_low_notify_num, int *sensor_high_notify_num)
2500{
2501 int rc = 0;
2502 u8 ctl = 0, sensor_mask = 0;
2503
2504 if (((status_low & 0x1) == 1) || ((status_high & 0x1) == 1)) {
2505 rc = qpnp_adc_tm_read_reg(chip,
2506 QPNP_BTM_Mn_EN(i), &ctl, 1);
2507 if (rc) {
2508 pr_err("ctl read failed with %d\n", rc);
2509 return IRQ_HANDLED;
2510 }
2511
2512 if ((status_low & 0x1) && (ctl & QPNP_BTM_Mn_MEAS_EN)
2513 && (ctl & QPNP_BTM_Mn_LOW_THR_INT_EN)) {
2514 /* Mask the corresponding low threshold interrupt en */
2515 if (!chip->sensor[i].thermal_node) {
2516 rc = qpnp_adc_tm_reg_update(chip,
2517 QPNP_BTM_Mn_EN(i),
2518 QPNP_BTM_Mn_LOW_THR_INT_EN, false);
2519 if (rc < 0) {
2520 pr_err("low thr_int en failed\n");
2521 return IRQ_HANDLED;
2522 }
2523 } else {
2524 /*
2525 * Uses the thermal sysfs registered device to disable
2526 * the corresponding low voltage threshold which
2527 * is triggered by high temp
2528 */
2529 pr_debug("thermal node with mask:%x\n", sensor_mask);
2530 rc = qpnp_adc_tm_activate_trip_type(
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002531 &chip->sensor[i],
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002532 ADC_TM_TRIP_HIGH_WARM,
2533 THERMAL_TRIP_ACTIVATION_DISABLED);
2534 if (rc < 0) {
2535 pr_err("notify error:%d\n", i);
2536 return IRQ_HANDLED;
2537 }
2538 }
2539 *sensor_low_notify_num |= (status_low & 0x1);
2540 chip->sensor[i].low_thr_triggered = true;
2541 }
2542
2543 if ((status_high & 0x1) && (ctl & QPNP_BTM_Mn_MEAS_EN) &&
2544 (ctl & QPNP_BTM_Mn_HIGH_THR_INT_EN)) {
2545 /* Mask the corresponding high threshold interrupt en */
2546 if (!chip->sensor[i].thermal_node) {
2547 rc = qpnp_adc_tm_reg_update(chip,
2548 QPNP_BTM_Mn_EN(i),
2549 QPNP_BTM_Mn_HIGH_THR_INT_EN, false);
2550 if (rc < 0) {
2551 pr_err("high thr_int en failed\n");
2552 return IRQ_HANDLED;
2553 }
2554 } else {
2555 /*
2556 * Uses the thermal sysfs registered device to disable
2557 * the corresponding high voltage threshold which
2558 * is triggered by low temp
2559 */
2560 pr_debug("thermal node with mask:%x\n", i);
2561 rc = qpnp_adc_tm_activate_trip_type(
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002562 &chip->sensor[i],
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002563 ADC_TM_TRIP_LOW_COOL,
2564 THERMAL_TRIP_ACTIVATION_DISABLED);
2565 if (rc < 0) {
2566 pr_err("notify error:%d\n", i);
2567 return IRQ_HANDLED;
2568 }
2569 }
2570 *sensor_high_notify_num |= (status_high & 0x1);
2571 chip->sensor[i].high_thr_triggered = true;
2572 }
2573 }
2574
2575 return rc;
2576}
2577
2578static irqreturn_t qpnp_adc_tm_rc_thr_isr(int irq, void *data)
2579{
2580 struct qpnp_adc_tm_chip *chip = data;
2581 u8 status_low = 0, status_high = 0;
2582 int rc = 0, sensor_low_notify_num = 0, i = 0;
2583 int sensor_high_notify_num = 0;
2584
2585 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_STATUS_LOW,
2586 &status_low, 1);
2587 if (rc) {
2588 pr_err("adc-tm-tm read status low failed with %d\n", rc);
2589 return IRQ_HANDLED;
2590 }
2591
2592 if (status_low)
2593 chip->th_info.adc_tm_low_enable = status_low;
2594
2595 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_STATUS_HIGH,
2596 &status_high, 1);
2597 if (rc) {
2598 pr_err("adc-tm-tm read status high failed with %d\n", rc);
2599 return IRQ_HANDLED;
2600 }
2601
2602 if (status_high)
2603 chip->th_info.adc_tm_high_enable = status_high;
2604
2605 while (i < chip->max_channels_available) {
2606 rc = qpnp_adc_tm_rc_check_sensor_trip(chip,
2607 status_low, status_high, i,
2608 &sensor_low_notify_num,
2609 &sensor_high_notify_num);
2610 if (rc) {
2611 pr_err("Sensor trip read failed\n");
2612 return IRQ_HANDLED;
2613 }
2614 status_low >>= 1;
2615 status_high >>= 1;
2616 i++;
2617 }
2618
2619 if (sensor_low_notify_num) {
Siddartha Mohanadoss336fff42017-12-11 16:51:00 -08002620 if (queue_work(chip->low_thr_wq, &chip->trigger_low_thr_work))
2621 atomic_inc(&chip->wq_cnt);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002622 }
2623
2624 if (sensor_high_notify_num) {
Siddartha Mohanadoss336fff42017-12-11 16:51:00 -08002625 if (queue_work(chip->high_thr_wq,
2626 &chip->trigger_high_thr_work))
2627 atomic_inc(&chip->wq_cnt);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002628 }
2629
2630 return IRQ_HANDLED;
2631}
2632
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002633static int qpnp_adc_read_temp(void *data, int *temp)
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002634{
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002635 struct qpnp_adc_tm_sensor *adc_tm_sensor = data;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002636 struct qpnp_adc_tm_chip *chip = adc_tm_sensor->chip;
2637 struct qpnp_vadc_result result;
2638 int rc = 0;
2639
2640 rc = qpnp_vadc_read(chip->vadc_dev,
2641 adc_tm_sensor->vadc_channel_num, &result);
2642 if (rc)
2643 return rc;
2644
2645 *temp = result.physical;
2646
2647 return rc;
2648}
2649
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002650static struct thermal_zone_of_device_ops qpnp_adc_tm_thermal_ops = {
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002651 .get_temp = qpnp_adc_read_temp,
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002652 .set_trips = qpnp_adc_tm_set_trip_temp,
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002653};
2654
2655int32_t qpnp_adc_tm_channel_measure(struct qpnp_adc_tm_chip *chip,
2656 struct qpnp_adc_tm_btm_param *param)
2657{
2658 uint32_t channel, amux_prescaling, dt_index = 0, scale_type = 0;
2659 int rc = 0, i = 0, version = 0;
2660 bool chan_found = false;
2661
2662 if (qpnp_adc_tm_is_valid(chip)) {
2663 pr_err("chip not valid\n");
2664 return -ENODEV;
2665 }
2666
2667 if (param->threshold_notification == NULL) {
2668 pr_debug("No notification for high/low temp??\n");
2669 return -EINVAL;
2670 }
2671
2672 mutex_lock(&chip->adc->adc_lock);
2673
2674 channel = param->channel;
2675
2676 if (channel == VSYS) {
2677 version = qpnp_adc_get_revid_version(chip->dev);
2678 if (version == QPNP_REV_ID_PM8950_1_0) {
2679 pr_debug("Channel not supported\n");
2680 rc = -EINVAL;
2681 goto fail_unlock;
2682 }
2683 }
2684
2685 while (i < chip->max_channels_available) {
2686 if (chip->adc->adc_channels[i].channel_num ==
2687 channel) {
2688 dt_index = i;
2689 chan_found = true;
2690 i++;
2691 } else
2692 i++;
2693 }
2694
2695 if (!chan_found) {
2696 pr_err("not a valid ADC_TM channel\n");
2697 rc = -EINVAL;
2698 goto fail_unlock;
2699 }
2700
2701 rc = qpnp_adc_tm_check_revision(chip,
2702 chip->sensor[dt_index].btm_channel_num);
2703 if (rc < 0)
2704 goto fail_unlock;
2705
2706 scale_type = chip->adc->adc_channels[dt_index].adc_scale_fn;
2707 if (scale_type >= SCALE_RSCALE_NONE) {
2708 rc = -EBADF;
2709 goto fail_unlock;
2710 }
2711
2712
2713 amux_prescaling =
2714 chip->adc->adc_channels[dt_index].chan_path_prescaling;
2715
2716 if (amux_prescaling >= PATH_SCALING_NONE) {
2717 rc = -EINVAL;
2718 goto fail_unlock;
2719 }
2720
2721 pr_debug("channel:%d, scale_type:%d, dt_idx:%d",
2722 channel, scale_type, dt_index);
2723 param->gain_num = qpnp_vadc_amux_scaling_ratio[amux_prescaling].num;
2724 param->gain_den = qpnp_vadc_amux_scaling_ratio[amux_prescaling].den;
2725 param->adc_tm_hc = chip->adc_tm_hc;
Siddartha Mohanadossd9e74fe2017-10-13 15:27:55 -07002726 param->full_scale_code = chip->adc->adc_prop->full_scale_code;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002727 chip->adc->amux_prop->amux_channel = channel;
2728 chip->adc->amux_prop->decimation =
2729 chip->adc->adc_channels[dt_index].adc_decimation;
2730 chip->adc->amux_prop->hw_settle_time =
2731 chip->adc->adc_channels[dt_index].hw_settle_time;
2732 chip->adc->amux_prop->fast_avg_setup =
2733 chip->adc->adc_channels[dt_index].fast_avg_setup;
2734 chip->adc->amux_prop->mode_sel =
2735 ADC_OP_MEASUREMENT_INTERVAL << QPNP_OP_MODE_SHIFT;
2736 adc_tm_rscale_fn[scale_type].chan(chip->vadc_dev, param,
2737 &chip->adc->amux_prop->chan_prop->low_thr,
2738 &chip->adc->amux_prop->chan_prop->high_thr);
2739 qpnp_adc_tm_add_to_list(chip, dt_index, param,
2740 chip->adc->amux_prop->chan_prop);
2741 chip->adc->amux_prop->chan_prop->tm_channel_select =
2742 chip->sensor[dt_index].btm_channel_num;
2743 chip->adc->amux_prop->chan_prop->state_request =
2744 param->state_request;
2745 chip->adc->amux_prop->calib_type =
2746 chip->adc->adc_channels[dt_index].calib_type;
Prasad Malisetty358dda32018-02-20 06:14:26 +05302747 if (!chip->adc_tm_hc) {
2748 rc = qpnp_adc_tm_configure(chip, chip->adc->amux_prop);
2749 if (rc) {
2750 pr_err("adc-tm configure failed with %d\n", rc);
2751 goto fail_unlock;
2752 }
2753 } else {
2754 rc = qpnp_adc_tm_hc_configure(chip, chip->adc->amux_prop);
2755 if (rc) {
2756 pr_err("adc-tm hc configure failed with %d\n", rc);
2757 goto fail_unlock;
2758 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002759 }
2760
2761 chip->sensor[dt_index].scale_type = scale_type;
2762
2763fail_unlock:
2764 mutex_unlock(&chip->adc->adc_lock);
2765
2766 return rc;
2767}
2768EXPORT_SYMBOL(qpnp_adc_tm_channel_measure);
2769
2770int32_t qpnp_adc_tm_disable_chan_meas(struct qpnp_adc_tm_chip *chip,
2771 struct qpnp_adc_tm_btm_param *param)
2772{
2773 uint32_t channel, dt_index = 0, btm_chan_num;
Prasad Malisetty358dda32018-02-20 06:14:26 +05302774 u8 sensor_mask = 0, mode_ctl = 0;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002775 int rc = 0;
2776
2777 if (qpnp_adc_tm_is_valid(chip))
2778 return -ENODEV;
2779
2780 mutex_lock(&chip->adc->adc_lock);
2781
Prasad Malisetty358dda32018-02-20 06:14:26 +05302782 if (!chip->adc_tm_hc) {
2783 /* Set measurement in single measurement mode */
2784 mode_ctl = ADC_OP_NORMAL_MODE << QPNP_OP_MODE_SHIFT;
2785 rc = qpnp_adc_tm_mode_select(chip, mode_ctl);
2786 if (rc < 0) {
2787 pr_err("adc-tm single mode select failed\n");
2788 goto fail;
2789 }
2790 }
2791
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002792 /* Disable bank */
2793 rc = qpnp_adc_tm_disable(chip);
2794 if (rc < 0) {
2795 pr_err("adc-tm disable failed\n");
2796 goto fail;
2797 }
2798
Prasad Malisetty358dda32018-02-20 06:14:26 +05302799 if (!chip->adc_tm_hc) {
2800 /* Check if a conversion is in progress */
2801 rc = qpnp_adc_tm_req_sts_check(chip);
2802 if (rc < 0) {
2803 pr_err("adc-tm req_sts check failed\n");
2804 goto fail;
2805 }
2806 }
2807
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002808 channel = param->channel;
2809 while ((chip->adc->adc_channels[dt_index].channel_num
2810 != channel) && (dt_index < chip->max_channels_available))
2811 dt_index++;
2812
2813 if (dt_index >= chip->max_channels_available) {
2814 pr_err("not a valid ADC_TMN channel\n");
2815 rc = -EINVAL;
2816 goto fail;
2817 }
2818
2819 btm_chan_num = chip->sensor[dt_index].btm_channel_num;
2820
Prasad Malisetty358dda32018-02-20 06:14:26 +05302821 if (!chip->adc_tm_hc) {
2822 sensor_mask = 1 << chip->sensor[dt_index].sensor_num;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002823
Prasad Malisetty358dda32018-02-20 06:14:26 +05302824 rc = qpnp_adc_tm_reg_update(chip, QPNP_ADC_TM_LOW_THR_INT_EN,
2825 sensor_mask, false);
2826 if (rc < 0) {
2827 pr_err("high threshold int enable failed\n");
2828 goto fail;
2829 }
2830
2831 rc = qpnp_adc_tm_reg_update(chip, QPNP_ADC_TM_MULTI_MEAS_EN,
2832 sensor_mask, false);
2833 if (rc < 0) {
2834 pr_err("multi measurement en failed\n");
2835 goto fail;
2836 }
2837 } else {
2838 rc = qpnp_adc_tm_reg_update(chip, QPNP_BTM_Mn_EN(btm_chan_num),
2839 QPNP_BTM_Mn_HIGH_THR_INT_EN, false);
2840 if (rc < 0) {
2841 pr_err("high thr disable err:%d\n", btm_chan_num);
2842 return rc;
2843 }
2844
2845 rc = qpnp_adc_tm_reg_update(chip, QPNP_BTM_Mn_EN(btm_chan_num),
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002846 QPNP_BTM_Mn_LOW_THR_INT_EN, false);
Prasad Malisetty358dda32018-02-20 06:14:26 +05302847 if (rc < 0) {
2848 pr_err("low thr disable err:%d\n", btm_chan_num);
2849 return rc;
2850 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002851
Prasad Malisetty358dda32018-02-20 06:14:26 +05302852 rc = qpnp_adc_tm_reg_update(chip, QPNP_BTM_Mn_EN(btm_chan_num),
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002853 QPNP_BTM_Mn_MEAS_EN, false);
Prasad Malisetty358dda32018-02-20 06:14:26 +05302854 if (rc < 0) {
2855 pr_err("multi measurement disable failed\n");
2856 return rc;
2857 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002858 }
2859
2860 rc = qpnp_adc_tm_enable_if_channel_meas(chip);
2861 if (rc < 0)
2862 pr_err("re-enabling measurement failed\n");
2863
2864fail:
2865 mutex_unlock(&chip->adc->adc_lock);
2866
2867 return rc;
2868}
2869EXPORT_SYMBOL(qpnp_adc_tm_disable_chan_meas);
2870
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002871struct qpnp_adc_tm_chip *qpnp_get_adc_tm(struct device *dev, const char *name)
2872{
2873 struct qpnp_adc_tm_chip *chip;
2874 struct device_node *node = NULL;
2875 char prop_name[QPNP_MAX_PROP_NAME_LEN];
2876
2877 snprintf(prop_name, QPNP_MAX_PROP_NAME_LEN, "qcom,%s-adc_tm", name);
2878
2879 node = of_parse_phandle(dev->of_node, prop_name, 0);
2880 if (node == NULL)
2881 return ERR_PTR(-ENODEV);
2882
2883 list_for_each_entry(chip, &qpnp_adc_tm_device_list, list)
2884 if (chip->adc->pdev->dev.of_node == node)
2885 return chip;
2886
2887 return ERR_PTR(-EPROBE_DEFER);
2888}
2889EXPORT_SYMBOL(qpnp_get_adc_tm);
2890
Prasad Malisetty358dda32018-02-20 06:14:26 +05302891static int qpnp_adc_tm_initial_setup(struct qpnp_adc_tm_chip *chip)
2892{
2893 u8 thr_init = 0;
2894 int rc = 0;
2895
2896 rc = qpnp_adc_tm_write_reg(chip, QPNP_ADC_TM_HIGH_THR_INT_EN,
2897 thr_init, 1);
2898 if (rc < 0) {
2899 pr_err("high thr init failed\n");
2900 return rc;
2901 }
2902
2903 rc = qpnp_adc_tm_write_reg(chip, QPNP_ADC_TM_LOW_THR_INT_EN,
2904 thr_init, 1);
2905 if (rc < 0) {
2906 pr_err("low thr init failed\n");
2907 return rc;
2908 }
2909
2910 rc = qpnp_adc_tm_write_reg(chip, QPNP_ADC_TM_MULTI_MEAS_EN,
2911 thr_init, 1);
2912 if (rc < 0) {
2913 pr_err("multi meas en failed\n");
2914 return rc;
2915 }
2916
2917 return rc;
2918}
2919
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002920static const struct of_device_id qpnp_adc_tm_match_table[] = {
2921 { .compatible = "qcom,qpnp-adc-tm" },
2922 { .compatible = "qcom,qpnp-adc-tm-hc" },
2923 {}
2924};
2925
2926static int qpnp_adc_tm_probe(struct platform_device *pdev)
2927{
2928 struct device_node *node = pdev->dev.of_node, *child;
2929 struct qpnp_adc_tm_chip *chip;
2930 struct qpnp_adc_drv *adc_qpnp;
2931 int32_t count_adc_channel_list = 0, rc, sen_idx = 0, i = 0;
2932 bool thermal_node = false;
2933 const struct of_device_id *id;
2934
2935 for_each_child_of_node(node, child)
2936 count_adc_channel_list++;
2937
2938 if (!count_adc_channel_list) {
2939 pr_err("No channel listing\n");
2940 return -EINVAL;
2941 }
2942
2943 id = of_match_node(qpnp_adc_tm_match_table, node);
2944 if (id == NULL) {
2945 pr_err("qpnp_adc_tm_match of_node prop not present\n");
2946 return -ENODEV;
2947 }
2948
2949 chip = devm_kzalloc(&pdev->dev, sizeof(struct qpnp_adc_tm_chip) +
2950 (count_adc_channel_list *
2951 sizeof(struct qpnp_adc_tm_sensor)),
2952 GFP_KERNEL);
2953 if (!chip)
2954 return -ENOMEM;
2955
2956 adc_qpnp = devm_kzalloc(&pdev->dev, sizeof(struct qpnp_adc_drv),
2957 GFP_KERNEL);
2958 if (!adc_qpnp) {
2959 rc = -ENOMEM;
2960 goto fail;
2961 }
2962
2963 chip->dev = &(pdev->dev);
2964 chip->adc = adc_qpnp;
2965 chip->adc->regmap = dev_get_regmap(pdev->dev.parent, NULL);
2966 if (!chip->adc->regmap) {
2967 dev_err(&pdev->dev, "Couldn't get parent's regmap\n");
2968 rc = -EINVAL;
2969 goto fail;
2970 }
2971
Prasad Malisetty358dda32018-02-20 06:14:26 +05302972 if (of_device_is_compatible(node, "qcom,qpnp-adc-tm-hc")) {
2973 chip->adc_tm_hc = true;
2974 chip->adc->adc_hc = true;
2975 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002976
2977 rc = qpnp_adc_get_devicetree_data(pdev, chip->adc);
2978 if (rc) {
2979 dev_err(&pdev->dev, "failed to read device tree\n");
2980 goto fail;
2981 }
2982 mutex_init(&chip->adc->adc_lock);
2983
Prasad Malisetty358dda32018-02-20 06:14:26 +05302984 /* Register the ADC peripheral interrupt */
2985 if (!chip->adc_tm_hc) {
2986 chip->adc->adc_high_thr_irq = platform_get_irq_byname(pdev,
2987 "high-thr-en-set");
2988 if (chip->adc->adc_high_thr_irq < 0) {
2989 pr_err("Invalid irq\n");
2990 rc = -ENXIO;
2991 goto fail;
2992 }
2993
2994 chip->adc->adc_low_thr_irq = platform_get_irq_byname(pdev,
2995 "low-thr-en-set");
2996 if (chip->adc->adc_low_thr_irq < 0) {
2997 pr_err("Invalid irq\n");
2998 rc = -ENXIO;
2999 goto fail;
3000 }
3001 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003002 chip->vadc_dev = qpnp_get_vadc(&pdev->dev, "adc_tm");
3003 if (IS_ERR(chip->vadc_dev)) {
3004 rc = PTR_ERR(chip->vadc_dev);
3005 if (rc != -EPROBE_DEFER)
3006 pr_err("vadc property missing, rc=%d\n", rc);
3007 goto fail;
3008 }
3009
3010 chip->adc_tm_recalib_check = of_property_read_bool(node,
3011 "qcom,adc-tm-recalib-check");
3012
3013 for_each_child_of_node(node, child) {
3014 char name[25];
3015 int btm_channel_num, timer_select = 0;
3016
3017 rc = of_property_read_u32(child,
3018 "qcom,btm-channel-number", &btm_channel_num);
3019 if (rc) {
3020 pr_err("Invalid btm channel number\n");
3021 goto fail;
3022 }
3023 rc = of_property_read_u32(child,
3024 "qcom,meas-interval-timer-idx", &timer_select);
3025 if (rc) {
3026 pr_debug("Default to timer2 with interval of 1 sec\n");
3027 chip->sensor[sen_idx].timer_select =
3028 ADC_MEAS_TIMER_SELECT2;
3029 chip->sensor[sen_idx].meas_interval =
3030 ADC_MEAS2_INTERVAL_1S;
3031 } else {
3032 if (timer_select >= ADC_MEAS_TIMER_NUM) {
3033 pr_err("Invalid timer selection number\n");
3034 goto fail;
3035 }
3036 chip->sensor[sen_idx].timer_select = timer_select;
3037 if (timer_select == ADC_MEAS_TIMER_SELECT1)
3038 chip->sensor[sen_idx].meas_interval =
3039 ADC_MEAS1_INTERVAL_3P9MS;
3040 else if (timer_select == ADC_MEAS_TIMER_SELECT3)
3041 chip->sensor[sen_idx].meas_interval =
3042 ADC_MEAS3_INTERVAL_4S;
3043 else if (timer_select == ADC_MEAS_TIMER_SELECT2)
3044 chip->sensor[sen_idx].meas_interval =
3045 ADC_MEAS2_INTERVAL_1S;
3046 }
3047
3048 chip->sensor[sen_idx].btm_channel_num = btm_channel_num;
3049 chip->sensor[sen_idx].vadc_channel_num =
3050 chip->adc->adc_channels[sen_idx].channel_num;
3051 chip->sensor[sen_idx].sensor_num = sen_idx;
3052 chip->sensor[sen_idx].chip = chip;
3053 pr_debug("btm_chan:%x, vadc_chan:%x\n", btm_channel_num,
3054 chip->adc->adc_channels[sen_idx].channel_num);
3055 thermal_node = of_property_read_bool(child,
3056 "qcom,thermal-node");
3057 if (thermal_node) {
3058 /* Register with the thermal zone */
3059 pr_debug("thermal node%x\n", btm_channel_num);
3060 chip->sensor[sen_idx].mode = THERMAL_DEVICE_DISABLED;
3061 chip->sensor[sen_idx].thermal_node = true;
3062 snprintf(name, sizeof(name), "%s",
3063 chip->adc->adc_channels[sen_idx].name);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003064 chip->sensor[sen_idx].low_thr =
3065 QPNP_ADC_TM_M0_LOW_THR;
3066 chip->sensor[sen_idx].high_thr =
3067 QPNP_ADC_TM_M0_HIGH_THR;
3068 chip->sensor[sen_idx].tz_dev =
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07003069 devm_thermal_zone_of_sensor_register(
3070 chip->dev,
3071 chip->sensor[sen_idx].vadc_channel_num,
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003072 &chip->sensor[sen_idx],
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07003073 &qpnp_adc_tm_thermal_ops);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003074 if (IS_ERR(chip->sensor[sen_idx].tz_dev))
3075 pr_err("thermal device register failed.\n");
3076 }
3077 chip->sensor[sen_idx].req_wq = alloc_workqueue(
3078 "qpnp_adc_notify_wq", WQ_HIGHPRI, 0);
3079 if (!chip->sensor[sen_idx].req_wq) {
3080 pr_err("Requesting priority wq failed\n");
3081 goto fail;
3082 }
3083 INIT_WORK(&chip->sensor[sen_idx].work, notify_adc_tm_fn);
3084 INIT_LIST_HEAD(&chip->sensor[sen_idx].thr_list);
3085 sen_idx++;
3086 }
3087 chip->max_channels_available = count_adc_channel_list;
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07003088
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003089 chip->high_thr_wq = alloc_workqueue("qpnp_adc_tm_high_thr_wq",
3090 WQ_HIGHPRI, 0);
3091 if (!chip->high_thr_wq) {
3092 pr_err("Requesting high thr priority wq failed\n");
3093 goto fail;
3094 }
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07003095
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003096 chip->low_thr_wq = alloc_workqueue("qpnp_adc_tm_low_thr_wq",
3097 WQ_HIGHPRI, 0);
3098 if (!chip->low_thr_wq) {
3099 pr_err("Requesting low thr priority wq failed\n");
3100 goto fail;
3101 }
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07003102
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003103 chip->thr_wq = alloc_workqueue("qpnp_adc_tm_thr_wq",
3104 WQ_HIGHPRI, 0);
3105 if (!chip->thr_wq) {
3106 pr_err("Requesting thr priority wq failed\n");
3107 goto fail;
3108 }
3109
3110 INIT_WORK(&chip->trigger_high_thr_work, qpnp_adc_tm_high_thr_work);
3111 INIT_WORK(&chip->trigger_low_thr_work, qpnp_adc_tm_low_thr_work);
3112 atomic_set(&chip->wq_cnt, 0);
3113
Prasad Malisetty358dda32018-02-20 06:14:26 +05303114 if (!chip->adc_tm_hc) {
3115 rc = qpnp_adc_tm_initial_setup(chip);
3116 if (rc)
3117 goto fail;
3118 rc = devm_request_irq(&pdev->dev, chip->adc->adc_high_thr_irq,
3119 qpnp_adc_tm_high_thr_isr,
3120 IRQF_TRIGGER_RISING, "qpnp_adc_tm_high_interrupt", chip);
3121 if (rc) {
3122 dev_err(&pdev->dev, "failed to request adc irq\n");
3123 goto fail;
3124 } else {
3125 enable_irq_wake(chip->adc->adc_high_thr_irq);
3126 }
3127
3128 rc = devm_request_irq(&pdev->dev, chip->adc->adc_low_thr_irq,
3129 qpnp_adc_tm_low_thr_isr,
3130 IRQF_TRIGGER_RISING,
3131 "qpnp_adc_tm_low_interrupt", chip);
3132 if (rc) {
3133 dev_err(&pdev->dev, "failed to request adc irq\n");
3134 goto fail;
3135 } else {
3136 enable_irq_wake(chip->adc->adc_low_thr_irq);
3137 }
3138 } else {
3139 rc = devm_request_irq(&pdev->dev, chip->adc->adc_irq_eoc,
3140 qpnp_adc_tm_rc_thr_isr,
3141 IRQF_TRIGGER_HIGH, "qpnp_adc_tm_interrupt", chip);
3142 if (rc)
3143 dev_err(&pdev->dev, "failed to request adc irq\n");
3144 else
3145 enable_irq_wake(chip->adc->adc_irq_eoc);
3146 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003147
3148 chip->adc_vote_enable = false;
3149 dev_set_drvdata(&pdev->dev, chip);
3150 list_add(&chip->list, &qpnp_adc_tm_device_list);
Prasad Malisetty358dda32018-02-20 06:14:26 +05303151 spin_lock_init(&chip->th_info.adc_tm_low_lock);
3152 spin_lock_init(&chip->th_info.adc_tm_high_lock);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003153
3154 pr_debug("OK\n");
3155 return 0;
3156fail:
3157 for_each_child_of_node(node, child) {
3158 thermal_node = of_property_read_bool(child,
3159 "qcom,thermal-node");
3160 if (thermal_node) {
3161 thermal_zone_device_unregister(chip->sensor[i].tz_dev);
3162 if (chip->sensor[i].req_wq)
3163 destroy_workqueue(chip->sensor[sen_idx].req_wq);
3164 }
3165 }
3166 if (chip->high_thr_wq)
3167 destroy_workqueue(chip->high_thr_wq);
3168 if (chip->low_thr_wq)
3169 destroy_workqueue(chip->low_thr_wq);
3170 dev_set_drvdata(&pdev->dev, NULL);
3171 return rc;
3172}
3173
3174static int qpnp_adc_tm_remove(struct platform_device *pdev)
3175{
3176 struct qpnp_adc_tm_chip *chip = dev_get_drvdata(&pdev->dev);
3177 struct device_node *node = pdev->dev.of_node, *child;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003178 int i = 0;
3179
3180 for_each_child_of_node(node, child) {
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07003181 if (chip->sensor[i].req_wq)
3182 destroy_workqueue(chip->sensor[i].req_wq);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003183 i++;
3184 }
3185
3186 if (chip->high_thr_wq)
3187 destroy_workqueue(chip->high_thr_wq);
3188 if (chip->low_thr_wq)
3189 destroy_workqueue(chip->low_thr_wq);
3190 if (chip->adc->hkadc_ldo && chip->adc->hkadc_ldo_ok)
3191 qpnp_adc_free_voltage_resource(chip->adc);
3192 dev_set_drvdata(&pdev->dev, NULL);
3193
3194 return 0;
3195}
3196
3197static void qpnp_adc_tm_shutdown(struct platform_device *pdev)
3198{
3199 struct qpnp_adc_tm_chip *chip = dev_get_drvdata(&pdev->dev);
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07003200 int rc = 0, i = 0;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003201
3202 /* Disable bank */
3203 rc = qpnp_adc_tm_disable(chip);
3204 if (rc < 0)
3205 pr_err("adc-tm disable failed\n");
3206
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07003207 for (i = 0; i < QPNP_BTM_CHANNELS; i++) {
3208 rc = qpnp_adc_tm_reg_update(chip,
3209 QPNP_BTM_Mn_EN(i),
3210 QPNP_BTM_Mn_MEAS_EN, false);
3211 if (rc < 0)
3212 pr_err("multi measurement disable failed\n");
3213 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003214}
3215
3216static int qpnp_adc_tm_suspend_noirq(struct device *dev)
3217{
3218 struct qpnp_adc_tm_chip *chip = dev_get_drvdata(dev);
3219
3220 if (atomic_read(&chip->wq_cnt) != 0) {
3221 pr_err(
3222 "Aborting suspend, adc_tm notification running while suspending\n");
3223 return -EBUSY;
3224 }
3225 return 0;
3226}
3227
3228static const struct dev_pm_ops qpnp_adc_tm_pm_ops = {
3229 .suspend_noirq = qpnp_adc_tm_suspend_noirq,
3230};
3231
3232static struct platform_driver qpnp_adc_tm_driver = {
3233 .driver = {
3234 .name = "qcom,qpnp-adc-tm",
3235 .of_match_table = qpnp_adc_tm_match_table,
3236 .pm = &qpnp_adc_tm_pm_ops,
3237 },
3238 .probe = qpnp_adc_tm_probe,
3239 .remove = qpnp_adc_tm_remove,
3240 .shutdown = qpnp_adc_tm_shutdown,
3241};
3242
3243static int __init qpnp_adc_tm_init(void)
3244{
3245 return platform_driver_register(&qpnp_adc_tm_driver);
3246}
3247module_init(qpnp_adc_tm_init);
3248
3249static void __exit qpnp_adc_tm_exit(void)
3250{
3251 platform_driver_unregister(&qpnp_adc_tm_driver);
3252}
3253module_exit(qpnp_adc_tm_exit);
3254
3255MODULE_DESCRIPTION("QPNP PMIC ADC Threshold Monitoring driver");
3256MODULE_LICENSE("GPL v2");