blob: 0be96f2e4d92cec7b025f369a1db3e084ab49a7f [file] [log] [blame]
Jishnu Prakashb5203662019-03-08 13:06:23 +05301/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -08002 *
3 * This program is free software; you can redistribute it and/or modify
Siddartha Mohanadosscd8aa0b2017-04-06 15:17:46 -07004 * it under the terms of the GNU General Public License version 2 and
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -08005 * 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#include <linux/module.h>
15#include <linux/platform_device.h>
16#include <linux/slab.h>
17#include <linux/err.h>
18#include <linux/of.h>
19#include <linux/vmalloc.h>
20#include "tsens.h"
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -070021#include "thermal_core.h"
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -080022
23#define TSENS_DRIVER_NAME "msm-tsens"
24
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -070025#define TSENS_TM_INT_EN(n) ((n) + 0x4)
26#define TSENS_TM_CRITICAL_INT_STATUS(n) ((n) + 0x14)
27#define TSENS_TM_CRITICAL_INT_CLEAR(n) ((n) + 0x18)
28#define TSENS_TM_CRITICAL_INT_MASK(n) ((n) + 0x1c)
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -080029#define TSENS_TM_CRITICAL_WD_BARK BIT(31)
30#define TSENS_TM_CRITICAL_CYCLE_MONITOR BIT(30)
31#define TSENS_TM_CRITICAL_INT_EN BIT(2)
32#define TSENS_TM_UPPER_INT_EN BIT(1)
33#define TSENS_TM_LOWER_INT_EN BIT(0)
Jishnu Prakash37ba7e52018-03-20 16:35:11 +053034#define TSENS_TM_UPPER_LOWER_INT_DISABLE 0xffffffff
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -070035#define TSENS_TM_SN_UPPER_LOWER_THRESHOLD(n) ((n) + 0x20)
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -080036#define TSENS_TM_SN_ADDR_OFFSET 0x4
37#define TSENS_TM_UPPER_THRESHOLD_SET(n) ((n) << 12)
38#define TSENS_TM_UPPER_THRESHOLD_VALUE_SHIFT(n) ((n) >> 12)
39#define TSENS_TM_LOWER_THRESHOLD_VALUE(n) ((n) & 0xfff)
40#define TSENS_TM_UPPER_THRESHOLD_VALUE(n) (((n) & 0xfff000) >> 12)
41#define TSENS_TM_UPPER_THRESHOLD_MASK 0xfff000
42#define TSENS_TM_LOWER_THRESHOLD_MASK 0xfff
43#define TSENS_TM_UPPER_THRESHOLD_SHIFT 12
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -070044#define TSENS_TM_SN_CRITICAL_THRESHOLD(n) ((n) + 0x60)
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -080045#define TSENS_STATUS_ADDR_OFFSET 2
46#define TSENS_TM_UPPER_INT_MASK(n) (((n) & 0xffff0000) >> 16)
47#define TSENS_TM_LOWER_INT_MASK(n) ((n) & 0xffff)
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -070048#define TSENS_TM_UPPER_LOWER_INT_STATUS(n) ((n) + 0x8)
49#define TSENS_TM_UPPER_LOWER_INT_CLEAR(n) ((n) + 0xc)
50#define TSENS_TM_UPPER_LOWER_INT_MASK(n) ((n) + 0x10)
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -080051#define TSENS_TM_UPPER_INT_SET(n) (1 << (n + 16))
52#define TSENS_TM_SN_CRITICAL_THRESHOLD_MASK 0xfff
53#define TSENS_TM_SN_STATUS_VALID_BIT BIT(21)
54#define TSENS_TM_SN_STATUS_CRITICAL_STATUS BIT(19)
55#define TSENS_TM_SN_STATUS_UPPER_STATUS BIT(18)
56#define TSENS_TM_SN_STATUS_LOWER_STATUS BIT(17)
57#define TSENS_TM_SN_LAST_TEMP_MASK 0xfff
58#define TSENS_TM_CODE_BIT_MASK 0xfff
59#define TSENS_TM_CODE_SIGN_BIT 0x800
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -070060#define TSENS_TM_SCALE_DECI_MILLIDEG 100
Siddartha Mohanadoss64a5da32017-05-09 11:09:51 -070061#define TSENS_DEBUG_WDOG_TRIGGER_COUNT 5
62#define TSENS_TM_WATCHDOG_LOG(n) ((n) + 0x13c)
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -080063#define TSENS_EN BIT(0)
Siddartha Mohanadossf86413d2017-07-18 13:44:31 -070064#define TSENS_CTRL_SENSOR_EN_MASK(n) ((n >> 3) & 0xffff)
Siddartha Mohanadoss5a4069b2018-02-09 11:19:11 -080065#define TSENS_TM_TRDY(n) ((n) + 0xe4)
66#define TSENS_TM_TRDY_FIRST_ROUND_COMPLETE BIT(3)
67#define TSENS_TM_TRDY_FIRST_ROUND_COMPLETE_SHIFT 3
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -080068
69static void msm_tsens_convert_temp(int last_temp, int *temp)
70{
71 int code_mask = ~TSENS_TM_CODE_BIT_MASK;
72
73 if (last_temp & TSENS_TM_CODE_SIGN_BIT) {
74 /* Sign extension for negative value */
75 last_temp |= code_mask;
76 }
77
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -070078 *temp = last_temp * TSENS_TM_SCALE_DECI_MILLIDEG;
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -080079}
80
81static int tsens2xxx_get_temp(struct tsens_sensor *sensor, int *temp)
82{
83 struct tsens_device *tmdev = NULL;
84 unsigned int code;
Siddartha Mohanadoss5a4069b2018-02-09 11:19:11 -080085 void __iomem *sensor_addr, *trdy;
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -080086 int last_temp = 0, last_temp2 = 0, last_temp3 = 0;
87
88 if (!sensor)
89 return -EINVAL;
90
91 tmdev = sensor->tmdev;
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -070092 sensor_addr = TSENS_TM_SN_STATUS(tmdev->tsens_tm_addr);
Siddartha Mohanadoss5a4069b2018-02-09 11:19:11 -080093 trdy = TSENS_TM_TRDY(tmdev->tsens_tm_addr);
94
95 code = readl_relaxed_no_log(trdy);
96 if (!((code & TSENS_TM_TRDY_FIRST_ROUND_COMPLETE) >>
97 TSENS_TM_TRDY_FIRST_ROUND_COMPLETE_SHIFT)) {
98 pr_err("TSENS device first round not complete0x%x\n", code);
99 return -ENODATA;
100 }
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800101
102 code = readl_relaxed_no_log(sensor_addr +
103 (sensor->hw_id << TSENS_STATUS_ADDR_OFFSET));
104 last_temp = code & TSENS_TM_SN_LAST_TEMP_MASK;
105
106 if (code & TSENS_TM_SN_STATUS_VALID_BIT) {
107 msm_tsens_convert_temp(last_temp, temp);
Rama Krishna Phani A6ad66332017-10-25 21:20:04 +0530108 goto dbg;
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800109 }
110
111 code = readl_relaxed_no_log(sensor_addr +
112 (sensor->hw_id << TSENS_STATUS_ADDR_OFFSET));
113 last_temp2 = code & TSENS_TM_SN_LAST_TEMP_MASK;
114 if (code & TSENS_TM_SN_STATUS_VALID_BIT) {
115 last_temp = last_temp2;
116 msm_tsens_convert_temp(last_temp, temp);
Rama Krishna Phani A6ad66332017-10-25 21:20:04 +0530117 goto dbg;
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800118 }
119
120 code = readl_relaxed_no_log(sensor_addr +
121 (sensor->hw_id <<
122 TSENS_STATUS_ADDR_OFFSET));
123 last_temp3 = code & TSENS_TM_SN_LAST_TEMP_MASK;
124 if (code & TSENS_TM_SN_STATUS_VALID_BIT) {
125 last_temp = last_temp3;
126 msm_tsens_convert_temp(last_temp, temp);
Rama Krishna Phani A6ad66332017-10-25 21:20:04 +0530127 goto dbg;
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800128 }
129
130 if (last_temp == last_temp2)
131 last_temp = last_temp2;
132 else if (last_temp2 == last_temp3)
133 last_temp = last_temp3;
134
135 msm_tsens_convert_temp(last_temp, temp);
136
Rama Krishna Phani A6ad66332017-10-25 21:20:04 +0530137dbg:
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800138 if (tmdev->ops->dbg)
139 tmdev->ops->dbg(tmdev, (u32) sensor->hw_id,
140 TSENS_DBG_LOG_TEMP_READS, temp);
141
142 return 0;
143}
144
145static int tsens_tm_activate_trip_type(struct tsens_sensor *tm_sensor,
146 int trip, enum thermal_trip_activation_mode mode)
147{
148 struct tsens_device *tmdev = NULL;
149 unsigned int reg_cntl, mask;
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800150 int rc = 0;
151
152 /* clear the interrupt and unmask */
153 if (!tm_sensor || trip < 0)
154 return -EINVAL;
155
156 tmdev = tm_sensor->tmdev;
157 if (!tmdev)
158 return -EINVAL;
159
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700160
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800161 mask = (tm_sensor->hw_id);
162 switch (trip) {
163 case THERMAL_TRIP_CRITICAL:
164 tmdev->sensor[tm_sensor->hw_id].
165 thr_state.crit_th_state = mode;
166 reg_cntl = readl_relaxed(TSENS_TM_CRITICAL_INT_MASK
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700167 (tmdev->tsens_tm_addr));
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800168 if (mode == THERMAL_TRIP_ACTIVATION_DISABLED)
169 writel_relaxed(reg_cntl | (1 << mask),
170 (TSENS_TM_CRITICAL_INT_MASK
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700171 (tmdev->tsens_tm_addr)));
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800172 else
173 writel_relaxed(reg_cntl & ~(1 << mask),
174 (TSENS_TM_CRITICAL_INT_MASK
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700175 (tmdev->tsens_tm_addr)));
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800176 break;
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700177 case THERMAL_TRIP_CONFIGURABLE_HI:
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800178 tmdev->sensor[tm_sensor->hw_id].
179 thr_state.high_th_state = mode;
180 reg_cntl = readl_relaxed(TSENS_TM_UPPER_LOWER_INT_MASK
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700181 (tmdev->tsens_tm_addr));
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800182 if (mode == THERMAL_TRIP_ACTIVATION_DISABLED)
183 writel_relaxed(reg_cntl |
184 (TSENS_TM_UPPER_INT_SET(mask)),
185 (TSENS_TM_UPPER_LOWER_INT_MASK
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700186 (tmdev->tsens_tm_addr)));
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800187 else
188 writel_relaxed(reg_cntl &
189 ~(TSENS_TM_UPPER_INT_SET(mask)),
190 (TSENS_TM_UPPER_LOWER_INT_MASK
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700191 (tmdev->tsens_tm_addr)));
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800192 break;
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700193 case THERMAL_TRIP_CONFIGURABLE_LOW:
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800194 tmdev->sensor[tm_sensor->hw_id].
195 thr_state.low_th_state = mode;
196 reg_cntl = readl_relaxed(TSENS_TM_UPPER_LOWER_INT_MASK
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700197 (tmdev->tsens_tm_addr));
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800198 if (mode == THERMAL_TRIP_ACTIVATION_DISABLED)
199 writel_relaxed(reg_cntl | (1 << mask),
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700200 (TSENS_TM_UPPER_LOWER_INT_MASK
201 (tmdev->tsens_tm_addr)));
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800202 else
203 writel_relaxed(reg_cntl & ~(1 << mask),
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700204 (TSENS_TM_UPPER_LOWER_INT_MASK
205 (tmdev->tsens_tm_addr)));
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800206 break;
207 default:
208 rc = -EINVAL;
209 }
210
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800211 /* Activate and enable the respective trip threshold setting */
212 mb();
213
214 return rc;
215}
216
217static int tsens2xxx_set_trip_temp(struct tsens_sensor *tm_sensor,
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700218 int low_temp, int high_temp)
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800219{
220 unsigned int reg_cntl;
221 unsigned long flags;
222 struct tsens_device *tmdev = NULL;
223 int rc = 0;
224
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700225 if (!tm_sensor)
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800226 return -EINVAL;
227
228 tmdev = tm_sensor->tmdev;
229 if (!tmdev)
230 return -EINVAL;
231
232 spin_lock_irqsave(&tmdev->tsens_upp_low_lock, flags);
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700233
234 if (high_temp != INT_MAX) {
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800235 tmdev->sensor[tm_sensor->hw_id].
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700236 thr_state.high_temp = high_temp;
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800237 reg_cntl = readl_relaxed((TSENS_TM_SN_UPPER_LOWER_THRESHOLD
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700238 (tmdev->tsens_tm_addr)) +
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800239 (tm_sensor->hw_id *
240 TSENS_TM_SN_ADDR_OFFSET));
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700241 high_temp /= TSENS_TM_SCALE_DECI_MILLIDEG;
242 high_temp = TSENS_TM_UPPER_THRESHOLD_SET(high_temp);
243 high_temp &= TSENS_TM_UPPER_THRESHOLD_MASK;
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800244 reg_cntl &= ~TSENS_TM_UPPER_THRESHOLD_MASK;
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700245 writel_relaxed(reg_cntl | high_temp,
246 (TSENS_TM_SN_UPPER_LOWER_THRESHOLD
247 (tmdev->tsens_tm_addr) +
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800248 (tm_sensor->hw_id * TSENS_TM_SN_ADDR_OFFSET)));
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800249 }
250
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700251 if (low_temp != INT_MIN) {
252 tmdev->sensor[tm_sensor->hw_id].
253 thr_state.low_temp = low_temp;
254 reg_cntl = readl_relaxed((TSENS_TM_SN_UPPER_LOWER_THRESHOLD
255 (tmdev->tsens_tm_addr)) +
256 (tm_sensor->hw_id *
257 TSENS_TM_SN_ADDR_OFFSET));
258 low_temp /= TSENS_TM_SCALE_DECI_MILLIDEG;
259 low_temp &= TSENS_TM_LOWER_THRESHOLD_MASK;
260 reg_cntl &= ~TSENS_TM_LOWER_THRESHOLD_MASK;
261 writel_relaxed(reg_cntl | low_temp,
262 (TSENS_TM_SN_UPPER_LOWER_THRESHOLD
263 (tmdev->tsens_tm_addr) +
264 (tm_sensor->hw_id * TSENS_TM_SN_ADDR_OFFSET)));
265 }
266
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800267 /* Set trip temperature thresholds */
268 mb();
269
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700270 if (high_temp != INT_MAX) {
271 rc = tsens_tm_activate_trip_type(tm_sensor,
272 THERMAL_TRIP_CONFIGURABLE_HI,
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800273 THERMAL_TRIP_ACTIVATION_ENABLED);
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700274 if (rc) {
Siddartha Mohanadossf10a5a32017-04-19 09:31:39 -0700275 pr_err("trip high enable error :%d\n", rc);
276 goto fail;
277 }
278 } else {
279 rc = tsens_tm_activate_trip_type(tm_sensor,
280 THERMAL_TRIP_CONFIGURABLE_HI,
281 THERMAL_TRIP_ACTIVATION_DISABLED);
282 if (rc) {
283 pr_err("trip high disable error :%d\n", rc);
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700284 goto fail;
285 }
286 }
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800287
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700288 if (low_temp != INT_MIN) {
289 rc = tsens_tm_activate_trip_type(tm_sensor,
290 THERMAL_TRIP_CONFIGURABLE_LOW,
291 THERMAL_TRIP_ACTIVATION_ENABLED);
292 if (rc) {
Siddartha Mohanadossf10a5a32017-04-19 09:31:39 -0700293 pr_err("trip low enable activation error :%d\n", rc);
294 goto fail;
295 }
296 } else {
297 rc = tsens_tm_activate_trip_type(tm_sensor,
298 THERMAL_TRIP_CONFIGURABLE_LOW,
299 THERMAL_TRIP_ACTIVATION_DISABLED);
300 if (rc) {
301 pr_err("trip low disable error :%d\n", rc);
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700302 goto fail;
303 }
304 }
305
306fail:
307 spin_unlock_irqrestore(&tmdev->tsens_upp_low_lock, flags);
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800308 return rc;
309}
310
311static irqreturn_t tsens_tm_critical_irq_thread(int irq, void *data)
312{
313 struct tsens_device *tm = data;
Siddartha Mohanadoss64a5da32017-05-09 11:09:51 -0700314 unsigned int i, status, wd_log, wd_mask;
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800315 unsigned long flags;
Siddartha Mohanadoss64a5da32017-05-09 11:09:51 -0700316 void __iomem *sensor_status_addr, *sensor_int_mask_addr;
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800317 void __iomem *sensor_critical_addr;
Siddartha Mohanadoss64a5da32017-05-09 11:09:51 -0700318 void __iomem *wd_critical_addr, *wd_log_addr;
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800319
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700320 sensor_status_addr = TSENS_TM_SN_STATUS(tm->tsens_tm_addr);
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800321 sensor_int_mask_addr =
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700322 TSENS_TM_CRITICAL_INT_MASK(tm->tsens_tm_addr);
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800323 sensor_critical_addr =
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700324 TSENS_TM_SN_CRITICAL_THRESHOLD(tm->tsens_tm_addr);
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800325 wd_critical_addr =
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700326 TSENS_TM_CRITICAL_INT_STATUS(tm->tsens_tm_addr);
Siddartha Mohanadoss64a5da32017-05-09 11:09:51 -0700327 wd_log_addr = TSENS_TM_WATCHDOG_LOG(tm->tsens_tm_addr);
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800328
329 if (tm->ctrl_data->wd_bark) {
330 wd_mask = readl_relaxed(wd_critical_addr);
331 if (wd_mask & TSENS_TM_CRITICAL_WD_BARK) {
332 /*
333 * Clear watchdog interrupt and
334 * increment global wd count
335 */
336 writel_relaxed(wd_mask | TSENS_TM_CRITICAL_WD_BARK,
337 (TSENS_TM_CRITICAL_INT_CLEAR
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700338 (tm->tsens_tm_addr)));
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800339 writel_relaxed(wd_mask & ~(TSENS_TM_CRITICAL_WD_BARK),
340 (TSENS_TM_CRITICAL_INT_CLEAR
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700341 (tm->tsens_tm_addr)));
Siddartha Mohanadoss64a5da32017-05-09 11:09:51 -0700342 wd_log = readl_relaxed(wd_log_addr);
343 if (wd_log >= TSENS_DEBUG_WDOG_TRIGGER_COUNT) {
344 pr_err("Watchdog count:%d\n", wd_log);
345 if (tm->ops->dbg)
346 tm->ops->dbg(tm, 0,
347 TSENS_DBG_LOG_BUS_ID_DATA, NULL);
348 BUG();
349 }
350
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800351 return IRQ_HANDLED;
352 }
353 }
354
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700355 for (i = 0; i < TSENS_MAX_SENSORS; i++) {
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800356 int int_mask, int_mask_val;
357 u32 addr_offset;
358
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700359 if (IS_ERR(tm->sensor[i].tzd))
360 continue;
361
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800362 spin_lock_irqsave(&tm->tsens_crit_lock, flags);
363 addr_offset = tm->sensor[i].hw_id *
364 TSENS_TM_SN_ADDR_OFFSET;
365 status = readl_relaxed(sensor_status_addr + addr_offset);
366 int_mask = readl_relaxed(sensor_int_mask_addr);
367
368 if ((status & TSENS_TM_SN_STATUS_CRITICAL_STATUS) &&
369 !(int_mask & (1 << tm->sensor[i].hw_id))) {
370 int_mask = readl_relaxed(sensor_int_mask_addr);
371 int_mask_val = (1 << tm->sensor[i].hw_id);
372 /* Mask the corresponding interrupt for the sensors */
373 writel_relaxed(int_mask | int_mask_val,
374 TSENS_TM_CRITICAL_INT_MASK(
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700375 tm->tsens_tm_addr));
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800376 /* Clear the corresponding sensors interrupt */
377 writel_relaxed(int_mask_val,
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700378 TSENS_TM_CRITICAL_INT_CLEAR
379 (tm->tsens_tm_addr));
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800380 writel_relaxed(0,
381 TSENS_TM_CRITICAL_INT_CLEAR(
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700382 tm->tsens_tm_addr));
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800383 tm->sensor[i].thr_state.
Jishnu Prakashb5203662019-03-08 13:06:23 +0530384 crit_th_state =
385 THERMAL_TRIP_ACTIVATION_DISABLED;
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800386 }
387 spin_unlock_irqrestore(&tm->tsens_crit_lock, flags);
388 }
389
390 /* Mask critical interrupt */
391 mb();
392
393 return IRQ_HANDLED;
394}
395
396static irqreturn_t tsens_tm_irq_thread(int irq, void *data)
397{
398 struct tsens_device *tm = data;
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700399 unsigned int i, status, threshold, temp;
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800400 unsigned long flags;
401 void __iomem *sensor_status_addr;
402 void __iomem *sensor_int_mask_addr;
403 void __iomem *sensor_upper_lower_addr;
404 u32 addr_offset = 0;
405
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700406 sensor_status_addr = TSENS_TM_SN_STATUS(tm->tsens_tm_addr);
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800407 sensor_int_mask_addr =
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700408 TSENS_TM_UPPER_LOWER_INT_MASK(tm->tsens_tm_addr);
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800409 sensor_upper_lower_addr =
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700410 TSENS_TM_SN_UPPER_LOWER_THRESHOLD(tm->tsens_tm_addr);
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800411
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700412 for (i = 0; i < TSENS_MAX_SENSORS; i++) {
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800413 bool upper_thr = false, lower_thr = false;
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700414 int int_mask, int_mask_val = 0, rc;
415
416 if (IS_ERR(tm->sensor[i].tzd))
417 continue;
418
419 rc = tsens2xxx_get_temp(&tm->sensor[i], &temp);
420 if (rc) {
421 pr_debug("Error:%d reading temp sensor:%d\n", rc, i);
422 continue;
423 }
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800424
425 spin_lock_irqsave(&tm->tsens_upp_low_lock, flags);
426 addr_offset = tm->sensor[i].hw_id *
427 TSENS_TM_SN_ADDR_OFFSET;
428 status = readl_relaxed(sensor_status_addr + addr_offset);
429 threshold = readl_relaxed(sensor_upper_lower_addr +
430 addr_offset);
431 int_mask = readl_relaxed(sensor_int_mask_addr);
432
433 if ((status & TSENS_TM_SN_STATUS_UPPER_STATUS) &&
434 !(int_mask &
435 (1 << (tm->sensor[i].hw_id + 16)))) {
436 int_mask = readl_relaxed(sensor_int_mask_addr);
437 int_mask_val = TSENS_TM_UPPER_INT_SET(
438 tm->sensor[i].hw_id);
439 /* Mask the corresponding interrupt for the sensors */
440 writel_relaxed(int_mask | int_mask_val,
441 TSENS_TM_UPPER_LOWER_INT_MASK(
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700442 tm->tsens_tm_addr));
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800443 /* Clear the corresponding sensors interrupt */
444 writel_relaxed(int_mask_val,
445 TSENS_TM_UPPER_LOWER_INT_CLEAR(
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700446 tm->tsens_tm_addr));
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800447 writel_relaxed(0,
448 TSENS_TM_UPPER_LOWER_INT_CLEAR(
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700449 tm->tsens_tm_addr));
450 if (TSENS_TM_UPPER_THRESHOLD_VALUE(threshold) >
451 (temp/TSENS_TM_SCALE_DECI_MILLIDEG)) {
452 pr_debug("Re-arm high threshold\n");
453 rc = tsens_tm_activate_trip_type(
454 &tm->sensor[i],
455 THERMAL_TRIP_CONFIGURABLE_HI,
456 THERMAL_TRIP_ACTIVATION_ENABLED);
457 if (rc)
458 pr_err("high rearm failed:%d\n", rc);
459 } else {
460 upper_thr = true;
461 tm->sensor[i].thr_state.
Jishnu Prakashb5203662019-03-08 13:06:23 +0530462 high_th_state =
463 THERMAL_TRIP_ACTIVATION_DISABLED;
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700464 }
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800465 }
466
467 if ((status & TSENS_TM_SN_STATUS_LOWER_STATUS) &&
468 !(int_mask &
469 (1 << tm->sensor[i].hw_id))) {
470 int_mask = readl_relaxed(sensor_int_mask_addr);
471 int_mask_val = (1 << tm->sensor[i].hw_id);
472 /* Mask the corresponding interrupt for the sensors */
473 writel_relaxed(int_mask | int_mask_val,
474 TSENS_TM_UPPER_LOWER_INT_MASK(
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700475 tm->tsens_tm_addr));
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800476 /* Clear the corresponding sensors interrupt */
477 writel_relaxed(int_mask_val,
478 TSENS_TM_UPPER_LOWER_INT_CLEAR(
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700479 tm->tsens_tm_addr));
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800480 writel_relaxed(0,
481 TSENS_TM_UPPER_LOWER_INT_CLEAR(
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700482 tm->tsens_tm_addr));
483 if (TSENS_TM_LOWER_THRESHOLD_VALUE(threshold)
484 < (temp/TSENS_TM_SCALE_DECI_MILLIDEG)) {
485 pr_debug("Re-arm low threshold\n");
486 rc = tsens_tm_activate_trip_type(
487 &tm->sensor[i],
488 THERMAL_TRIP_CONFIGURABLE_LOW,
489 THERMAL_TRIP_ACTIVATION_ENABLED);
490 if (rc)
491 pr_err("low rearm failed:%d\n", rc);
492 } else {
493 lower_thr = true;
494 tm->sensor[i].thr_state.
Jishnu Prakashb5203662019-03-08 13:06:23 +0530495 low_th_state =
496 THERMAL_TRIP_ACTIVATION_DISABLED;
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700497 }
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800498 }
499 spin_unlock_irqrestore(&tm->tsens_upp_low_lock, flags);
500
501 if (upper_thr || lower_thr) {
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800502 /* Use id for multiple controllers */
503 pr_debug("sensor:%d trigger temp (%d degC)\n",
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700504 tm->sensor[i].hw_id, temp);
Ram Chandrasekarb9bb1362018-11-02 12:28:37 -0600505 of_thermal_handle_trip_temp(tm->sensor[i].tzd, temp);
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800506 }
507 }
508
509 /* Disable monitoring sensor trip threshold for triggered sensor */
510 mb();
511
512 if (tm->ops->dbg)
513 tm->ops->dbg(tm, 0, TSENS_DBG_LOG_INTERRUPT_TIMESTAMP, NULL);
514
515 return IRQ_HANDLED;
516}
517
Siddartha Mohanadossf86413d2017-07-18 13:44:31 -0700518static int tsens2xxx_hw_sensor_en(struct tsens_device *tmdev,
519 u32 sensor_id)
520{
521 void __iomem *srot_addr;
522 unsigned int srot_val, sensor_en;
523
524 srot_addr = TSENS_CTRL_ADDR(tmdev->tsens_srot_addr + 0x4);
525 srot_val = readl_relaxed(srot_addr);
526 srot_val = TSENS_CTRL_SENSOR_EN_MASK(srot_val);
527
528 sensor_en = ((1 << sensor_id) & srot_val);
529
530 return sensor_en;
531}
532
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800533static int tsens2xxx_hw_init(struct tsens_device *tmdev)
534{
535 void __iomem *srot_addr;
536 void __iomem *sensor_int_mask_addr;
Siddartha Mohanadoss64a5da32017-05-09 11:09:51 -0700537 unsigned int srot_val, crit_mask, crit_val;
Jishnu Prakash37ba7e52018-03-20 16:35:11 +0530538 void __iomem *int_mask_addr;
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800539
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700540 srot_addr = TSENS_CTRL_ADDR(tmdev->tsens_srot_addr + 0x4);
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800541 srot_val = readl_relaxed(srot_addr);
542 if (!(srot_val & TSENS_EN)) {
543 pr_err("TSENS device is not enabled\n");
544 return -ENODEV;
545 }
546
547 if (tmdev->ctrl_data->cycle_monitor) {
548 sensor_int_mask_addr =
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700549 TSENS_TM_CRITICAL_INT_MASK(tmdev->tsens_tm_addr);
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800550 crit_mask = readl_relaxed(sensor_int_mask_addr);
Siddartha Mohanadoss64a5da32017-05-09 11:09:51 -0700551 crit_val = TSENS_TM_CRITICAL_CYCLE_MONITOR;
552 if (tmdev->ctrl_data->cycle_compltn_monitor_mask)
553 writel_relaxed((crit_mask | crit_val),
554 (TSENS_TM_CRITICAL_INT_MASK
555 (tmdev->tsens_tm_addr)));
556 else
557 writel_relaxed((crit_mask & ~crit_val),
558 (TSENS_TM_CRITICAL_INT_MASK
559 (tmdev->tsens_tm_addr)));
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800560 /*Update critical cycle monitoring*/
561 mb();
562 }
Siddartha Mohanadoss64a5da32017-05-09 11:09:51 -0700563
564 if (tmdev->ctrl_data->wd_bark) {
565 sensor_int_mask_addr =
566 TSENS_TM_CRITICAL_INT_MASK(tmdev->tsens_tm_addr);
567 crit_mask = readl_relaxed(sensor_int_mask_addr);
568 crit_val = TSENS_TM_CRITICAL_WD_BARK;
569 if (tmdev->ctrl_data->wd_bark_mask)
570 writel_relaxed((crit_mask | crit_val),
571 (TSENS_TM_CRITICAL_INT_MASK
572 (tmdev->tsens_tm_addr)));
573 else
574 writel_relaxed((crit_mask & ~crit_val),
575 (TSENS_TM_CRITICAL_INT_MASK
576 (tmdev->tsens_tm_addr)));
577 /*Update watchdog monitoring*/
578 mb();
579 }
580
Jishnu Prakash37ba7e52018-03-20 16:35:11 +0530581 int_mask_addr = TSENS_TM_UPPER_LOWER_INT_MASK(tmdev->tsens_tm_addr);
582 writel_relaxed(TSENS_TM_UPPER_LOWER_INT_DISABLE, int_mask_addr);
583
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800584 writel_relaxed(TSENS_TM_CRITICAL_INT_EN |
585 TSENS_TM_UPPER_INT_EN | TSENS_TM_LOWER_INT_EN,
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700586 TSENS_TM_INT_EN(tmdev->tsens_tm_addr));
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800587
588 spin_lock_init(&tmdev->tsens_crit_lock);
589 spin_lock_init(&tmdev->tsens_upp_low_lock);
590
Ashok Jammigumpulaa1b7ec12017-11-23 15:37:44 +0530591 if (tmdev->ctrl_data->mtc) {
592 if (tmdev->ops->dbg)
593 tmdev->ops->dbg(tmdev, 0, TSENS_DBG_MTC_DATA, NULL);
594 }
595
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800596 return 0;
597}
598
599static const struct tsens_irqs tsens2xxx_irqs[] = {
600 { "tsens-upper-lower", tsens_tm_irq_thread},
601 { "tsens-critical", tsens_tm_critical_irq_thread},
602};
603
604static int tsens2xxx_register_interrupts(struct tsens_device *tmdev)
605{
606 struct platform_device *pdev;
607 int i, rc;
608
609 if (!tmdev)
610 return -EINVAL;
611
612 pdev = tmdev->pdev;
613
614 for (i = 0; i < ARRAY_SIZE(tsens2xxx_irqs); i++) {
615 int irq;
616
617 irq = platform_get_irq_byname(pdev, tsens2xxx_irqs[i].name);
618 if (irq < 0) {
619 dev_err(&pdev->dev, "failed to get irq %s\n",
620 tsens2xxx_irqs[i].name);
621 return irq;
622 }
623
624 rc = devm_request_threaded_irq(&pdev->dev, irq, NULL,
625 tsens2xxx_irqs[i].handler,
626 IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
627 tsens2xxx_irqs[i].name, tmdev);
628 if (rc) {
629 dev_err(&pdev->dev, "failed to get irq %s\n",
630 tsens2xxx_irqs[i].name);
631 return rc;
632 }
633 enable_irq_wake(irq);
634 }
635
636 return 0;
637}
638
639static const struct tsens_ops ops_tsens2xxx = {
640 .hw_init = tsens2xxx_hw_init,
641 .get_temp = tsens2xxx_get_temp,
Siddartha Mohanadoss07b10612017-04-07 14:53:45 -0700642 .set_trips = tsens2xxx_set_trip_temp,
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800643 .interrupts_reg = tsens2xxx_register_interrupts,
644 .dbg = tsens2xxx_dbg,
Siddartha Mohanadossf86413d2017-07-18 13:44:31 -0700645 .sensor_en = tsens2xxx_hw_sensor_en,
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800646};
647
648const struct tsens_data data_tsens2xxx = {
649 .cycle_monitor = false,
Siddartha Mohanadoss64a5da32017-05-09 11:09:51 -0700650 .cycle_compltn_monitor_mask = 1,
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800651 .wd_bark = false,
Siddartha Mohanadoss64a5da32017-05-09 11:09:51 -0700652 .wd_bark_mask = 1,
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800653 .ops = &ops_tsens2xxx,
Ashok Jammigumpulaa1b7ec12017-11-23 15:37:44 +0530654 .mtc = true,
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800655};
656
657const struct tsens_data data_tsens23xx = {
658 .cycle_monitor = true,
Siddartha Mohanadoss64a5da32017-05-09 11:09:51 -0700659 .cycle_compltn_monitor_mask = 1,
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800660 .wd_bark = true,
Siddartha Mohanadoss64a5da32017-05-09 11:09:51 -0700661 .wd_bark_mask = 1,
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800662 .ops = &ops_tsens2xxx,
Ashok Jammigumpulaa1b7ec12017-11-23 15:37:44 +0530663 .mtc = false,
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800664};
665
666const struct tsens_data data_tsens24xx = {
667 .cycle_monitor = true,
Siddartha Mohanadoss64a5da32017-05-09 11:09:51 -0700668 .cycle_compltn_monitor_mask = 1,
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800669 .wd_bark = true,
Siddartha Mohanadoss64a5da32017-05-09 11:09:51 -0700670 /* Enable Watchdog monitoring by unmasking */
671 .wd_bark_mask = 0,
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800672 .ops = &ops_tsens2xxx,
Ashok Jammigumpulaa1b7ec12017-11-23 15:37:44 +0530673 .mtc = false,
Siddartha Mohanadoss41b4cd92017-02-21 14:34:23 -0800674};