blob: f8fdc13d4b5ebf1f0a2a52b3b5158207d6778638 [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
472 if (chip->adc_tm_hc) {
473 rc = qpnp_adc_tm_write_reg(chip, QPNP_BTM_CONV_REQ, data, 1);
474 if (rc < 0) {
475 pr_err("adc-tm enable failed\n");
476 return rc;
477 }
478 }
479
480 rc = qpnp_adc_tm_write_reg(chip, QPNP_EN_CTL1, data, 1);
481 if (rc < 0) {
482 pr_err("adc-tm disable failed\n");
483 return rc;
484 }
485
486 return rc;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800487}
488
489static int qpnp_adc_tm_is_valid(struct qpnp_adc_tm_chip *chip)
490{
491 struct qpnp_adc_tm_chip *adc_tm_chip = NULL;
492
493 list_for_each_entry(adc_tm_chip, &qpnp_adc_tm_device_list, list)
494 if (chip == adc_tm_chip)
495 return 0;
496
497 return -EINVAL;
498}
499
500static int32_t qpnp_adc_tm_rc_check_channel_en(struct qpnp_adc_tm_chip *chip)
501{
502 u8 adc_tm_ctl = 0, status_low = 0, status_high = 0;
503 int rc = 0, i = 0;
504 bool ldo_en = false;
505
506 for (i = 0; i < chip->max_channels_available; i++) {
507 rc = qpnp_adc_tm_read_reg(chip, QPNP_BTM_Mn_CTL(i),
508 &adc_tm_ctl, 1);
509 if (rc) {
510 pr_err("adc-tm-tm read ctl failed with %d\n", rc);
511 return rc;
512 }
513
514 adc_tm_ctl &= QPNP_BTM_Mn_MEAS_EN;
515 status_low = adc_tm_ctl & QPNP_BTM_Mn_LOW_THR_INT_EN;
516 status_high = adc_tm_ctl & QPNP_BTM_Mn_HIGH_THR_INT_EN;
517
518 /* Enable only if there are pending measurement requests */
519 if ((adc_tm_ctl && status_high) ||
520 (adc_tm_ctl && status_low)) {
521 qpnp_adc_tm_enable(chip);
522 ldo_en = true;
523
524 /* Request conversion */
525 rc = qpnp_adc_tm_write_reg(chip, QPNP_CONV_REQ,
526 QPNP_CONV_REQ_SET, 1);
527 if (rc < 0) {
528 pr_err("adc-tm request conversion failed\n");
529 return rc;
530 }
531 }
532 break;
533 }
534
535 if (!ldo_en) {
536 /* disable the vote if applicable */
537 if (chip->adc_vote_enable && chip->adc->hkadc_ldo &&
538 chip->adc->hkadc_ldo_ok) {
539 qpnp_adc_disable_voltage(chip->adc);
540 chip->adc_vote_enable = false;
541 }
542 }
543
544 return rc;
545}
546
547static int32_t qpnp_adc_tm_enable_if_channel_meas(
548 struct qpnp_adc_tm_chip *chip)
549{
Prasad Malisetty358dda32018-02-20 06:14:26 +0530550 u8 adc_tm_meas_en = 0, status_low = 0, status_high = 0;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800551 int rc = 0;
552
Prasad Malisetty358dda32018-02-20 06:14:26 +0530553 if (chip->adc_tm_hc) {
554 rc = qpnp_adc_tm_rc_check_channel_en(chip);
555 if (rc) {
556 pr_err("adc_tm channel check failed\n");
557 return rc;
558 }
559 } else {
560 /* Check if a measurement request is still required */
561 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_MULTI_MEAS_EN,
562 &adc_tm_meas_en, 1);
563 if (rc) {
564 pr_err("read status high failed with %d\n", rc);
565 return rc;
566 }
567 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_LOW_THR_INT_EN,
568 &status_low, 1);
569 if (rc) {
570 pr_err("read status low failed with %d\n", rc);
571 return rc;
572 }
573
574 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_HIGH_THR_INT_EN,
575 &status_high, 1);
576 if (rc) {
577 pr_err("read status high failed with %d\n", rc);
578 return rc;
579 }
580
581 /* Enable only if there are pending measurement requests */
582 if ((adc_tm_meas_en && status_high) ||
583 (adc_tm_meas_en && status_low)) {
584 qpnp_adc_tm_enable(chip);
585 /* Request conversion */
586 rc = qpnp_adc_tm_write_reg(chip, QPNP_CONV_REQ,
587 QPNP_CONV_REQ_SET, 1);
588 if (rc < 0) {
589 pr_err("adc-tm request conversion failed\n");
590 return rc;
591 }
592 } else {
593 /* disable the vote if applicable */
594 if (chip->adc_vote_enable && chip->adc->hkadc_ldo &&
595 chip->adc->hkadc_ldo_ok) {
596 qpnp_adc_disable_voltage(chip->adc);
597 chip->adc_vote_enable = false;
598 }
599 }
600 }
601 return rc;
602}
603
604static int32_t qpnp_adc_tm_mode_select(struct qpnp_adc_tm_chip *chip,
605 u8 mode_ctl)
606{
607 int rc;
608
609 mode_ctl |= (QPNP_ADC_TRIM_EN | QPNP_AMUX_TRIM_EN);
610
611 /* VADC_BTM current sets mode to recurring measurements */
612 rc = qpnp_adc_tm_write_reg(chip, QPNP_MODE_CTL, mode_ctl, 1);
613 if (rc < 0)
614 pr_err("adc-tm write mode selection err\n");
615
616 return rc;
617}
618
619static int32_t qpnp_adc_tm_req_sts_check(struct qpnp_adc_tm_chip *chip)
620{
621 u8 status1 = 0, mode_ctl = 0;
622 int rc, count = 0;
623
624 /* Re-enable the peripheral */
625 rc = qpnp_adc_tm_enable(chip);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800626 if (rc) {
Prasad Malisetty358dda32018-02-20 06:14:26 +0530627 pr_err("adc-tm re-enable peripheral failed\n");
628 return rc;
629 }
630
631 /* The VADC_TM bank needs to be disabled for new conversion request */
632 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_STATUS1, &status1, 1);
633 if (rc) {
634 pr_err("adc-tm read status1 failed\n");
635 return rc;
636 }
637
638 /* Disable the bank if a conversion is occurring */
639 while (status1 & QPNP_STATUS1_REQ_STS) {
640 if (count > QPNP_RETRY) {
641 pr_err("retry error=%d with 0x%x\n", count, status1);
642 break;
643 }
644 /*
645 * Wait time is based on the optimum sampling rate
646 * and adding enough time buffer to account for ADC conversions
647 * occurring on different peripheral banks
648 */
649 usleep_range(QPNP_MIN_TIME, QPNP_MAX_TIME);
650 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_STATUS1,
651 &status1, 1);
652 if (rc < 0) {
653 pr_err("adc-tm disable failed\n");
654 return rc;
655 }
656 count++;
657 }
658
659 if (!chip->adc_tm_hc) {
660 /* Change the mode back to recurring measurement mode */
661 mode_ctl = ADC_OP_MEASUREMENT_INTERVAL << QPNP_OP_MODE_SHIFT;
662 rc = qpnp_adc_tm_mode_select(chip, mode_ctl);
663 if (rc < 0) {
664 pr_err("adc-tm mode change to recurring failed\n");
665 return rc;
666 }
667 }
668
669 /* Disable the peripheral */
670 rc = qpnp_adc_tm_disable(chip);
671 if (rc < 0) {
672 pr_err("adc-tm peripheral disable failed\n");
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800673 return rc;
674 }
675
676 return rc;
677}
678
679static int32_t qpnp_adc_tm_get_btm_idx(struct qpnp_adc_tm_chip *chip,
680 uint32_t btm_chan, uint32_t *btm_chan_idx)
681{
682 int rc = 0, i;
683 bool chan_found = false;
684
Prasad Malisetty358dda32018-02-20 06:14:26 +0530685 if (!chip->adc_tm_hc) {
686 for (i = 0; i < QPNP_ADC_TM_CHAN_NONE; i++) {
687 if (adc_tm_data[i].btm_amux_chan == btm_chan) {
688 *btm_chan_idx = i;
689 chan_found = true;
690 }
691 }
692 } else {
693 for (i = 0; i < chip->max_channels_available; i++) {
694 if (chip->sensor[i].btm_channel_num == btm_chan) {
695 *btm_chan_idx = i;
696 chan_found = true;
697 break;
698 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800699 }
700 }
701
702 if (!chan_found)
703 return -EINVAL;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800704 return rc;
705}
706
707static int32_t qpnp_adc_tm_check_revision(struct qpnp_adc_tm_chip *chip,
708 uint32_t btm_chan_num)
709{
710 u8 rev, perph_subtype;
711 int rc = 0;
712
713 rc = qpnp_adc_tm_read_reg(chip, QPNP_REVISION3, &rev, 1);
714 if (rc) {
715 pr_err("adc-tm revision read failed\n");
716 return rc;
717 }
718
719 rc = qpnp_adc_tm_read_reg(chip, QPNP_PERPH_SUBTYPE, &perph_subtype, 1);
720 if (rc) {
721 pr_err("adc-tm perph_subtype read failed\n");
722 return rc;
723 }
724
725 if (perph_subtype == QPNP_PERPH_TYPE2) {
726 if ((rev < QPNP_REVISION_EIGHT_CHANNEL_SUPPORT) &&
727 (btm_chan_num > QPNP_ADC_TM_M4_ADC_CH_SEL_CTL)) {
728 pr_debug("Version does not support more than 5 channels\n");
729 return -EINVAL;
730 }
731 }
732
733 if (perph_subtype == QPNP_PERPH_SUBTYPE_TWO_CHANNEL_SUPPORT) {
734 if (btm_chan_num > QPNP_ADC_TM_M1_ADC_CH_SEL_CTL) {
735 pr_debug("Version does not support more than 2 channels\n");
736 return -EINVAL;
737 }
738 }
739
740 return rc;
741}
742
743static int32_t qpnp_adc_tm_timer_interval_select(
744 struct qpnp_adc_tm_chip *chip, uint32_t btm_chan,
745 struct qpnp_vadc_chan_properties *chan_prop)
746{
747 int rc, chan_idx = 0, i = 0;
748 bool chan_found = false;
749 u8 meas_interval_timer2 = 0, timer_interval_store = 0;
750 uint32_t btm_chan_idx = 0;
751
752 while (i < chip->max_channels_available) {
753 if (chip->sensor[i].btm_channel_num == btm_chan) {
754 chan_idx = i;
755 chan_found = true;
756 i++;
757 } else
758 i++;
759 }
760
761 if (!chan_found) {
762 pr_err("Channel not found\n");
763 return -EINVAL;
764 }
765
766 switch (chip->sensor[chan_idx].timer_select) {
767 case ADC_MEAS_TIMER_SELECT1:
Prasad Malisetty358dda32018-02-20 06:14:26 +0530768 if (!chip->adc_tm_hc)
769 rc = qpnp_adc_tm_write_reg(chip,
770 QPNP_ADC_TM_MEAS_INTERVAL_CTL,
771 chip->sensor[chan_idx].meas_interval, 1);
772 else
773 rc = qpnp_adc_tm_write_reg(chip,
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800774 QPNP_BTM_MEAS_INTERVAL_CTL,
775 chip->sensor[chan_idx].meas_interval, 1);
776 if (rc < 0) {
777 pr_err("timer1 configure failed\n");
778 return rc;
779 }
Prasad Malisetty358dda32018-02-20 06:14:26 +0530780 break;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800781 case ADC_MEAS_TIMER_SELECT2:
782 /* Thermal channels uses timer2, default to 1 second */
Prasad Malisetty358dda32018-02-20 06:14:26 +0530783 if (!chip->adc_tm_hc)
784 rc = qpnp_adc_tm_read_reg(chip,
785 QPNP_ADC_TM_MEAS_INTERVAL_CTL2,
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800786 &meas_interval_timer2, 1);
Prasad Malisetty358dda32018-02-20 06:14:26 +0530787 else
788 rc = qpnp_adc_tm_read_reg(chip,
789 QPNP_BTM_MEAS_INTERVAL_CTL2,
790 &meas_interval_timer2, 1);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800791 if (rc < 0) {
792 pr_err("timer2 configure read failed\n");
793 return rc;
794 }
795 timer_interval_store = chip->sensor[chan_idx].meas_interval;
796 timer_interval_store <<= QPNP_ADC_TM_MEAS_INTERVAL_CTL2_SHIFT;
797 timer_interval_store &= QPNP_ADC_TM_MEAS_INTERVAL_CTL2_MASK;
798 meas_interval_timer2 |= timer_interval_store;
Prasad Malisetty358dda32018-02-20 06:14:26 +0530799 if (!chip->adc_tm_hc)
800 rc = qpnp_adc_tm_write_reg(chip,
801 QPNP_ADC_TM_MEAS_INTERVAL_CTL2,
802 meas_interval_timer2, 1);
803 else
804 rc = qpnp_adc_tm_write_reg(chip,
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800805 QPNP_BTM_MEAS_INTERVAL_CTL2,
806 meas_interval_timer2, 1);
807 if (rc < 0) {
808 pr_err("timer2 configure failed\n");
809 return rc;
810 }
811 break;
812 case ADC_MEAS_TIMER_SELECT3:
Prasad Malisetty358dda32018-02-20 06:14:26 +0530813 if (!chip->adc_tm_hc)
814 rc = qpnp_adc_tm_read_reg(chip,
815 QPNP_ADC_TM_MEAS_INTERVAL_CTL2,
816 &meas_interval_timer2, 1);
817 else
818 rc = qpnp_adc_tm_read_reg(chip,
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800819 QPNP_BTM_MEAS_INTERVAL_CTL2,
820 &meas_interval_timer2, 1);
821 if (rc < 0) {
822 pr_err("timer3 read failed\n");
823 return rc;
824 }
825 timer_interval_store = chip->sensor[chan_idx].meas_interval;
826 timer_interval_store &= QPNP_ADC_TM_MEAS_INTERVAL_CTL3_MASK;
827 meas_interval_timer2 |= timer_interval_store;
Prasad Malisetty358dda32018-02-20 06:14:26 +0530828 if (!chip->adc_tm_hc)
829 rc = qpnp_adc_tm_write_reg(chip,
830 QPNP_ADC_TM_MEAS_INTERVAL_CTL2,
831 meas_interval_timer2, 1);
832 else
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800833 rc = qpnp_adc_tm_write_reg(chip,
834 QPNP_BTM_MEAS_INTERVAL_CTL2,
835 meas_interval_timer2, 1);
836 if (rc < 0) {
837 pr_err("timer3 configure failed\n");
838 return rc;
839 }
840 break;
841 default:
842 pr_err("Invalid timer selection\n");
843 return -EINVAL;
844 }
845
846 /* Select the timer to use for the corresponding channel */
847 rc = qpnp_adc_tm_get_btm_idx(chip, btm_chan, &btm_chan_idx);
848 if (rc < 0) {
849 pr_err("Invalid btm channel idx\n");
850 return rc;
851 }
Prasad Malisetty358dda32018-02-20 06:14:26 +0530852 if (!chip->adc_tm_hc)
853 rc = qpnp_adc_tm_write_reg(chip,
854 adc_tm_data[btm_chan_idx].meas_interval_ctl,
855 chip->sensor[chan_idx].timer_select, 1);
856 else
857 rc = qpnp_adc_tm_write_reg(chip,
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -0700858 QPNP_BTM_Mn_MEAS_INTERVAL_CTL(btm_chan_idx),
859 chip->sensor[chan_idx].timer_select, 1);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -0800860 if (rc < 0) {
861 pr_err("TM channel timer configure failed\n");
862 return rc;
863 }
864
865 pr_debug("timer select:%d, timer_value_within_select:%d, channel:%x\n",
866 chip->sensor[chan_idx].timer_select,
867 chip->sensor[chan_idx].meas_interval,
868 btm_chan);
869
870 return rc;
871}
872
873static int32_t qpnp_adc_tm_add_to_list(struct qpnp_adc_tm_chip *chip,
874 uint32_t dt_index,
875 struct qpnp_adc_tm_btm_param *param,
876 struct qpnp_vadc_chan_properties *chan_prop)
877{
878 struct qpnp_adc_thr_client_info *client_info = NULL;
879 bool client_info_exists = false;
880
881 list_for_each_entry(client_info,
882 &chip->sensor[dt_index].thr_list, list) {
883 if (client_info->btm_param == param) {
884 client_info->low_thr_requested = chan_prop->low_thr;
885 client_info->high_thr_requested = chan_prop->high_thr;
886 client_info->state_requested = param->state_request;
887 client_info->state_req_copy = param->state_request;
888 client_info->notify_low_thr = false;
889 client_info->notify_high_thr = false;
890 client_info_exists = true;
891 pr_debug("client found\n");
892 }
893 }
894
895 if (!client_info_exists) {
896 client_info = devm_kzalloc(chip->dev,
897 sizeof(struct qpnp_adc_thr_client_info), GFP_KERNEL);
898 if (!client_info)
899 return -ENOMEM;
900
901 pr_debug("new client\n");
902 client_info->btm_param = param;
903 client_info->low_thr_requested = chan_prop->low_thr;
904 client_info->high_thr_requested = chan_prop->high_thr;
905 client_info->state_requested = param->state_request;
906 client_info->state_req_copy = param->state_request;
907
908 list_add_tail(&client_info->list,
909 &chip->sensor[dt_index].thr_list);
910 }
911
912 return 0;
913}
914
915static int32_t qpnp_adc_tm_reg_update(struct qpnp_adc_tm_chip *chip,
916 uint16_t addr, u8 mask, bool state)
917{
918 u8 reg_value = 0;
919 int rc = 0;
920
921 rc = qpnp_adc_tm_read_reg(chip, addr, &reg_value, 1);
922 if (rc < 0) {
923 pr_err("read failed for addr:0x%x\n", addr);
924 return rc;
925 }
926
927 reg_value = reg_value & ~mask;
928 if (state)
929 reg_value |= mask;
930
931 pr_debug("state:%d, reg:0x%x with bits:0x%x and mask:0x%x\n",
932 state, addr, reg_value, ~mask);
933 rc = qpnp_adc_tm_write_reg(chip, addr, reg_value, 1);
934 if (rc < 0) {
935 pr_err("write failed for addr:%x\n", addr);
936 return rc;
937 }
938
939 return rc;
940}
941
Prasad Malisetty358dda32018-02-20 06:14:26 +0530942static int32_t qpnp_adc_tm_read_thr_value(struct qpnp_adc_tm_chip *chip,
943 uint32_t btm_chan)
944{
945 int rc = 0;
946 u8 data_lsb = 0, data_msb = 0;
947 uint32_t btm_chan_idx = 0;
948 int32_t low_thr = 0, high_thr = 0;
949
950 if (!chip->adc_tm_hc) {
951 pr_err("Not applicable for VADC HC peripheral\n");
952 return -EINVAL;
953 }
954
955 rc = qpnp_adc_tm_get_btm_idx(chip, btm_chan, &btm_chan_idx);
956 if (rc < 0) {
957 pr_err("Invalid btm channel idx\n");
958 return rc;
959 }
960
961 rc = qpnp_adc_tm_read_reg(chip,
962 adc_tm_data[btm_chan_idx].low_thr_lsb_addr,
963 &data_lsb, 1);
964 if (rc < 0) {
965 pr_err("low threshold lsb setting failed\n");
966 return rc;
967 }
968
969 rc = qpnp_adc_tm_read_reg(chip,
970 adc_tm_data[btm_chan_idx].low_thr_msb_addr,
971 &data_msb, 1);
972 if (rc < 0) {
973 pr_err("low threshold msb setting failed\n");
974 return rc;
975 }
976
977 low_thr = (data_msb << 8) | data_lsb;
978
979 rc = qpnp_adc_tm_read_reg(chip,
980 adc_tm_data[btm_chan_idx].high_thr_lsb_addr,
981 &data_lsb, 1);
982 if (rc < 0) {
983 pr_err("high threshold lsb setting failed\n");
984 return rc;
985 }
986
987 rc = qpnp_adc_tm_read_reg(chip,
988 adc_tm_data[btm_chan_idx].high_thr_msb_addr,
989 &data_msb, 1);
990 if (rc < 0) {
991 pr_err("high threshold msb setting failed\n");
992 return rc;
993 }
994
995 high_thr = (data_msb << 8) | data_lsb;
996
997 pr_debug("configured thresholds high:0x%x and low:0x%x\n",
998 high_thr, low_thr);
999
1000 return rc;
1001}
1002
1003
1004
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001005static int32_t qpnp_adc_tm_thr_update(struct qpnp_adc_tm_chip *chip,
1006 uint32_t btm_chan, int32_t high_thr, int32_t low_thr)
1007{
1008 int rc = 0;
1009 uint32_t btm_chan_idx = 0;
1010
1011 rc = qpnp_adc_tm_get_btm_idx(chip, btm_chan, &btm_chan_idx);
1012 if (rc < 0) {
1013 pr_err("Invalid btm channel idx\n");
1014 return rc;
1015 }
1016
Prasad Malisetty358dda32018-02-20 06:14:26 +05301017 if (!chip->adc_tm_hc) {
1018 rc = qpnp_adc_tm_write_reg(chip,
1019 adc_tm_data[btm_chan_idx].low_thr_lsb_addr,
1020 QPNP_ADC_TM_THR_LSB_MASK(low_thr), 1);
1021 if (rc < 0) {
1022 pr_err("low threshold lsb setting failed\n");
1023 return rc;
1024 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001025
Prasad Malisetty358dda32018-02-20 06:14:26 +05301026 rc = qpnp_adc_tm_write_reg(chip,
1027 adc_tm_data[btm_chan_idx].low_thr_msb_addr,
1028 QPNP_ADC_TM_THR_MSB_MASK(low_thr), 1);
1029 if (rc < 0) {
1030 pr_err("low threshold msb setting failed\n");
1031 return rc;
1032 }
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001033
Prasad Malisetty358dda32018-02-20 06:14:26 +05301034 rc = qpnp_adc_tm_write_reg(chip,
1035 adc_tm_data[btm_chan_idx].high_thr_lsb_addr,
1036 QPNP_ADC_TM_THR_LSB_MASK(high_thr), 1);
1037 if (rc < 0) {
1038 pr_err("high threshold lsb setting failed\n");
1039 return rc;
1040 }
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001041
Prasad Malisetty358dda32018-02-20 06:14:26 +05301042 rc = qpnp_adc_tm_write_reg(chip,
1043 adc_tm_data[btm_chan_idx].high_thr_msb_addr,
1044 QPNP_ADC_TM_THR_MSB_MASK(high_thr), 1);
1045 if (rc < 0)
1046 pr_err("high threshold msb setting failed\n");
1047 } else {
1048 rc = qpnp_adc_tm_write_reg(chip,
1049 QPNP_BTM_Mn_LOW_THR0(btm_chan_idx),
1050 QPNP_ADC_TM_THR_LSB_MASK(low_thr), 1);
1051 if (rc < 0) {
1052 pr_err("low threshold lsb setting failed\n");
1053 return rc;
1054 }
1055
1056 rc = qpnp_adc_tm_write_reg(chip,
1057 QPNP_BTM_Mn_LOW_THR1(btm_chan_idx),
1058 QPNP_ADC_TM_THR_MSB_MASK(low_thr), 1);
1059 if (rc < 0) {
1060 pr_err("low threshold msb setting failed\n");
1061 return rc;
1062 }
1063
1064 rc = qpnp_adc_tm_write_reg(chip,
1065 QPNP_BTM_Mn_HIGH_THR0(btm_chan_idx),
1066 QPNP_ADC_TM_THR_LSB_MASK(high_thr), 1);
1067 if (rc < 0) {
1068 pr_err("high threshold lsb setting failed\n");
1069 return rc;
1070 }
1071
1072 rc = qpnp_adc_tm_write_reg(chip,
1073 QPNP_BTM_Mn_HIGH_THR1(btm_chan_idx),
1074 QPNP_ADC_TM_THR_MSB_MASK(high_thr), 1);
1075 if (rc < 0)
1076 pr_err("high threshold msb setting failed\n");
1077
1078 }
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001079
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001080 pr_debug("client requested high:%d and low:%d\n",
Prasad Malisetty358dda32018-02-20 06:14:26 +05301081 high_thr, low_thr);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001082
1083 return rc;
1084}
1085
1086static int32_t qpnp_adc_tm_manage_thresholds(struct qpnp_adc_tm_chip *chip,
1087 uint32_t dt_index, uint32_t btm_chan)
1088{
1089 struct qpnp_adc_thr_client_info *client_info = NULL;
1090 struct list_head *thr_list;
1091 int high_thr = 0, low_thr = 0, rc = 0;
1092
1093
1094 /*
1095 * high_thr/low_thr starting point and reset the high_thr_set and
1096 * low_thr_set back to reset since the thresholds will be
1097 * recomputed.
1098 */
1099 list_for_each(thr_list,
1100 &chip->sensor[dt_index].thr_list) {
1101 client_info = list_entry(thr_list,
1102 struct qpnp_adc_thr_client_info, list);
1103 high_thr = client_info->high_thr_requested;
1104 low_thr = client_info->low_thr_requested;
1105 client_info->high_thr_set = false;
1106 client_info->low_thr_set = false;
1107 }
1108
1109 pr_debug("init threshold is high:%d and low:%d\n", high_thr, low_thr);
1110
1111 /* Find the min of high_thr and max of low_thr */
1112 list_for_each(thr_list,
1113 &chip->sensor[dt_index].thr_list) {
1114 client_info = list_entry(thr_list,
1115 struct qpnp_adc_thr_client_info, list);
1116 if ((client_info->state_req_copy == ADC_TM_HIGH_THR_ENABLE) ||
1117 (client_info->state_req_copy ==
1118 ADC_TM_HIGH_LOW_THR_ENABLE))
1119 if (client_info->high_thr_requested < high_thr)
1120 high_thr = client_info->high_thr_requested;
1121
1122 if ((client_info->state_req_copy == ADC_TM_LOW_THR_ENABLE) ||
1123 (client_info->state_req_copy ==
1124 ADC_TM_HIGH_LOW_THR_ENABLE))
1125 if (client_info->low_thr_requested > low_thr)
1126 low_thr = client_info->low_thr_requested;
1127
1128 pr_debug("threshold compared is high:%d and low:%d\n",
1129 client_info->high_thr_requested,
1130 client_info->low_thr_requested);
1131 pr_debug("current threshold is high:%d and low:%d\n",
1132 high_thr, low_thr);
1133 }
1134
1135 /* Check which of the high_thr and low_thr got set */
1136 list_for_each(thr_list,
1137 &chip->sensor[dt_index].thr_list) {
1138 client_info = list_entry(thr_list,
1139 struct qpnp_adc_thr_client_info, list);
1140 if ((client_info->state_req_copy == ADC_TM_HIGH_THR_ENABLE) ||
1141 (client_info->state_req_copy ==
1142 ADC_TM_HIGH_LOW_THR_ENABLE))
1143 if (high_thr == client_info->high_thr_requested)
1144 client_info->high_thr_set = true;
1145
1146 if ((client_info->state_req_copy == ADC_TM_LOW_THR_ENABLE) ||
1147 (client_info->state_req_copy ==
1148 ADC_TM_HIGH_LOW_THR_ENABLE))
1149 if (low_thr == client_info->low_thr_requested)
1150 client_info->low_thr_set = true;
1151 }
1152
1153 rc = qpnp_adc_tm_thr_update(chip, btm_chan, high_thr, low_thr);
1154 if (rc < 0)
1155 pr_err("setting chan:%d threshold failed\n", btm_chan);
1156
1157 pr_debug("threshold written is high:%d and low:%d\n",
1158 high_thr, low_thr);
1159
1160 return 0;
1161}
1162
1163static int32_t qpnp_adc_tm_channel_configure(struct qpnp_adc_tm_chip *chip,
1164 uint32_t btm_chan,
1165 struct qpnp_vadc_chan_properties *chan_prop,
1166 uint32_t amux_channel)
1167{
1168 int rc = 0, i = 0, chan_idx = 0;
1169 bool chan_found = false, high_thr_set = false, low_thr_set = false;
1170 u8 sensor_mask = 0;
1171 struct qpnp_adc_thr_client_info *client_info = NULL;
1172 uint32_t btm_chan_idx = 0;
1173
1174 while (i < chip->max_channels_available) {
1175 if (chip->sensor[i].btm_channel_num == btm_chan) {
1176 chan_idx = i;
1177 chan_found = true;
1178 i++;
1179 } else
1180 i++;
1181 }
1182
1183 if (!chan_found) {
1184 pr_err("Channel not found\n");
1185 return -EINVAL;
1186 }
1187
1188 rc = qpnp_adc_tm_get_btm_idx(chip, btm_chan, &btm_chan_idx);
1189 if (rc < 0) {
1190 pr_err("Invalid btm channel idx\n");
1191 return rc;
1192 }
1193
1194 sensor_mask = 1 << chan_idx;
1195 if (!chip->sensor[chan_idx].thermal_node) {
1196 /* Update low and high notification thresholds */
1197 rc = qpnp_adc_tm_manage_thresholds(chip, chan_idx,
1198 btm_chan);
1199 if (rc < 0) {
1200 pr_err("setting chan:%d threshold failed\n", btm_chan);
1201 return rc;
1202 }
1203
1204 list_for_each_entry(client_info,
1205 &chip->sensor[chan_idx].thr_list, list) {
1206 if (client_info->high_thr_set == true)
1207 high_thr_set = true;
1208 if (client_info->low_thr_set == true)
1209 low_thr_set = true;
1210 }
1211
1212 if (low_thr_set) {
1213 pr_debug("low sensor mask:%x with state:%d\n",
1214 sensor_mask, chan_prop->state_request);
1215 /* Enable low threshold's interrupt */
Prasad Malisetty358dda32018-02-20 06:14:26 +05301216 if (!chip->adc_tm_hc)
1217 rc = qpnp_adc_tm_reg_update(chip,
1218 QPNP_ADC_TM_LOW_THR_INT_EN,
1219 sensor_mask, true);
1220 else
1221 rc = qpnp_adc_tm_reg_update(chip,
1222 QPNP_BTM_Mn_EN(btm_chan_idx),
1223 QPNP_BTM_Mn_LOW_THR_INT_EN, true);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001224 if (rc < 0) {
1225 pr_err("low thr enable err:%d\n", btm_chan);
1226 return rc;
1227 }
1228 }
1229
1230 if (high_thr_set) {
1231 /* Enable high threshold's interrupt */
1232 pr_debug("high sensor mask:%x\n", sensor_mask);
Prasad Malisetty358dda32018-02-20 06:14:26 +05301233 if (!chip->adc_tm_hc)
1234 rc = qpnp_adc_tm_reg_update(chip,
1235 QPNP_ADC_TM_HIGH_THR_INT_EN,
1236 sensor_mask, true);
1237 else
1238 rc = qpnp_adc_tm_reg_update(chip,
1239 QPNP_BTM_Mn_EN(btm_chan_idx),
1240 QPNP_BTM_Mn_HIGH_THR_INT_EN, true);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001241 if (rc < 0) {
1242 pr_err("high thr enable err:%d\n", btm_chan);
1243 return rc;
1244 }
1245 }
1246 }
1247
1248 /* Enable corresponding BTM channel measurement */
Prasad Malisetty358dda32018-02-20 06:14:26 +05301249 if (!chip->adc_tm_hc)
1250 rc = qpnp_adc_tm_reg_update(chip,
1251 QPNP_ADC_TM_MULTI_MEAS_EN, sensor_mask, true);
1252 else
1253 rc = qpnp_adc_tm_reg_update(chip, QPNP_BTM_Mn_EN(btm_chan_idx),
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001254 QPNP_BTM_Mn_MEAS_EN, true);
1255 if (rc < 0) {
1256 pr_err("multi measurement en failed\n");
1257 return rc;
1258 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001259 return rc;
1260}
1261
1262static int32_t qpnp_adc_tm_hc_configure(struct qpnp_adc_tm_chip *chip,
1263 struct qpnp_adc_amux_properties *chan_prop)
1264{
1265 u8 decimation = 0, fast_avg_ctl = 0;
1266 u8 buf[8];
1267 int rc = 0;
1268 uint32_t btm_chan = 0, cal_type = 0, btm_chan_idx = 0;
1269
1270 /* Disable bank */
1271 rc = qpnp_adc_tm_disable(chip);
1272 if (rc)
1273 return rc;
1274
1275 /* Decimation setup */
1276 decimation = chan_prop->decimation;
1277 rc = qpnp_adc_tm_write_reg(chip, QPNP_BTM_HC_ADC_DIG_PARAM,
1278 decimation, 1);
1279 if (rc < 0) {
1280 pr_err("adc-tm digital parameter setup err\n");
1281 return rc;
1282 }
1283
1284 /* Fast averaging setup/enable */
1285 rc = qpnp_adc_tm_read_reg(chip, QPNP_BTM_HC_FAST_AVG_CTL,
1286 &fast_avg_ctl, 1);
1287 if (rc < 0) {
1288 pr_err("adc-tm fast-avg enable read err\n");
1289 return rc;
1290 }
1291 fast_avg_ctl |= chan_prop->fast_avg_setup;
1292 rc = qpnp_adc_tm_write_reg(chip, QPNP_BTM_HC_FAST_AVG_CTL,
1293 fast_avg_ctl, 1);
1294 if (rc < 0) {
1295 pr_err("adc-tm fast-avg enable write err\n");
1296 return rc;
1297 }
1298
1299 /* Read block registers for respective BTM channel */
1300 btm_chan = chan_prop->chan_prop->tm_channel_select;
1301 rc = qpnp_adc_tm_get_btm_idx(chip, btm_chan, &btm_chan_idx);
1302 if (rc < 0) {
1303 pr_err("Invalid btm channel idx\n");
1304 return rc;
1305 }
1306
1307 rc = qpnp_adc_tm_read_reg(chip,
1308 QPNP_BTM_Mn_ADC_CH_SEL_CTL(btm_chan_idx), buf, 8);
1309 if (rc < 0) {
1310 pr_err("qpnp adc configure block read failed\n");
1311 return rc;
1312 }
1313
1314 /* Update ADC channel sel */
1315 rc = qpnp_adc_tm_write_reg(chip,
1316 QPNP_BTM_Mn_ADC_CH_SEL_CTL(btm_chan_idx),
1317 chan_prop->amux_channel, 1);
1318 if (rc < 0) {
1319 pr_err("adc-tm channel amux select failed\n");
1320 return rc;
1321 }
1322
1323 /* Manage thresholds */
1324 rc = qpnp_adc_tm_channel_configure(chip, btm_chan,
1325 chan_prop->chan_prop, chan_prop->amux_channel);
1326 if (rc < 0) {
1327 pr_err("adc-tm channel threshold configure failed\n");
1328 return rc;
1329 }
1330
1331 /* Measurement interval setup */
1332 rc = qpnp_adc_tm_timer_interval_select(chip, btm_chan,
1333 chan_prop->chan_prop);
1334 if (rc < 0) {
1335 pr_err("adc-tm timer select failed\n");
1336 return rc;
1337 }
1338
1339 /* Set calibration select, hw_settle delay */
1340 cal_type |= (chan_prop->calib_type << QPNP_BTM_CTL_CAL_SEL_MASK_SHIFT);
1341 buf[6] &= ~QPNP_BTM_CTL_HW_SETTLE_DELAY_MASK;
1342 buf[6] |= chan_prop->hw_settle_time;
1343 buf[6] &= ~QPNP_BTM_CTL_CAL_SEL;
1344 buf[6] |= cal_type;
1345 rc = qpnp_adc_tm_write_reg(chip, QPNP_BTM_Mn_CTL(btm_chan_idx),
1346 buf[6], 1);
1347 if (rc < 0) {
1348 pr_err("adc-tm hw-settle, calib sel failed\n");
1349 return rc;
1350 }
1351
1352 /* Enable bank */
1353 rc = qpnp_adc_tm_enable(chip);
1354 if (rc)
1355 return rc;
1356
1357 /* Request conversion */
1358 rc = qpnp_adc_tm_write_reg(chip, QPNP_CONV_REQ, QPNP_CONV_REQ_SET, 1);
1359 if (rc < 0) {
1360 pr_err("adc-tm request conversion failed\n");
1361 return rc;
1362 }
1363
1364 return 0;
1365}
1366
Prasad Malisetty358dda32018-02-20 06:14:26 +05301367static int32_t qpnp_adc_tm_configure(struct qpnp_adc_tm_chip *chip,
1368 struct qpnp_adc_amux_properties *chan_prop)
1369{
1370 u8 decimation = 0, op_cntrl = 0, mode_ctl = 0;
1371 int rc = 0;
1372 uint32_t btm_chan = 0;
1373
1374 /* Set measurement in single measurement mode */
1375 mode_ctl = ADC_OP_NORMAL_MODE << QPNP_OP_MODE_SHIFT;
1376 rc = qpnp_adc_tm_mode_select(chip, mode_ctl);
1377 if (rc < 0) {
1378 pr_err("adc-tm single mode select failed\n");
1379 return rc;
1380 }
1381
1382 /* Disable bank */
1383 rc = qpnp_adc_tm_disable(chip);
1384 if (rc)
1385 return rc;
1386
1387 /* Check if a conversion is in progress */
1388 rc = qpnp_adc_tm_req_sts_check(chip);
1389 if (rc < 0) {
1390 pr_err("adc-tm req_sts check failed\n");
1391 return rc;
1392 }
1393
1394 /* Configure AMUX channel select for the corresponding BTM channel*/
1395 btm_chan = chan_prop->chan_prop->tm_channel_select;
1396 rc = qpnp_adc_tm_write_reg(chip, btm_chan, chan_prop->amux_channel, 1);
1397 if (rc < 0) {
1398 pr_err("adc-tm channel selection err\n");
1399 return rc;
1400 }
1401
1402 /* Digital parameter setup */
1403 decimation |= chan_prop->decimation <<
1404 QPNP_ADC_DIG_DEC_RATIO_SEL_SHIFT;
1405 rc = qpnp_adc_tm_write_reg(chip, QPNP_ADC_DIG_PARAM, decimation, 1);
1406 if (rc < 0) {
1407 pr_err("adc-tm digital parameter setup err\n");
1408 return rc;
1409 }
1410
1411 /* Hardware setting time */
1412 rc = qpnp_adc_tm_write_reg(chip, QPNP_HW_SETTLE_DELAY,
1413 chan_prop->hw_settle_time, 1);
1414 if (rc < 0) {
1415 pr_err("adc-tm hw settling time setup err\n");
1416 return rc;
1417 }
1418
1419 /* Fast averaging setup/enable */
1420 rc = qpnp_adc_tm_fast_avg_en(chip, &chan_prop->fast_avg_setup);
1421 if (rc < 0) {
1422 pr_err("adc-tm fast-avg enable err\n");
1423 return rc;
1424 }
1425
1426 rc = qpnp_adc_tm_write_reg(chip, QPNP_FAST_AVG_CTL,
1427 chan_prop->fast_avg_setup, 1);
1428 if (rc < 0) {
1429 pr_err("adc-tm fast-avg setup err\n");
1430 return rc;
1431 }
1432
1433 /* Measurement interval setup */
1434 rc = qpnp_adc_tm_timer_interval_select(chip, btm_chan,
1435 chan_prop->chan_prop);
1436 if (rc < 0) {
1437 pr_err("adc-tm timer select failed\n");
1438 return rc;
1439 }
1440
1441 /* Channel configuration setup */
1442 rc = qpnp_adc_tm_channel_configure(chip, btm_chan,
1443 chan_prop->chan_prop, chan_prop->amux_channel);
1444 if (rc < 0) {
1445 pr_err("adc-tm channel configure failed\n");
1446 return rc;
1447 }
1448
1449 /* Recurring interval measurement enable */
1450 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_MEAS_INTERVAL_OP_CTL,
1451 &op_cntrl, 1);
1452 op_cntrl |= QPNP_ADC_MEAS_INTERVAL_OP;
1453 rc = qpnp_adc_tm_reg_update(chip, QPNP_ADC_MEAS_INTERVAL_OP_CTL,
1454 op_cntrl, true);
1455 if (rc < 0) {
1456 pr_err("adc-tm meas interval op configure failed\n");
1457 return rc;
1458 }
1459
1460 /* Enable bank */
1461 rc = qpnp_adc_tm_enable(chip);
1462 if (rc)
1463 return rc;
1464
1465 /* Request conversion */
1466 rc = qpnp_adc_tm_write_reg(chip, QPNP_CONV_REQ, QPNP_CONV_REQ_SET, 1);
1467 if (rc < 0) {
1468 pr_err("adc-tm request conversion failed\n");
1469 return rc;
1470 }
1471
1472 return 0;
1473}
1474
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001475static int qpnp_adc_tm_set_mode(struct qpnp_adc_tm_sensor *adc_tm,
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001476 enum thermal_device_mode mode)
1477{
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001478 struct qpnp_adc_tm_chip *chip = adc_tm->chip;
1479 int rc = 0, channel;
Prasad Malisetty358dda32018-02-20 06:14:26 +05301480 u8 sensor_mask = 0, mode_ctl = 0;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001481 uint32_t btm_chan_idx = 0, btm_chan = 0;
1482
1483 if (qpnp_adc_tm_is_valid(chip)) {
1484 pr_err("invalid device\n");
1485 return -ENODEV;
1486 }
1487
1488 if (qpnp_adc_tm_check_revision(chip, adc_tm->btm_channel_num))
1489 return -EINVAL;
1490
1491 mutex_lock(&chip->adc->adc_lock);
1492
1493 btm_chan = adc_tm->btm_channel_num;
1494 rc = qpnp_adc_tm_get_btm_idx(chip, btm_chan, &btm_chan_idx);
1495 if (rc < 0) {
1496 pr_err("Invalid btm channel idx\n");
1497 goto fail;
1498 }
1499
1500 if (mode == THERMAL_DEVICE_ENABLED) {
1501 chip->adc->amux_prop->amux_channel =
1502 adc_tm->vadc_channel_num;
1503 channel = adc_tm->sensor_num;
1504 chip->adc->amux_prop->decimation =
1505 chip->adc->adc_channels[channel].adc_decimation;
1506 chip->adc->amux_prop->hw_settle_time =
1507 chip->adc->adc_channels[channel].hw_settle_time;
1508 chip->adc->amux_prop->fast_avg_setup =
1509 chip->adc->adc_channels[channel].fast_avg_setup;
1510 chip->adc->amux_prop->mode_sel =
1511 ADC_OP_MEASUREMENT_INTERVAL << QPNP_OP_MODE_SHIFT;
1512 chip->adc->amux_prop->chan_prop->low_thr = adc_tm->low_thr;
1513 chip->adc->amux_prop->chan_prop->high_thr = adc_tm->high_thr;
1514 chip->adc->amux_prop->chan_prop->tm_channel_select =
1515 adc_tm->btm_channel_num;
1516 chip->adc->amux_prop->calib_type =
1517 chip->adc->adc_channels[channel].calib_type;
1518
Prasad Malisetty358dda32018-02-20 06:14:26 +05301519 if (!chip->adc_tm_hc) {
1520 rc = qpnp_adc_tm_configure(chip, chip->adc->amux_prop);
1521 if (rc) {
1522 pr_err("adc-tm configure failed with %d\n", rc);
1523 goto fail;
1524 }
1525 } else {
1526 rc = qpnp_adc_tm_hc_configure(chip,
1527 chip->adc->amux_prop);
1528 if (rc) {
1529 pr_err("hc configure failed with %d\n", rc);
1530 goto fail;
1531 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001532 }
1533 } else if (mode == THERMAL_DEVICE_DISABLED) {
1534 sensor_mask = 1 << adc_tm->sensor_num;
Prasad Malisetty358dda32018-02-20 06:14:26 +05301535 if (!chip->adc_tm_hc) {
1536 mode_ctl = ADC_OP_NORMAL_MODE << QPNP_OP_MODE_SHIFT;
1537 rc = qpnp_adc_tm_mode_select(chip, mode_ctl);
1538 if (rc < 0) {
1539 pr_err("adc-tm single mode select failed\n");
1540 goto fail;
1541 }
1542 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001543
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001544 /* Disable bank */
1545 rc = qpnp_adc_tm_disable(chip);
1546 if (rc < 0) {
1547 pr_err("adc-tm disable failed\n");
1548 goto fail;
1549 }
1550
Prasad Malisetty358dda32018-02-20 06:14:26 +05301551 if (!chip->adc_tm_hc) {
1552 /* Check if a conversion is in progress */
1553 rc = qpnp_adc_tm_req_sts_check(chip);
1554 if (rc < 0) {
1555 pr_err("adc-tm req_sts check failed\n");
1556 goto fail;
1557 }
1558 rc = qpnp_adc_tm_reg_update(chip,
1559 QPNP_ADC_TM_MULTI_MEAS_EN,
1560 sensor_mask, false);
1561 if (rc < 0) {
1562 pr_err("multi measurement update failed\n");
1563 goto fail;
1564 }
1565 } else {
1566 rc = qpnp_adc_tm_reg_update(chip,
1567 QPNP_BTM_Mn_EN(btm_chan_idx),
1568 QPNP_BTM_Mn_MEAS_EN, false);
1569 if (rc < 0) {
1570 pr_err("multi measurement disable failed\n");
1571 goto fail;
1572 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001573 }
1574
1575 rc = qpnp_adc_tm_enable_if_channel_meas(chip);
1576 if (rc < 0) {
1577 pr_err("re-enabling measurement failed\n");
1578 goto fail;
1579 }
1580 }
1581
1582 adc_tm->mode = mode;
1583
1584fail:
1585 mutex_unlock(&chip->adc->adc_lock);
1586
1587 return 0;
1588}
1589
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001590static int qpnp_adc_tm_activate_trip_type(struct qpnp_adc_tm_sensor *adc_tm,
1591 int trip, enum thermal_trip_activation_mode mode)
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001592{
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001593 struct qpnp_adc_tm_chip *chip = adc_tm->chip;
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001594 int rc = 0, sensor_mask = 0;
Prasad Malisetty358dda32018-02-20 06:14:26 +05301595 u8 thr_int_en = 0;
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001596 bool state = false;
1597 uint32_t btm_chan_idx = 0, btm_chan = 0;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001598
1599 if (qpnp_adc_tm_is_valid(chip))
1600 return -ENODEV;
1601
1602 if (qpnp_adc_tm_check_revision(chip, adc_tm->btm_channel_num))
1603 return -EINVAL;
1604
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001605 if (mode == THERMAL_TRIP_ACTIVATION_ENABLED)
1606 state = true;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001607
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001608 sensor_mask = 1 << adc_tm->sensor_num;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001609
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001610 pr_debug("Sensor number:%x with state:%d\n",
1611 adc_tm->sensor_num, state);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001612
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001613 btm_chan = adc_tm->btm_channel_num;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001614 rc = qpnp_adc_tm_get_btm_idx(chip, btm_chan, &btm_chan_idx);
1615 if (rc < 0) {
1616 pr_err("Invalid btm channel idx\n");
1617 return rc;
1618 }
1619
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001620 switch (trip) {
1621 case ADC_TM_TRIP_HIGH_WARM:
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001622 /* low_thr (lower voltage) for higher temp */
Prasad Malisetty358dda32018-02-20 06:14:26 +05301623 thr_int_en = adc_tm_data[btm_chan_idx].low_thr_int_chan_en;
1624 if (!chip->adc_tm_hc)
1625 rc = qpnp_adc_tm_reg_update(chip,
1626 QPNP_ADC_TM_LOW_THR_INT_EN,
1627 sensor_mask, state);
1628 else
1629 rc = qpnp_adc_tm_reg_update(chip,
1630 QPNP_BTM_Mn_EN(btm_chan_idx),
1631 QPNP_BTM_Mn_LOW_THR_INT_EN, state);
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001632 if (rc)
1633 pr_err("channel:%x failed\n", btm_chan);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001634 break;
1635 case ADC_TM_TRIP_LOW_COOL:
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001636 /* high_thr (higher voltage) for cooler temp */
Prasad Malisetty358dda32018-02-20 06:14:26 +05301637 thr_int_en = adc_tm_data[btm_chan_idx].high_thr_int_chan_en;
1638 if (!chip->adc_tm_hc)
1639 rc = qpnp_adc_tm_reg_update(chip,
1640 QPNP_ADC_TM_HIGH_THR_INT_EN,
1641 sensor_mask, state);
1642 else
1643 rc = qpnp_adc_tm_reg_update(chip,
1644 QPNP_BTM_Mn_EN(btm_chan_idx),
1645 QPNP_BTM_Mn_HIGH_THR_INT_EN, state);
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001646 if (rc)
1647 pr_err("channel:%x failed\n", btm_chan);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001648 break;
1649 default:
1650 return -EINVAL;
1651 }
1652
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001653 return rc;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001654}
1655
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001656static int qpnp_adc_tm_set_trip_temp(void *data, int low_temp, int high_temp)
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001657{
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001658 struct qpnp_adc_tm_sensor *adc_tm = data;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001659 struct qpnp_adc_tm_chip *chip = adc_tm->chip;
1660 struct qpnp_adc_tm_config tm_config;
1661 u8 trip_cool_thr0, trip_cool_thr1, trip_warm_thr0, trip_warm_thr1;
1662 uint16_t reg_low_thr_lsb, reg_low_thr_msb;
1663 uint16_t reg_high_thr_lsb, reg_high_thr_msb;
1664 int rc = 0;
1665 uint32_t btm_chan = 0, btm_chan_idx = 0;
1666
1667 if (qpnp_adc_tm_is_valid(chip))
1668 return -ENODEV;
1669
1670 if (qpnp_adc_tm_check_revision(chip, adc_tm->btm_channel_num))
1671 return -EINVAL;
1672
1673 tm_config.channel = adc_tm->vadc_channel_num;
1674 tm_config.high_thr_temp = tm_config.low_thr_temp = 0;
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001675 if (high_temp != INT_MAX)
1676 tm_config.high_thr_temp = high_temp;
1677 if (low_temp != INT_MIN)
1678 tm_config.low_thr_temp = low_temp;
1679
1680 if ((high_temp == INT_MAX) && (low_temp == INT_MIN)) {
1681 pr_err("No trips to set\n");
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001682 return -EINVAL;
1683 }
1684
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001685 pr_debug("requested a high - %d and low - %d\n",
1686 tm_config.high_thr_temp, tm_config.low_thr_temp);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001687 rc = qpnp_adc_tm_scale_therm_voltage_pu2(chip->vadc_dev,
1688 chip->adc->adc_prop, &tm_config);
1689 if (rc < 0) {
1690 pr_err("Failed to lookup the adc-tm thresholds\n");
1691 return rc;
1692 }
1693
1694 trip_warm_thr0 = ((tm_config.low_thr_voltage << 24) >> 24);
1695 trip_warm_thr1 = ((tm_config.low_thr_voltage << 16) >> 24);
1696 trip_cool_thr0 = ((tm_config.high_thr_voltage << 24) >> 24);
1697 trip_cool_thr1 = ((tm_config.high_thr_voltage << 16) >> 24);
1698
1699 pr_debug("low_thr:0x%llx, high_thr:0x%llx\n", tm_config.low_thr_voltage,
1700 tm_config.high_thr_voltage);
1701
1702 btm_chan = adc_tm->btm_channel_num;
1703 rc = qpnp_adc_tm_get_btm_idx(chip, btm_chan, &btm_chan_idx);
1704 if (rc < 0) {
1705 pr_err("Invalid btm channel idx\n");
1706 return rc;
1707 }
1708
Prasad Malisetty358dda32018-02-20 06:14:26 +05301709 if (!chip->adc_tm_hc) {
1710 reg_low_thr_lsb = adc_tm_data[btm_chan_idx].low_thr_lsb_addr;
1711 reg_low_thr_msb = adc_tm_data[btm_chan_idx].low_thr_msb_addr;
1712 reg_high_thr_lsb = adc_tm_data[btm_chan_idx].high_thr_lsb_addr;
1713 reg_high_thr_msb = adc_tm_data[btm_chan_idx].high_thr_msb_addr;
1714 } else {
1715 reg_low_thr_lsb = QPNP_BTM_Mn_LOW_THR0(btm_chan_idx);
1716 reg_low_thr_msb = QPNP_BTM_Mn_LOW_THR1(btm_chan_idx);
1717 reg_high_thr_lsb = QPNP_BTM_Mn_HIGH_THR0(btm_chan_idx);
1718 reg_high_thr_msb = QPNP_BTM_Mn_HIGH_THR1(btm_chan_idx);
1719 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001720
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001721 if (high_temp != INT_MAX) {
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001722 rc = qpnp_adc_tm_write_reg(chip, reg_low_thr_lsb,
1723 trip_cool_thr0, 1);
1724 if (rc) {
1725 pr_err("adc-tm_tm read threshold err\n");
1726 return rc;
1727 }
1728
1729 rc = qpnp_adc_tm_write_reg(chip, reg_low_thr_msb,
1730 trip_cool_thr1, 1);
1731 if (rc) {
1732 pr_err("adc-tm_tm read threshold err\n");
1733 return rc;
1734 }
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001735 adc_tm->low_thr = tm_config.high_thr_voltage;
1736
1737 rc = qpnp_adc_tm_activate_trip_type(adc_tm,
1738 ADC_TM_TRIP_HIGH_WARM,
1739 THERMAL_TRIP_ACTIVATION_ENABLED);
1740 if (rc) {
1741 pr_err("adc-tm warm activation failed\n");
1742 return rc;
1743 }
1744 } else {
1745 rc = qpnp_adc_tm_activate_trip_type(adc_tm,
1746 ADC_TM_TRIP_HIGH_WARM,
1747 THERMAL_TRIP_ACTIVATION_DISABLED);
1748 if (rc) {
1749 pr_err("adc-tm warm deactivation failed\n");
1750 return rc;
1751 }
1752 }
1753
1754 if (low_temp != INT_MIN) {
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001755 rc = qpnp_adc_tm_write_reg(chip, reg_high_thr_lsb,
1756 trip_warm_thr0, 1);
1757 if (rc) {
1758 pr_err("adc-tm_tm read threshold err\n");
1759 return rc;
1760 }
1761
1762 rc = qpnp_adc_tm_write_reg(chip, reg_high_thr_msb,
1763 trip_warm_thr1, 1);
1764 if (rc) {
1765 pr_err("adc-tm_tm read threshold err\n");
1766 return rc;
1767 }
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001768 adc_tm->high_thr = tm_config.low_thr_voltage;
1769
1770 rc = qpnp_adc_tm_activate_trip_type(adc_tm,
1771 ADC_TM_TRIP_LOW_COOL,
1772 THERMAL_TRIP_ACTIVATION_ENABLED);
1773 if (rc) {
1774 pr_err("adc-tm cool activation failed\n");
1775 return rc;
1776 }
1777 } else {
1778 rc = qpnp_adc_tm_activate_trip_type(adc_tm,
1779 ADC_TM_TRIP_LOW_COOL,
1780 THERMAL_TRIP_ACTIVATION_DISABLED);
1781 if (rc) {
1782 pr_err("adc-tm cool deactivation failed\n");
1783 return rc;
1784 }
1785 }
1786
1787 if ((high_temp != INT_MAX) || (low_temp != INT_MIN)) {
1788 rc = qpnp_adc_tm_set_mode(adc_tm, THERMAL_DEVICE_ENABLED);
1789 if (rc) {
1790 pr_err("sensor enabled failed\n");
1791 return rc;
1792 }
1793 } else {
1794 rc = qpnp_adc_tm_set_mode(adc_tm, THERMAL_DEVICE_DISABLED);
1795 if (rc) {
1796 pr_err("sensor disable failed\n");
1797 return rc;
1798 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001799 }
1800
1801 return 0;
1802}
1803
1804static void notify_battery_therm(struct qpnp_adc_tm_sensor *adc_tm)
1805{
1806 struct qpnp_adc_thr_client_info *client_info = NULL;
1807
1808 list_for_each_entry(client_info,
1809 &adc_tm->thr_list, list) {
1810 /* Batt therm's warm temperature translates to low voltage */
1811 if (client_info->notify_low_thr) {
1812 /* HIGH_STATE = WARM_TEMP for battery client */
1813 client_info->btm_param->threshold_notification(
1814 ADC_TM_WARM_STATE, client_info->btm_param->btm_ctx);
1815 client_info->notify_low_thr = false;
1816 }
1817
1818 /* Batt therm's cool temperature translates to high voltage */
1819 if (client_info->notify_high_thr) {
1820 /* LOW_STATE = COOL_TEMP for battery client */
1821 client_info->btm_param->threshold_notification(
1822 ADC_TM_COOL_STATE, client_info->btm_param->btm_ctx);
1823 client_info->notify_high_thr = false;
1824 }
1825 }
1826}
1827
1828static void notify_clients(struct qpnp_adc_tm_sensor *adc_tm)
1829{
1830 struct qpnp_adc_thr_client_info *client_info = NULL;
1831
1832 list_for_each_entry(client_info,
1833 &adc_tm->thr_list, list) {
1834 /* For non batt therm clients */
1835 if (client_info->notify_low_thr) {
1836 if (client_info->btm_param->threshold_notification
1837 != NULL) {
1838 pr_debug("notify kernel with low state\n");
1839 client_info->btm_param->threshold_notification(
1840 ADC_TM_LOW_STATE,
1841 client_info->btm_param->btm_ctx);
1842 client_info->notify_low_thr = false;
1843 }
1844 }
1845
1846 if (client_info->notify_high_thr) {
1847 if (client_info->btm_param->threshold_notification
1848 != NULL) {
1849 pr_debug("notify kernel with high state\n");
1850 client_info->btm_param->threshold_notification(
1851 ADC_TM_HIGH_STATE,
1852 client_info->btm_param->btm_ctx);
1853 client_info->notify_high_thr = false;
1854 }
1855 }
1856 }
1857}
1858
1859static void notify_adc_tm_fn(struct work_struct *work)
1860{
1861 struct qpnp_adc_tm_sensor *adc_tm = container_of(work,
1862 struct qpnp_adc_tm_sensor, work);
1863 struct qpnp_adc_tm_chip *chip = adc_tm->chip;
1864
1865 if (adc_tm->thermal_node) {
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001866 pr_debug("notifying uspace client\n");
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07001867 of_thermal_handle_trip(adc_tm->tz_dev);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08001868 } else {
1869 if (adc_tm->scale_type == SCALE_RBATT_THERM)
1870 notify_battery_therm(adc_tm);
1871 else
1872 notify_clients(adc_tm);
1873 }
1874
1875 atomic_dec(&chip->wq_cnt);
1876}
1877
Prasad Malisetty358dda32018-02-20 06:14:26 +05301878static int qpnp_adc_tm_recalib_request_check(struct qpnp_adc_tm_chip *chip,
1879 int sensor_num, u8 status_high, u8 *notify_check)
1880{
1881 int rc = 0;
1882 u8 sensor_mask = 0, mode_ctl = 0;
1883 int32_t old_thr = 0, new_thr = 0;
1884 uint32_t channel, btm_chan_num, scale_type;
1885 struct qpnp_vadc_result result;
1886 struct qpnp_adc_thr_client_info *client_info = NULL;
1887 struct list_head *thr_list;
1888 bool status = false;
1889
1890 if (!chip->adc_tm_recalib_check) {
1891 *notify_check = 1;
1892 return rc;
1893 }
1894
1895 list_for_each(thr_list, &chip->sensor[sensor_num].thr_list) {
1896 client_info = list_entry(thr_list,
1897 struct qpnp_adc_thr_client_info, list);
1898 channel = client_info->btm_param->channel;
1899 btm_chan_num = chip->sensor[sensor_num].btm_channel_num;
1900 sensor_mask = 1 << sensor_num;
1901
1902 rc = qpnp_vadc_read(chip->vadc_dev, channel, &result);
1903 if (rc < 0) {
1904 pr_err("failure to read vadc channel=%d\n",
1905 client_info->btm_param->channel);
1906 goto fail;
1907 }
1908 new_thr = result.physical;
1909
1910 if (status_high)
1911 old_thr = client_info->btm_param->high_thr;
1912 else
1913 old_thr = client_info->btm_param->low_thr;
1914
1915 if (new_thr > old_thr)
1916 status = (status_high) ? true : false;
1917 else
1918 status = (status_high) ? false : true;
1919
1920 pr_debug(
1921 "recalib:sen=%d, new_thr=%d, new_thr_adc_code=0x%x, old_thr=%d status=%d valid_status=%d\n",
1922 sensor_num, new_thr, result.adc_code,
1923 old_thr, status_high, status);
1924
1925 rc = qpnp_adc_tm_read_thr_value(chip, btm_chan_num);
1926 if (rc < 0) {
1927 pr_err("adc-tm thresholds read failed\n");
1928 goto fail;
1929 }
1930
1931 if (status) {
1932 *notify_check = 1;
1933 pr_debug("Client can be notify\n");
1934 return rc;
1935 }
1936
1937 pr_debug("Client can not be notify, restart measurement\n");
1938 /* Set measurement in single measurement mode */
1939 mode_ctl = ADC_OP_NORMAL_MODE << QPNP_OP_MODE_SHIFT;
1940 rc = qpnp_adc_tm_mode_select(chip, mode_ctl);
1941 if (rc < 0) {
1942 pr_err("adc-tm single mode select failed\n");
1943 goto fail;
1944 }
1945
1946 /* Disable bank */
1947 rc = qpnp_adc_tm_disable(chip);
1948 if (rc < 0) {
1949 pr_err("adc-tm disable failed\n");
1950 goto fail;
1951 }
1952
1953 /* Check if a conversion is in progress */
1954 rc = qpnp_adc_tm_req_sts_check(chip);
1955 if (rc < 0) {
1956 pr_err("adc-tm req_sts check failed\n");
1957 goto fail;
1958 }
1959
1960 rc = qpnp_adc_tm_reg_update(chip, QPNP_ADC_TM_LOW_THR_INT_EN,
1961 sensor_mask, false);
1962 if (rc < 0) {
1963 pr_err("low threshold int write failed\n");
1964 goto fail;
1965 }
1966
1967 rc = qpnp_adc_tm_reg_update(chip, QPNP_ADC_TM_HIGH_THR_INT_EN,
1968 sensor_mask, false);
1969 if (rc < 0) {
1970 pr_err("high threshold int enable failed\n");
1971 goto fail;
1972 }
1973
1974 rc = qpnp_adc_tm_reg_update(chip, QPNP_ADC_TM_MULTI_MEAS_EN,
1975 sensor_mask, false);
1976 if (rc < 0) {
1977 pr_err("multi measurement en failed\n");
1978 goto fail;
1979 }
1980
1981 /* restart measurement */
1982 scale_type = chip->sensor[sensor_num].scale_type;
1983 chip->adc->amux_prop->amux_channel = channel;
1984 chip->adc->amux_prop->decimation =
1985 chip->adc->adc_channels[sensor_num].adc_decimation;
1986 chip->adc->amux_prop->hw_settle_time =
1987 chip->adc->adc_channels[sensor_num].hw_settle_time;
1988 chip->adc->amux_prop->fast_avg_setup =
1989 chip->adc->adc_channels[sensor_num].fast_avg_setup;
1990 chip->adc->amux_prop->mode_sel =
1991 ADC_OP_MEASUREMENT_INTERVAL << QPNP_OP_MODE_SHIFT;
1992 adc_tm_rscale_fn[scale_type].chan(chip->vadc_dev,
1993 client_info->btm_param,
1994 &chip->adc->amux_prop->chan_prop->low_thr,
1995 &chip->adc->amux_prop->chan_prop->high_thr);
1996 qpnp_adc_tm_add_to_list(chip, sensor_num,
1997 client_info->btm_param,
1998 chip->adc->amux_prop->chan_prop);
1999 chip->adc->amux_prop->chan_prop->tm_channel_select =
2000 chip->sensor[sensor_num].btm_channel_num;
2001 chip->adc->amux_prop->chan_prop->state_request =
2002 client_info->btm_param->state_request;
2003
2004 rc = qpnp_adc_tm_configure(chip, chip->adc->amux_prop);
2005 if (rc) {
2006 pr_err("adc-tm configure failed with %d\n", rc);
2007 goto fail;
2008 }
2009 *notify_check = 0;
2010 pr_debug("BTM channel reconfigured for measuremnt\n");
2011 }
2012fail:
2013 return rc;
2014}
2015
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002016static int qpnp_adc_tm_disable_rearm_high_thresholds(
2017 struct qpnp_adc_tm_chip *chip, int sensor_num)
2018{
2019
2020 struct qpnp_adc_thr_client_info *client_info = NULL;
2021 struct list_head *thr_list;
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002022 uint32_t btm_chan_num = 0, btm_chan_idx = 0;
Prasad Malisetty358dda32018-02-20 06:14:26 +05302023 u8 sensor_mask = 0, notify_check = 0;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002024 int rc = 0;
2025
2026 btm_chan_num = chip->sensor[sensor_num].btm_channel_num;
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002027 rc = qpnp_adc_tm_get_btm_idx(chip, btm_chan_num, &btm_chan_idx);
2028 if (rc < 0) {
2029 pr_err("Invalid btm channel idx\n");
2030 return rc;
2031 }
2032
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002033 pr_debug("high:sen:%d, hs:0x%x, ls:0x%x, meas_en:0x%x\n",
2034 sensor_num, chip->th_info.adc_tm_high_enable,
2035 chip->th_info.adc_tm_low_enable,
2036 chip->th_info.qpnp_adc_tm_meas_en);
2037 if (!chip->sensor[sensor_num].thermal_node) {
2038 /*
2039 * For non thermal registered clients such as usb_id,
2040 * vbatt, pmic_therm
2041 */
2042 sensor_mask = 1 << sensor_num;
2043 pr_debug("non thermal node - mask:%x\n", sensor_mask);
Prasad Malisetty358dda32018-02-20 06:14:26 +05302044 if (!chip->adc_tm_hc) {
2045 rc = qpnp_adc_tm_recalib_request_check(chip,
2046 sensor_num, true, &notify_check);
2047 if (rc < 0 || !notify_check) {
2048 pr_debug("Calib recheck re-armed rc=%d\n", rc);
2049 chip->th_info.adc_tm_high_enable = 0;
2050 return rc;
2051 }
2052 } else {
2053 rc = qpnp_adc_tm_reg_update(chip,
2054 QPNP_BTM_Mn_EN(btm_chan_idx),
2055 QPNP_BTM_Mn_HIGH_THR_INT_EN, false);
2056 if (rc < 0) {
2057 pr_err("high threshold int update failed\n");
2058 return rc;
2059 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002060 }
Prasad Malisetty358dda32018-02-20 06:14:26 +05302061 } else {
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002062 /*
2063 * Uses the thermal sysfs registered device to disable
2064 * the corresponding high voltage threshold which
2065 * is triggered by low temp
2066 */
2067 sensor_mask = 1 << sensor_num;
2068 pr_debug("thermal node with mask:%x\n", sensor_mask);
2069 rc = qpnp_adc_tm_activate_trip_type(
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002070 &chip->sensor[sensor_num],
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002071 ADC_TM_TRIP_LOW_COOL,
2072 THERMAL_TRIP_ACTIVATION_DISABLED);
2073 if (rc < 0) {
2074 pr_err("notify error:%d\n", sensor_num);
2075 return rc;
2076 }
2077 }
2078 list_for_each(thr_list, &chip->sensor[sensor_num].thr_list) {
2079 client_info = list_entry(thr_list,
2080 struct qpnp_adc_thr_client_info, list);
2081 if (client_info->high_thr_set) {
2082 client_info->high_thr_set = false;
2083 client_info->notify_high_thr = true;
2084 if (client_info->state_req_copy ==
2085 ADC_TM_HIGH_LOW_THR_ENABLE)
2086 client_info->state_req_copy =
2087 ADC_TM_LOW_THR_ENABLE;
2088 else
2089 client_info->state_req_copy =
2090 ADC_TM_HIGH_THR_DISABLE;
2091 }
2092 }
2093 qpnp_adc_tm_manage_thresholds(chip, sensor_num, btm_chan_num);
2094
Prasad Malisetty358dda32018-02-20 06:14:26 +05302095 if (!chip->adc_tm_hc) {
2096 rc = qpnp_adc_tm_reg_update(chip,
2097 QPNP_ADC_TM_MULTI_MEAS_EN,
2098 sensor_mask, false);
2099 if (rc < 0) {
2100 pr_err("multi meas disable failed\n");
2101 return rc;
2102 }
2103 } else {
2104 rc = qpnp_adc_tm_reg_update(chip,
2105 QPNP_BTM_Mn_EN(sensor_num),
2106 QPNP_BTM_Mn_MEAS_EN, false);
2107 if (rc < 0) {
2108 pr_err("multi meas disable failed\n");
2109 return rc;
2110 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002111 }
2112
2113 rc = qpnp_adc_tm_enable_if_channel_meas(chip);
2114 if (rc < 0) {
2115 pr_err("re-enabling measurement failed\n");
2116 return rc;
2117 }
2118
Siddartha Mohanadoss336fff42017-12-11 16:51:00 -08002119 if (!queue_work(chip->sensor[sensor_num].req_wq,
2120 &chip->sensor[sensor_num].work)) {
2121 /* The item is already queued, reduce the count */
2122 atomic_dec(&chip->wq_cnt);
2123 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002124
2125 return rc;
2126}
2127
2128static int qpnp_adc_tm_disable_rearm_low_thresholds(
2129 struct qpnp_adc_tm_chip *chip, int sensor_num)
2130{
2131 struct qpnp_adc_thr_client_info *client_info = NULL;
2132 struct list_head *thr_list;
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002133 uint32_t btm_chan_num = 0, btm_chan_idx = 0;
Prasad Malisetty358dda32018-02-20 06:14:26 +05302134 u8 sensor_mask = 0, notify_check = 0;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002135 int rc = 0;
2136
2137 btm_chan_num = chip->sensor[sensor_num].btm_channel_num;
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002138 rc = qpnp_adc_tm_get_btm_idx(chip, btm_chan_num, &btm_chan_idx);
2139 if (rc < 0) {
2140 pr_err("Invalid btm channel idx\n");
2141 return rc;
2142 }
2143
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002144 pr_debug("low:sen:%d, hs:0x%x, ls:0x%x, meas_en:0x%x\n",
2145 sensor_num, chip->th_info.adc_tm_high_enable,
2146 chip->th_info.adc_tm_low_enable,
2147 chip->th_info.qpnp_adc_tm_meas_en);
2148 if (!chip->sensor[sensor_num].thermal_node) {
2149 /*
2150 * For non thermal registered clients such as usb_id,
2151 * vbatt, pmic_therm
2152 */
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002153 sensor_mask = 1 << sensor_num;
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002154 pr_debug("non thermal node - mask:%x\n", sensor_mask);
Prasad Malisetty358dda32018-02-20 06:14:26 +05302155 if (!chip->adc_tm_hc) {
2156 rc = qpnp_adc_tm_recalib_request_check(chip,
2157 sensor_num, false, &notify_check);
2158 if (rc < 0 || !notify_check) {
2159 pr_debug("Calib recheck re-armed rc=%d\n", rc);
2160 chip->th_info.adc_tm_low_enable = 0;
2161 return rc;
2162 }
2163 } else {
2164 rc = qpnp_adc_tm_reg_update(chip,
2165 QPNP_BTM_Mn_EN(btm_chan_idx),
2166 QPNP_BTM_Mn_LOW_THR_INT_EN, false);
2167 if (rc < 0) {
2168 pr_err("low threshold int update failed\n");
2169 return rc;
2170 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002171 }
2172 } else {
2173 /*
2174 * Uses the thermal sysfs registered device to disable
2175 * the corresponding high voltage threshold which
2176 * is triggered by low temp
2177 */
2178 sensor_mask = 1 << sensor_num;
2179 pr_debug("thermal node with mask:%x\n", sensor_mask);
2180 rc = qpnp_adc_tm_activate_trip_type(
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002181 &chip->sensor[sensor_num],
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002182 ADC_TM_TRIP_HIGH_WARM,
2183 THERMAL_TRIP_ACTIVATION_DISABLED);
2184 if (rc < 0) {
2185 pr_err("notify error:%d\n", sensor_num);
2186 return rc;
2187 }
2188 }
2189 list_for_each(thr_list, &chip->sensor[sensor_num].thr_list) {
2190 client_info = list_entry(thr_list,
2191 struct qpnp_adc_thr_client_info, list);
2192 if (client_info->low_thr_set) {
2193 client_info->low_thr_set = false;
2194 client_info->notify_low_thr = true;
2195 if (client_info->state_req_copy ==
2196 ADC_TM_HIGH_LOW_THR_ENABLE)
2197 client_info->state_req_copy =
2198 ADC_TM_HIGH_THR_ENABLE;
2199 else
2200 client_info->state_req_copy =
2201 ADC_TM_LOW_THR_DISABLE;
2202 }
2203 }
2204 qpnp_adc_tm_manage_thresholds(chip, sensor_num, btm_chan_num);
2205
Prasad Malisetty358dda32018-02-20 06:14:26 +05302206 if (!chip->adc_tm_hc) {
2207 rc = qpnp_adc_tm_reg_update(chip,
2208 QPNP_ADC_TM_MULTI_MEAS_EN,
2209 sensor_mask, false);
2210 if (rc < 0) {
2211 pr_err("multi meas disable failed\n");
2212 return rc;
2213 }
2214 } else {
2215 rc = qpnp_adc_tm_reg_update(chip,
2216 QPNP_BTM_Mn_EN(sensor_num),
2217 QPNP_BTM_Mn_MEAS_EN, false);
2218 if (rc < 0) {
2219 pr_err("multi meas disable failed\n");
2220 return rc;
2221 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002222 }
2223
2224 rc = qpnp_adc_tm_enable_if_channel_meas(chip);
2225 if (rc < 0) {
2226 pr_err("re-enabling measurement failed\n");
2227 return rc;
2228 }
2229
Siddartha Mohanadoss336fff42017-12-11 16:51:00 -08002230 if (!queue_work(chip->sensor[sensor_num].req_wq,
2231 &chip->sensor[sensor_num].work)) {
2232 /* The item is already queued, reduce the count */
2233 atomic_dec(&chip->wq_cnt);
2234 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002235
2236 return rc;
2237}
2238
2239static int qpnp_adc_tm_read_status(struct qpnp_adc_tm_chip *chip)
2240{
2241 int rc = 0, sensor_num = 0;
2242
2243 if (qpnp_adc_tm_is_valid(chip))
2244 return -ENODEV;
2245
2246 pr_debug("%s\n", __func__);
2247
2248 mutex_lock(&chip->adc->adc_lock);
2249
Prasad Malisetty358dda32018-02-20 06:14:26 +05302250 if (!chip->adc_tm_hc) {
2251 rc = qpnp_adc_tm_req_sts_check(chip);
2252 if (rc) {
2253 pr_err("adc-tm-tm req sts check failed with %d\n", rc);
2254 goto fail;
2255 }
2256 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002257 while (sensor_num < chip->max_channels_available) {
2258 if (chip->sensor[sensor_num].high_thr_triggered) {
2259 rc = qpnp_adc_tm_disable_rearm_high_thresholds(
2260 chip, sensor_num);
2261 if (rc) {
2262 pr_err("rearm threshold failed\n");
2263 goto fail;
2264 }
2265 chip->sensor[sensor_num].high_thr_triggered = false;
2266 }
2267 sensor_num++;
2268 }
2269
2270 sensor_num = 0;
2271 while (sensor_num < chip->max_channels_available) {
2272 if (chip->sensor[sensor_num].low_thr_triggered) {
2273 rc = qpnp_adc_tm_disable_rearm_low_thresholds(
2274 chip, sensor_num);
2275 if (rc) {
2276 pr_err("rearm threshold failed\n");
2277 goto fail;
2278 }
2279 chip->sensor[sensor_num].low_thr_triggered = false;
2280 }
2281 sensor_num++;
2282 }
2283
2284fail:
2285 mutex_unlock(&chip->adc->adc_lock);
2286
2287 if (rc < 0 || (!chip->th_info.adc_tm_high_enable &&
2288 !chip->th_info.adc_tm_low_enable))
2289 atomic_dec(&chip->wq_cnt);
2290
2291 return rc;
2292}
2293
2294static void qpnp_adc_tm_high_thr_work(struct work_struct *work)
2295{
2296 struct qpnp_adc_tm_chip *chip = container_of(work,
2297 struct qpnp_adc_tm_chip, trigger_high_thr_work);
2298 int rc;
2299
2300 /* disable the vote if applicable */
2301 if (chip->adc_vote_enable && chip->adc->hkadc_ldo &&
2302 chip->adc->hkadc_ldo_ok) {
2303 qpnp_adc_disable_voltage(chip->adc);
2304 chip->adc_vote_enable = false;
2305 }
2306
2307 pr_debug("thr:0x%x\n", chip->th_info.adc_tm_high_enable);
2308
2309 rc = qpnp_adc_tm_read_status(chip);
2310 if (rc < 0)
2311 pr_err("adc-tm high thr work failed\n");
2312}
2313
Prasad Malisetty358dda32018-02-20 06:14:26 +05302314static irqreturn_t qpnp_adc_tm_high_thr_isr(int irq, void *data)
2315{
2316 struct qpnp_adc_tm_chip *chip = data;
2317 u8 mode_ctl = 0, status1 = 0, sensor_mask = 0;
2318 int rc = 0, sensor_notify_num = 0, i = 0, sensor_num = 0;
2319
2320 mode_ctl = ADC_OP_NORMAL_MODE << QPNP_OP_MODE_SHIFT;
2321 /* Set measurement in single measurement mode */
2322 qpnp_adc_tm_mode_select(chip, mode_ctl);
2323
2324 qpnp_adc_tm_disable(chip);
2325
2326 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_STATUS1, &status1, 1);
2327 if (rc) {
2328 pr_err("adc-tm read status1 failed\n");
2329 return IRQ_HANDLED;
2330 }
2331
2332 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_STATUS_HIGH,
2333 &chip->th_info.status_high, 1);
2334 if (rc) {
2335 pr_err("adc-tm-tm read status high failed with %d\n", rc);
2336 return IRQ_HANDLED;
2337 }
2338
2339 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_HIGH_THR_INT_EN,
2340 &chip->th_info.adc_tm_high_thr_set, 1);
2341 if (rc) {
2342 pr_err("adc-tm-tm read high thr failed with %d\n", rc);
2343 return IRQ_HANDLED;
2344 }
2345
2346 /* Check which interrupt threshold is lower and measure against the
2347 * enabled channel
2348 */
2349 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_MULTI_MEAS_EN,
2350 &chip->th_info.qpnp_adc_tm_meas_en, 1);
2351 if (rc) {
2352 pr_err("adc-tm-tm read status high failed with %d\n", rc);
2353 return IRQ_HANDLED;
2354 }
2355
2356 chip->th_info.adc_tm_high_enable = chip->th_info.qpnp_adc_tm_meas_en &
2357 chip->th_info.status_high;
2358 chip->th_info.adc_tm_high_enable &= chip->th_info.adc_tm_high_thr_set;
2359
2360 sensor_notify_num = chip->th_info.adc_tm_high_enable;
2361 while (i < chip->max_channels_available) {
2362 if ((sensor_notify_num & 0x1) == 1)
2363 sensor_num = i;
2364 sensor_notify_num >>= 1;
2365 i++;
2366 }
2367
2368 if (!chip->sensor[sensor_num].thermal_node) {
2369 sensor_mask = 1 << sensor_num;
2370 rc = qpnp_adc_tm_reg_update(chip,
2371 QPNP_ADC_TM_HIGH_THR_INT_EN,
2372 sensor_mask, false);
2373 if (rc < 0) {
2374 pr_err("high threshold int read failed\n");
2375 return IRQ_HANDLED;
2376 }
2377 } else {
2378 /*
2379 * Uses the thermal sysfs registered device to disable
2380 * the corresponding high voltage threshold which
2381 * is triggered by low temp
2382 */
2383 pr_debug("thermal node with mask:%x\n", sensor_mask);
2384 rc = qpnp_adc_tm_activate_trip_type(
2385 &chip->sensor[sensor_num],
2386 ADC_TM_TRIP_LOW_COOL,
2387 THERMAL_TRIP_ACTIVATION_DISABLED);
2388 if (rc < 0) {
2389 pr_err("notify error:%d\n", sensor_num);
2390 return IRQ_HANDLED;
2391 }
2392 }
2393
2394 atomic_inc(&chip->wq_cnt);
2395 queue_work(chip->high_thr_wq, &chip->trigger_high_thr_work);
2396
2397 return IRQ_HANDLED;
2398}
2399
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002400static void qpnp_adc_tm_low_thr_work(struct work_struct *work)
2401{
2402 struct qpnp_adc_tm_chip *chip = container_of(work,
2403 struct qpnp_adc_tm_chip, trigger_low_thr_work);
2404 int rc;
2405
2406 /* disable the vote if applicable */
2407 if (chip->adc_vote_enable && chip->adc->hkadc_ldo &&
2408 chip->adc->hkadc_ldo_ok) {
2409 qpnp_adc_disable_voltage(chip->adc);
2410 chip->adc_vote_enable = false;
2411 }
2412
2413 pr_debug("thr:0x%x\n", chip->th_info.adc_tm_low_enable);
2414
2415 rc = qpnp_adc_tm_read_status(chip);
2416 if (rc < 0)
2417 pr_err("adc-tm low thr work failed\n");
2418}
2419
Prasad Malisetty358dda32018-02-20 06:14:26 +05302420static irqreturn_t qpnp_adc_tm_low_thr_isr(int irq, void *data)
2421{
2422 struct qpnp_adc_tm_chip *chip = data;
2423 u8 mode_ctl = 0, status1 = 0, sensor_mask = 0;
2424 int rc = 0, sensor_notify_num = 0, i = 0, sensor_num = 0;
2425
2426 mode_ctl = ADC_OP_NORMAL_MODE << QPNP_OP_MODE_SHIFT;
2427 /* Set measurement in single measurement mode */
2428 qpnp_adc_tm_mode_select(chip, mode_ctl);
2429
2430 qpnp_adc_tm_disable(chip);
2431
2432 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_STATUS1, &status1, 1);
2433 if (rc) {
2434 pr_err("adc-tm read status1 failed\n");
2435 return IRQ_HANDLED;
2436 }
2437
2438 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_STATUS_LOW,
2439 &chip->th_info.status_low, 1);
2440 if (rc) {
2441 pr_err("adc-tm-tm read status low failed with %d\n", rc);
2442 return IRQ_HANDLED;
2443 }
2444
2445 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_LOW_THR_INT_EN,
2446 &chip->th_info.adc_tm_low_thr_set, 1);
2447 if (rc) {
2448 pr_err("adc-tm-tm read low thr failed with %d\n", rc);
2449 return IRQ_HANDLED;
2450 }
2451
2452 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_MULTI_MEAS_EN,
2453 &chip->th_info.qpnp_adc_tm_meas_en, 1);
2454 if (rc) {
2455 pr_err("adc-tm-tm read status high failed with %d\n", rc);
2456 return IRQ_HANDLED;
2457 }
2458
2459 chip->th_info.adc_tm_low_enable = chip->th_info.qpnp_adc_tm_meas_en &
2460 chip->th_info.status_low;
2461 chip->th_info.adc_tm_low_enable &= chip->th_info.adc_tm_low_thr_set;
2462
2463 sensor_notify_num = chip->th_info.adc_tm_low_enable;
2464 while (i < chip->max_channels_available) {
2465 if ((sensor_notify_num & 0x1) == 1)
2466 sensor_num = i;
2467 sensor_notify_num >>= 1;
2468 i++;
2469 }
2470
2471 if (!chip->sensor[sensor_num].thermal_node) {
2472 sensor_mask = 1 << sensor_num;
2473 rc = qpnp_adc_tm_reg_update(chip,
2474 QPNP_ADC_TM_LOW_THR_INT_EN,
2475 sensor_mask, false);
2476 if (rc < 0) {
2477 pr_err("low threshold int read failed\n");
2478 return IRQ_HANDLED;
2479 }
2480 } else {
2481 /*
2482 * Uses the thermal sysfs registered device to disable
2483 * the corresponding low voltage threshold which
2484 * is triggered by high temp
2485 */
2486 pr_debug("thermal node with mask:%x\n", sensor_mask);
2487 rc = qpnp_adc_tm_activate_trip_type(
2488 &chip->sensor[sensor_num],
2489 ADC_TM_TRIP_HIGH_WARM,
2490 THERMAL_TRIP_ACTIVATION_DISABLED);
2491 if (rc < 0) {
2492 pr_err("notify error:%d\n", sensor_num);
2493 return IRQ_HANDLED;
2494 }
2495 }
2496
2497 atomic_inc(&chip->wq_cnt);
2498 queue_work(chip->low_thr_wq, &chip->trigger_low_thr_work);
2499
2500 return IRQ_HANDLED;
2501}
2502
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002503static int qpnp_adc_tm_rc_check_sensor_trip(struct qpnp_adc_tm_chip *chip,
2504 u8 status_low, u8 status_high, int i,
2505 int *sensor_low_notify_num, int *sensor_high_notify_num)
2506{
2507 int rc = 0;
2508 u8 ctl = 0, sensor_mask = 0;
2509
2510 if (((status_low & 0x1) == 1) || ((status_high & 0x1) == 1)) {
2511 rc = qpnp_adc_tm_read_reg(chip,
2512 QPNP_BTM_Mn_EN(i), &ctl, 1);
2513 if (rc) {
2514 pr_err("ctl read failed with %d\n", rc);
2515 return IRQ_HANDLED;
2516 }
2517
2518 if ((status_low & 0x1) && (ctl & QPNP_BTM_Mn_MEAS_EN)
2519 && (ctl & QPNP_BTM_Mn_LOW_THR_INT_EN)) {
2520 /* Mask the corresponding low threshold interrupt en */
2521 if (!chip->sensor[i].thermal_node) {
2522 rc = qpnp_adc_tm_reg_update(chip,
2523 QPNP_BTM_Mn_EN(i),
2524 QPNP_BTM_Mn_LOW_THR_INT_EN, false);
2525 if (rc < 0) {
2526 pr_err("low thr_int en failed\n");
2527 return IRQ_HANDLED;
2528 }
2529 } else {
2530 /*
2531 * Uses the thermal sysfs registered device to disable
2532 * the corresponding low voltage threshold which
2533 * is triggered by high temp
2534 */
2535 pr_debug("thermal node with mask:%x\n", sensor_mask);
2536 rc = qpnp_adc_tm_activate_trip_type(
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002537 &chip->sensor[i],
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002538 ADC_TM_TRIP_HIGH_WARM,
2539 THERMAL_TRIP_ACTIVATION_DISABLED);
2540 if (rc < 0) {
2541 pr_err("notify error:%d\n", i);
2542 return IRQ_HANDLED;
2543 }
2544 }
2545 *sensor_low_notify_num |= (status_low & 0x1);
2546 chip->sensor[i].low_thr_triggered = true;
2547 }
2548
2549 if ((status_high & 0x1) && (ctl & QPNP_BTM_Mn_MEAS_EN) &&
2550 (ctl & QPNP_BTM_Mn_HIGH_THR_INT_EN)) {
2551 /* Mask the corresponding high threshold interrupt en */
2552 if (!chip->sensor[i].thermal_node) {
2553 rc = qpnp_adc_tm_reg_update(chip,
2554 QPNP_BTM_Mn_EN(i),
2555 QPNP_BTM_Mn_HIGH_THR_INT_EN, false);
2556 if (rc < 0) {
2557 pr_err("high thr_int en failed\n");
2558 return IRQ_HANDLED;
2559 }
2560 } else {
2561 /*
2562 * Uses the thermal sysfs registered device to disable
2563 * the corresponding high voltage threshold which
2564 * is triggered by low temp
2565 */
2566 pr_debug("thermal node with mask:%x\n", i);
2567 rc = qpnp_adc_tm_activate_trip_type(
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002568 &chip->sensor[i],
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002569 ADC_TM_TRIP_LOW_COOL,
2570 THERMAL_TRIP_ACTIVATION_DISABLED);
2571 if (rc < 0) {
2572 pr_err("notify error:%d\n", i);
2573 return IRQ_HANDLED;
2574 }
2575 }
2576 *sensor_high_notify_num |= (status_high & 0x1);
2577 chip->sensor[i].high_thr_triggered = true;
2578 }
2579 }
2580
2581 return rc;
2582}
2583
2584static irqreturn_t qpnp_adc_tm_rc_thr_isr(int irq, void *data)
2585{
2586 struct qpnp_adc_tm_chip *chip = data;
2587 u8 status_low = 0, status_high = 0;
2588 int rc = 0, sensor_low_notify_num = 0, i = 0;
2589 int sensor_high_notify_num = 0;
2590
2591 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_STATUS_LOW,
2592 &status_low, 1);
2593 if (rc) {
2594 pr_err("adc-tm-tm read status low failed with %d\n", rc);
2595 return IRQ_HANDLED;
2596 }
2597
2598 if (status_low)
2599 chip->th_info.adc_tm_low_enable = status_low;
2600
2601 rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_STATUS_HIGH,
2602 &status_high, 1);
2603 if (rc) {
2604 pr_err("adc-tm-tm read status high failed with %d\n", rc);
2605 return IRQ_HANDLED;
2606 }
2607
2608 if (status_high)
2609 chip->th_info.adc_tm_high_enable = status_high;
2610
2611 while (i < chip->max_channels_available) {
2612 rc = qpnp_adc_tm_rc_check_sensor_trip(chip,
2613 status_low, status_high, i,
2614 &sensor_low_notify_num,
2615 &sensor_high_notify_num);
2616 if (rc) {
2617 pr_err("Sensor trip read failed\n");
2618 return IRQ_HANDLED;
2619 }
2620 status_low >>= 1;
2621 status_high >>= 1;
2622 i++;
2623 }
2624
2625 if (sensor_low_notify_num) {
Siddartha Mohanadoss336fff42017-12-11 16:51:00 -08002626 if (queue_work(chip->low_thr_wq, &chip->trigger_low_thr_work))
2627 atomic_inc(&chip->wq_cnt);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002628 }
2629
2630 if (sensor_high_notify_num) {
Siddartha Mohanadoss336fff42017-12-11 16:51:00 -08002631 if (queue_work(chip->high_thr_wq,
2632 &chip->trigger_high_thr_work))
2633 atomic_inc(&chip->wq_cnt);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002634 }
2635
2636 return IRQ_HANDLED;
2637}
2638
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002639static int qpnp_adc_read_temp(void *data, int *temp)
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002640{
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002641 struct qpnp_adc_tm_sensor *adc_tm_sensor = data;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002642 struct qpnp_adc_tm_chip *chip = adc_tm_sensor->chip;
2643 struct qpnp_vadc_result result;
2644 int rc = 0;
2645
2646 rc = qpnp_vadc_read(chip->vadc_dev,
2647 adc_tm_sensor->vadc_channel_num, &result);
2648 if (rc)
2649 return rc;
2650
2651 *temp = result.physical;
2652
2653 return rc;
2654}
2655
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002656static struct thermal_zone_of_device_ops qpnp_adc_tm_thermal_ops = {
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002657 .get_temp = qpnp_adc_read_temp,
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002658 .set_trips = qpnp_adc_tm_set_trip_temp,
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002659};
2660
2661int32_t qpnp_adc_tm_channel_measure(struct qpnp_adc_tm_chip *chip,
2662 struct qpnp_adc_tm_btm_param *param)
2663{
2664 uint32_t channel, amux_prescaling, dt_index = 0, scale_type = 0;
2665 int rc = 0, i = 0, version = 0;
2666 bool chan_found = false;
2667
2668 if (qpnp_adc_tm_is_valid(chip)) {
2669 pr_err("chip not valid\n");
2670 return -ENODEV;
2671 }
2672
2673 if (param->threshold_notification == NULL) {
2674 pr_debug("No notification for high/low temp??\n");
2675 return -EINVAL;
2676 }
2677
2678 mutex_lock(&chip->adc->adc_lock);
2679
2680 channel = param->channel;
2681
2682 if (channel == VSYS) {
2683 version = qpnp_adc_get_revid_version(chip->dev);
2684 if (version == QPNP_REV_ID_PM8950_1_0) {
2685 pr_debug("Channel not supported\n");
2686 rc = -EINVAL;
2687 goto fail_unlock;
2688 }
2689 }
2690
2691 while (i < chip->max_channels_available) {
2692 if (chip->adc->adc_channels[i].channel_num ==
2693 channel) {
2694 dt_index = i;
2695 chan_found = true;
2696 i++;
2697 } else
2698 i++;
2699 }
2700
2701 if (!chan_found) {
2702 pr_err("not a valid ADC_TM channel\n");
2703 rc = -EINVAL;
2704 goto fail_unlock;
2705 }
2706
2707 rc = qpnp_adc_tm_check_revision(chip,
2708 chip->sensor[dt_index].btm_channel_num);
2709 if (rc < 0)
2710 goto fail_unlock;
2711
2712 scale_type = chip->adc->adc_channels[dt_index].adc_scale_fn;
2713 if (scale_type >= SCALE_RSCALE_NONE) {
2714 rc = -EBADF;
2715 goto fail_unlock;
2716 }
2717
2718
2719 amux_prescaling =
2720 chip->adc->adc_channels[dt_index].chan_path_prescaling;
2721
2722 if (amux_prescaling >= PATH_SCALING_NONE) {
2723 rc = -EINVAL;
2724 goto fail_unlock;
2725 }
2726
2727 pr_debug("channel:%d, scale_type:%d, dt_idx:%d",
2728 channel, scale_type, dt_index);
2729 param->gain_num = qpnp_vadc_amux_scaling_ratio[amux_prescaling].num;
2730 param->gain_den = qpnp_vadc_amux_scaling_ratio[amux_prescaling].den;
2731 param->adc_tm_hc = chip->adc_tm_hc;
Siddartha Mohanadossd9e74fe2017-10-13 15:27:55 -07002732 param->full_scale_code = chip->adc->adc_prop->full_scale_code;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002733 chip->adc->amux_prop->amux_channel = channel;
2734 chip->adc->amux_prop->decimation =
2735 chip->adc->adc_channels[dt_index].adc_decimation;
2736 chip->adc->amux_prop->hw_settle_time =
2737 chip->adc->adc_channels[dt_index].hw_settle_time;
2738 chip->adc->amux_prop->fast_avg_setup =
2739 chip->adc->adc_channels[dt_index].fast_avg_setup;
2740 chip->adc->amux_prop->mode_sel =
2741 ADC_OP_MEASUREMENT_INTERVAL << QPNP_OP_MODE_SHIFT;
2742 adc_tm_rscale_fn[scale_type].chan(chip->vadc_dev, param,
2743 &chip->adc->amux_prop->chan_prop->low_thr,
2744 &chip->adc->amux_prop->chan_prop->high_thr);
2745 qpnp_adc_tm_add_to_list(chip, dt_index, param,
2746 chip->adc->amux_prop->chan_prop);
2747 chip->adc->amux_prop->chan_prop->tm_channel_select =
2748 chip->sensor[dt_index].btm_channel_num;
2749 chip->adc->amux_prop->chan_prop->state_request =
2750 param->state_request;
2751 chip->adc->amux_prop->calib_type =
2752 chip->adc->adc_channels[dt_index].calib_type;
Prasad Malisetty358dda32018-02-20 06:14:26 +05302753 if (!chip->adc_tm_hc) {
2754 rc = qpnp_adc_tm_configure(chip, chip->adc->amux_prop);
2755 if (rc) {
2756 pr_err("adc-tm configure failed with %d\n", rc);
2757 goto fail_unlock;
2758 }
2759 } else {
2760 rc = qpnp_adc_tm_hc_configure(chip, chip->adc->amux_prop);
2761 if (rc) {
2762 pr_err("adc-tm hc configure failed with %d\n", rc);
2763 goto fail_unlock;
2764 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002765 }
2766
2767 chip->sensor[dt_index].scale_type = scale_type;
2768
2769fail_unlock:
2770 mutex_unlock(&chip->adc->adc_lock);
2771
2772 return rc;
2773}
2774EXPORT_SYMBOL(qpnp_adc_tm_channel_measure);
2775
2776int32_t qpnp_adc_tm_disable_chan_meas(struct qpnp_adc_tm_chip *chip,
2777 struct qpnp_adc_tm_btm_param *param)
2778{
2779 uint32_t channel, dt_index = 0, btm_chan_num;
Prasad Malisetty358dda32018-02-20 06:14:26 +05302780 u8 sensor_mask = 0, mode_ctl = 0;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002781 int rc = 0;
2782
2783 if (qpnp_adc_tm_is_valid(chip))
2784 return -ENODEV;
2785
2786 mutex_lock(&chip->adc->adc_lock);
2787
Prasad Malisetty358dda32018-02-20 06:14:26 +05302788 if (!chip->adc_tm_hc) {
2789 /* Set measurement in single measurement mode */
2790 mode_ctl = ADC_OP_NORMAL_MODE << QPNP_OP_MODE_SHIFT;
2791 rc = qpnp_adc_tm_mode_select(chip, mode_ctl);
2792 if (rc < 0) {
2793 pr_err("adc-tm single mode select failed\n");
2794 goto fail;
2795 }
2796 }
2797
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002798 /* Disable bank */
2799 rc = qpnp_adc_tm_disable(chip);
2800 if (rc < 0) {
2801 pr_err("adc-tm disable failed\n");
2802 goto fail;
2803 }
2804
Prasad Malisetty358dda32018-02-20 06:14:26 +05302805 if (!chip->adc_tm_hc) {
2806 /* Check if a conversion is in progress */
2807 rc = qpnp_adc_tm_req_sts_check(chip);
2808 if (rc < 0) {
2809 pr_err("adc-tm req_sts check failed\n");
2810 goto fail;
2811 }
2812 }
2813
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002814 channel = param->channel;
2815 while ((chip->adc->adc_channels[dt_index].channel_num
2816 != channel) && (dt_index < chip->max_channels_available))
2817 dt_index++;
2818
2819 if (dt_index >= chip->max_channels_available) {
2820 pr_err("not a valid ADC_TMN channel\n");
2821 rc = -EINVAL;
2822 goto fail;
2823 }
2824
2825 btm_chan_num = chip->sensor[dt_index].btm_channel_num;
2826
Prasad Malisetty358dda32018-02-20 06:14:26 +05302827 if (!chip->adc_tm_hc) {
2828 sensor_mask = 1 << chip->sensor[dt_index].sensor_num;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002829
Prasad Malisetty358dda32018-02-20 06:14:26 +05302830 rc = qpnp_adc_tm_reg_update(chip, QPNP_ADC_TM_LOW_THR_INT_EN,
2831 sensor_mask, false);
2832 if (rc < 0) {
2833 pr_err("high threshold int enable failed\n");
2834 goto fail;
2835 }
2836
2837 rc = qpnp_adc_tm_reg_update(chip, QPNP_ADC_TM_MULTI_MEAS_EN,
2838 sensor_mask, false);
2839 if (rc < 0) {
2840 pr_err("multi measurement en failed\n");
2841 goto fail;
2842 }
2843 } else {
2844 rc = qpnp_adc_tm_reg_update(chip, QPNP_BTM_Mn_EN(btm_chan_num),
2845 QPNP_BTM_Mn_HIGH_THR_INT_EN, false);
2846 if (rc < 0) {
2847 pr_err("high thr disable err:%d\n", btm_chan_num);
2848 return rc;
2849 }
2850
2851 rc = qpnp_adc_tm_reg_update(chip, QPNP_BTM_Mn_EN(btm_chan_num),
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002852 QPNP_BTM_Mn_LOW_THR_INT_EN, false);
Prasad Malisetty358dda32018-02-20 06:14:26 +05302853 if (rc < 0) {
2854 pr_err("low thr disable err:%d\n", btm_chan_num);
2855 return rc;
2856 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002857
Prasad Malisetty358dda32018-02-20 06:14:26 +05302858 rc = qpnp_adc_tm_reg_update(chip, QPNP_BTM_Mn_EN(btm_chan_num),
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07002859 QPNP_BTM_Mn_MEAS_EN, false);
Prasad Malisetty358dda32018-02-20 06:14:26 +05302860 if (rc < 0) {
2861 pr_err("multi measurement disable failed\n");
2862 return rc;
2863 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002864 }
2865
2866 rc = qpnp_adc_tm_enable_if_channel_meas(chip);
2867 if (rc < 0)
2868 pr_err("re-enabling measurement failed\n");
2869
2870fail:
2871 mutex_unlock(&chip->adc->adc_lock);
2872
2873 return rc;
2874}
2875EXPORT_SYMBOL(qpnp_adc_tm_disable_chan_meas);
2876
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002877struct qpnp_adc_tm_chip *qpnp_get_adc_tm(struct device *dev, const char *name)
2878{
2879 struct qpnp_adc_tm_chip *chip;
2880 struct device_node *node = NULL;
2881 char prop_name[QPNP_MAX_PROP_NAME_LEN];
2882
2883 snprintf(prop_name, QPNP_MAX_PROP_NAME_LEN, "qcom,%s-adc_tm", name);
2884
2885 node = of_parse_phandle(dev->of_node, prop_name, 0);
2886 if (node == NULL)
2887 return ERR_PTR(-ENODEV);
2888
2889 list_for_each_entry(chip, &qpnp_adc_tm_device_list, list)
2890 if (chip->adc->pdev->dev.of_node == node)
2891 return chip;
2892
2893 return ERR_PTR(-EPROBE_DEFER);
2894}
2895EXPORT_SYMBOL(qpnp_get_adc_tm);
2896
Prasad Malisetty358dda32018-02-20 06:14:26 +05302897static int qpnp_adc_tm_initial_setup(struct qpnp_adc_tm_chip *chip)
2898{
2899 u8 thr_init = 0;
2900 int rc = 0;
2901
2902 rc = qpnp_adc_tm_write_reg(chip, QPNP_ADC_TM_HIGH_THR_INT_EN,
2903 thr_init, 1);
2904 if (rc < 0) {
2905 pr_err("high thr init failed\n");
2906 return rc;
2907 }
2908
2909 rc = qpnp_adc_tm_write_reg(chip, QPNP_ADC_TM_LOW_THR_INT_EN,
2910 thr_init, 1);
2911 if (rc < 0) {
2912 pr_err("low thr init failed\n");
2913 return rc;
2914 }
2915
2916 rc = qpnp_adc_tm_write_reg(chip, QPNP_ADC_TM_MULTI_MEAS_EN,
2917 thr_init, 1);
2918 if (rc < 0) {
2919 pr_err("multi meas en failed\n");
2920 return rc;
2921 }
2922
2923 return rc;
2924}
2925
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002926static const struct of_device_id qpnp_adc_tm_match_table[] = {
2927 { .compatible = "qcom,qpnp-adc-tm" },
2928 { .compatible = "qcom,qpnp-adc-tm-hc" },
2929 {}
2930};
2931
2932static int qpnp_adc_tm_probe(struct platform_device *pdev)
2933{
2934 struct device_node *node = pdev->dev.of_node, *child;
2935 struct qpnp_adc_tm_chip *chip;
2936 struct qpnp_adc_drv *adc_qpnp;
2937 int32_t count_adc_channel_list = 0, rc, sen_idx = 0, i = 0;
2938 bool thermal_node = false;
2939 const struct of_device_id *id;
2940
2941 for_each_child_of_node(node, child)
2942 count_adc_channel_list++;
2943
2944 if (!count_adc_channel_list) {
2945 pr_err("No channel listing\n");
2946 return -EINVAL;
2947 }
2948
2949 id = of_match_node(qpnp_adc_tm_match_table, node);
2950 if (id == NULL) {
2951 pr_err("qpnp_adc_tm_match of_node prop not present\n");
2952 return -ENODEV;
2953 }
2954
2955 chip = devm_kzalloc(&pdev->dev, sizeof(struct qpnp_adc_tm_chip) +
2956 (count_adc_channel_list *
2957 sizeof(struct qpnp_adc_tm_sensor)),
2958 GFP_KERNEL);
2959 if (!chip)
2960 return -ENOMEM;
2961
2962 adc_qpnp = devm_kzalloc(&pdev->dev, sizeof(struct qpnp_adc_drv),
2963 GFP_KERNEL);
2964 if (!adc_qpnp) {
2965 rc = -ENOMEM;
2966 goto fail;
2967 }
2968
2969 chip->dev = &(pdev->dev);
2970 chip->adc = adc_qpnp;
2971 chip->adc->regmap = dev_get_regmap(pdev->dev.parent, NULL);
2972 if (!chip->adc->regmap) {
2973 dev_err(&pdev->dev, "Couldn't get parent's regmap\n");
2974 rc = -EINVAL;
2975 goto fail;
2976 }
2977
Prasad Malisetty358dda32018-02-20 06:14:26 +05302978 if (of_device_is_compatible(node, "qcom,qpnp-adc-tm-hc")) {
2979 chip->adc_tm_hc = true;
2980 chip->adc->adc_hc = true;
2981 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08002982
2983 rc = qpnp_adc_get_devicetree_data(pdev, chip->adc);
2984 if (rc) {
2985 dev_err(&pdev->dev, "failed to read device tree\n");
2986 goto fail;
2987 }
2988 mutex_init(&chip->adc->adc_lock);
2989
Prasad Malisetty358dda32018-02-20 06:14:26 +05302990 /* Register the ADC peripheral interrupt */
2991 if (!chip->adc_tm_hc) {
2992 chip->adc->adc_high_thr_irq = platform_get_irq_byname(pdev,
2993 "high-thr-en-set");
2994 if (chip->adc->adc_high_thr_irq < 0) {
2995 pr_err("Invalid irq\n");
2996 rc = -ENXIO;
2997 goto fail;
2998 }
2999
3000 chip->adc->adc_low_thr_irq = platform_get_irq_byname(pdev,
3001 "low-thr-en-set");
3002 if (chip->adc->adc_low_thr_irq < 0) {
3003 pr_err("Invalid irq\n");
3004 rc = -ENXIO;
3005 goto fail;
3006 }
3007 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003008 chip->vadc_dev = qpnp_get_vadc(&pdev->dev, "adc_tm");
3009 if (IS_ERR(chip->vadc_dev)) {
3010 rc = PTR_ERR(chip->vadc_dev);
3011 if (rc != -EPROBE_DEFER)
3012 pr_err("vadc property missing, rc=%d\n", rc);
3013 goto fail;
3014 }
3015
3016 chip->adc_tm_recalib_check = of_property_read_bool(node,
3017 "qcom,adc-tm-recalib-check");
3018
3019 for_each_child_of_node(node, child) {
3020 char name[25];
3021 int btm_channel_num, timer_select = 0;
3022
3023 rc = of_property_read_u32(child,
3024 "qcom,btm-channel-number", &btm_channel_num);
3025 if (rc) {
3026 pr_err("Invalid btm channel number\n");
3027 goto fail;
3028 }
3029 rc = of_property_read_u32(child,
3030 "qcom,meas-interval-timer-idx", &timer_select);
3031 if (rc) {
3032 pr_debug("Default to timer2 with interval of 1 sec\n");
3033 chip->sensor[sen_idx].timer_select =
3034 ADC_MEAS_TIMER_SELECT2;
3035 chip->sensor[sen_idx].meas_interval =
3036 ADC_MEAS2_INTERVAL_1S;
3037 } else {
3038 if (timer_select >= ADC_MEAS_TIMER_NUM) {
3039 pr_err("Invalid timer selection number\n");
3040 goto fail;
3041 }
3042 chip->sensor[sen_idx].timer_select = timer_select;
3043 if (timer_select == ADC_MEAS_TIMER_SELECT1)
3044 chip->sensor[sen_idx].meas_interval =
3045 ADC_MEAS1_INTERVAL_3P9MS;
3046 else if (timer_select == ADC_MEAS_TIMER_SELECT3)
3047 chip->sensor[sen_idx].meas_interval =
3048 ADC_MEAS3_INTERVAL_4S;
3049 else if (timer_select == ADC_MEAS_TIMER_SELECT2)
3050 chip->sensor[sen_idx].meas_interval =
3051 ADC_MEAS2_INTERVAL_1S;
3052 }
3053
3054 chip->sensor[sen_idx].btm_channel_num = btm_channel_num;
3055 chip->sensor[sen_idx].vadc_channel_num =
3056 chip->adc->adc_channels[sen_idx].channel_num;
3057 chip->sensor[sen_idx].sensor_num = sen_idx;
3058 chip->sensor[sen_idx].chip = chip;
3059 pr_debug("btm_chan:%x, vadc_chan:%x\n", btm_channel_num,
3060 chip->adc->adc_channels[sen_idx].channel_num);
3061 thermal_node = of_property_read_bool(child,
3062 "qcom,thermal-node");
3063 if (thermal_node) {
3064 /* Register with the thermal zone */
3065 pr_debug("thermal node%x\n", btm_channel_num);
3066 chip->sensor[sen_idx].mode = THERMAL_DEVICE_DISABLED;
3067 chip->sensor[sen_idx].thermal_node = true;
3068 snprintf(name, sizeof(name), "%s",
3069 chip->adc->adc_channels[sen_idx].name);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003070 chip->sensor[sen_idx].low_thr =
3071 QPNP_ADC_TM_M0_LOW_THR;
3072 chip->sensor[sen_idx].high_thr =
3073 QPNP_ADC_TM_M0_HIGH_THR;
3074 chip->sensor[sen_idx].tz_dev =
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07003075 devm_thermal_zone_of_sensor_register(
3076 chip->dev,
3077 chip->sensor[sen_idx].vadc_channel_num,
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003078 &chip->sensor[sen_idx],
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07003079 &qpnp_adc_tm_thermal_ops);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003080 if (IS_ERR(chip->sensor[sen_idx].tz_dev))
3081 pr_err("thermal device register failed.\n");
3082 }
3083 chip->sensor[sen_idx].req_wq = alloc_workqueue(
3084 "qpnp_adc_notify_wq", WQ_HIGHPRI, 0);
3085 if (!chip->sensor[sen_idx].req_wq) {
3086 pr_err("Requesting priority wq failed\n");
3087 goto fail;
3088 }
3089 INIT_WORK(&chip->sensor[sen_idx].work, notify_adc_tm_fn);
3090 INIT_LIST_HEAD(&chip->sensor[sen_idx].thr_list);
3091 sen_idx++;
3092 }
3093 chip->max_channels_available = count_adc_channel_list;
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07003094
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003095 chip->high_thr_wq = alloc_workqueue("qpnp_adc_tm_high_thr_wq",
3096 WQ_HIGHPRI, 0);
3097 if (!chip->high_thr_wq) {
3098 pr_err("Requesting high thr priority wq failed\n");
3099 goto fail;
3100 }
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07003101
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003102 chip->low_thr_wq = alloc_workqueue("qpnp_adc_tm_low_thr_wq",
3103 WQ_HIGHPRI, 0);
3104 if (!chip->low_thr_wq) {
3105 pr_err("Requesting low thr priority wq failed\n");
3106 goto fail;
3107 }
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07003108
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003109 chip->thr_wq = alloc_workqueue("qpnp_adc_tm_thr_wq",
3110 WQ_HIGHPRI, 0);
3111 if (!chip->thr_wq) {
3112 pr_err("Requesting thr priority wq failed\n");
3113 goto fail;
3114 }
3115
3116 INIT_WORK(&chip->trigger_high_thr_work, qpnp_adc_tm_high_thr_work);
3117 INIT_WORK(&chip->trigger_low_thr_work, qpnp_adc_tm_low_thr_work);
3118 atomic_set(&chip->wq_cnt, 0);
3119
Prasad Malisetty358dda32018-02-20 06:14:26 +05303120 if (!chip->adc_tm_hc) {
3121 rc = qpnp_adc_tm_initial_setup(chip);
3122 if (rc)
3123 goto fail;
3124 rc = devm_request_irq(&pdev->dev, chip->adc->adc_high_thr_irq,
3125 qpnp_adc_tm_high_thr_isr,
3126 IRQF_TRIGGER_RISING, "qpnp_adc_tm_high_interrupt", chip);
3127 if (rc) {
3128 dev_err(&pdev->dev, "failed to request adc irq\n");
3129 goto fail;
3130 } else {
3131 enable_irq_wake(chip->adc->adc_high_thr_irq);
3132 }
3133
3134 rc = devm_request_irq(&pdev->dev, chip->adc->adc_low_thr_irq,
3135 qpnp_adc_tm_low_thr_isr,
3136 IRQF_TRIGGER_RISING,
3137 "qpnp_adc_tm_low_interrupt", chip);
3138 if (rc) {
3139 dev_err(&pdev->dev, "failed to request adc irq\n");
3140 goto fail;
3141 } else {
3142 enable_irq_wake(chip->adc->adc_low_thr_irq);
3143 }
3144 } else {
3145 rc = devm_request_irq(&pdev->dev, chip->adc->adc_irq_eoc,
3146 qpnp_adc_tm_rc_thr_isr,
3147 IRQF_TRIGGER_HIGH, "qpnp_adc_tm_interrupt", chip);
3148 if (rc)
3149 dev_err(&pdev->dev, "failed to request adc irq\n");
3150 else
3151 enable_irq_wake(chip->adc->adc_irq_eoc);
3152 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003153
3154 chip->adc_vote_enable = false;
3155 dev_set_drvdata(&pdev->dev, chip);
3156 list_add(&chip->list, &qpnp_adc_tm_device_list);
Prasad Malisetty358dda32018-02-20 06:14:26 +05303157 spin_lock_init(&chip->th_info.adc_tm_low_lock);
3158 spin_lock_init(&chip->th_info.adc_tm_high_lock);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003159
3160 pr_debug("OK\n");
3161 return 0;
3162fail:
3163 for_each_child_of_node(node, child) {
3164 thermal_node = of_property_read_bool(child,
3165 "qcom,thermal-node");
3166 if (thermal_node) {
3167 thermal_zone_device_unregister(chip->sensor[i].tz_dev);
3168 if (chip->sensor[i].req_wq)
3169 destroy_workqueue(chip->sensor[sen_idx].req_wq);
3170 }
3171 }
3172 if (chip->high_thr_wq)
3173 destroy_workqueue(chip->high_thr_wq);
3174 if (chip->low_thr_wq)
3175 destroy_workqueue(chip->low_thr_wq);
3176 dev_set_drvdata(&pdev->dev, NULL);
3177 return rc;
3178}
3179
3180static int qpnp_adc_tm_remove(struct platform_device *pdev)
3181{
3182 struct qpnp_adc_tm_chip *chip = dev_get_drvdata(&pdev->dev);
3183 struct device_node *node = pdev->dev.of_node, *child;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003184 int i = 0;
3185
3186 for_each_child_of_node(node, child) {
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07003187 if (chip->sensor[i].req_wq)
3188 destroy_workqueue(chip->sensor[i].req_wq);
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003189 i++;
3190 }
3191
3192 if (chip->high_thr_wq)
3193 destroy_workqueue(chip->high_thr_wq);
3194 if (chip->low_thr_wq)
3195 destroy_workqueue(chip->low_thr_wq);
3196 if (chip->adc->hkadc_ldo && chip->adc->hkadc_ldo_ok)
3197 qpnp_adc_free_voltage_resource(chip->adc);
3198 dev_set_drvdata(&pdev->dev, NULL);
3199
3200 return 0;
3201}
3202
3203static void qpnp_adc_tm_shutdown(struct platform_device *pdev)
3204{
3205 struct qpnp_adc_tm_chip *chip = dev_get_drvdata(&pdev->dev);
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07003206 int rc = 0, i = 0;
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003207
3208 /* Disable bank */
3209 rc = qpnp_adc_tm_disable(chip);
3210 if (rc < 0)
3211 pr_err("adc-tm disable failed\n");
3212
Siddartha Mohanadoss697fe0d2017-04-26 17:10:11 -07003213 for (i = 0; i < QPNP_BTM_CHANNELS; i++) {
3214 rc = qpnp_adc_tm_reg_update(chip,
3215 QPNP_BTM_Mn_EN(i),
3216 QPNP_BTM_Mn_MEAS_EN, false);
3217 if (rc < 0)
3218 pr_err("multi measurement disable failed\n");
3219 }
Siddartha Mohanadoss45a944b2017-01-23 19:46:10 -08003220}
3221
3222static int qpnp_adc_tm_suspend_noirq(struct device *dev)
3223{
3224 struct qpnp_adc_tm_chip *chip = dev_get_drvdata(dev);
3225
3226 if (atomic_read(&chip->wq_cnt) != 0) {
3227 pr_err(
3228 "Aborting suspend, adc_tm notification running while suspending\n");
3229 return -EBUSY;
3230 }
3231 return 0;
3232}
3233
3234static const struct dev_pm_ops qpnp_adc_tm_pm_ops = {
3235 .suspend_noirq = qpnp_adc_tm_suspend_noirq,
3236};
3237
3238static struct platform_driver qpnp_adc_tm_driver = {
3239 .driver = {
3240 .name = "qcom,qpnp-adc-tm",
3241 .of_match_table = qpnp_adc_tm_match_table,
3242 .pm = &qpnp_adc_tm_pm_ops,
3243 },
3244 .probe = qpnp_adc_tm_probe,
3245 .remove = qpnp_adc_tm_remove,
3246 .shutdown = qpnp_adc_tm_shutdown,
3247};
3248
3249static int __init qpnp_adc_tm_init(void)
3250{
3251 return platform_driver_register(&qpnp_adc_tm_driver);
3252}
3253module_init(qpnp_adc_tm_init);
3254
3255static void __exit qpnp_adc_tm_exit(void)
3256{
3257 platform_driver_unregister(&qpnp_adc_tm_driver);
3258}
3259module_exit(qpnp_adc_tm_exit);
3260
3261MODULE_DESCRIPTION("QPNP PMIC ADC Threshold Monitoring driver");
3262MODULE_LICENSE("GPL v2");