xref: /rk3399_ARM-atf/plat/mediatek/drivers/thermal/src/thermal_lvts.c (revision c2fa83f97fab72a1f874aff8d4aeeeee7fb5240d)
1 /*
2  * Copyright (c) 2025, MediaTek Inc. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <errno.h>
8 #include <stdint.h>
9 #include <stdio.h>
10 #include <common/debug.h>
11 #include <drivers/delay_timer.h>
12 #include <lib/mmio.h>
13 #include <lib/mmio_poll.h>
14 #include <lib/utils_def.h>
15 
16 #include <lib/mtk_init/mtk_init.h>
17 #include <lpm/mt_lp_api.h>
18 #include <mtk_mmap_pool.h>
19 #include <soc_temp_lvts_interface.h>
20 #include <thermal_lvts.h>
21 
lvts_write_device_nodelay(struct lvts_data * lvts_data,uint32_t data,unsigned int tc_id)22 static void lvts_write_device_nodelay(struct lvts_data *lvts_data,
23 				      uint32_t data, unsigned int tc_id)
24 {
25 	uintptr_t base;
26 
27 	base = GET_BASE_ADDR(lvts_data, tc_id);
28 
29 	mmio_write_32(LVTS_CONFIG_0 + base, data);
30 }
31 
lvts_write_data_check(struct lvts_data * lvts_data,uint32_t data,unsigned int tc_id)32 static void lvts_write_data_check(struct lvts_data *lvts_data, uint32_t data,
33 				  unsigned int tc_id)
34 {
35 	uintptr_t base;
36 	int ret;
37 	uint32_t temp;
38 
39 	base = GET_BASE_ADDR(lvts_data, tc_id);
40 
41 	ret = mmio_read_32_poll_timeout(
42 		LVTS_CONFIG_0 + base,
43 		temp,
44 		((temp & (0x1 << DEVICE_ACCESS_START_BIT)) == 0),
45 		20);
46 
47 	if (ret)
48 		INFO("write device err: LVTS %d didn't ready, data 0x%x\n",
49 		     tc_id, data);
50 }
51 
lvts_write_all_device(struct lvts_data * lvts_data,uint32_t data)52 void lvts_write_all_device(struct lvts_data *lvts_data, uint32_t data)
53 {
54 	unsigned int tc_id;
55 	struct tc_settings *tc = lvts_data->tc;
56 
57 	for (tc_id = 0; tc_id < lvts_data->num_tc; tc_id++) {
58 		if (tc[tc_id].ctrl_on_off == CTRL_OFF)
59 			continue;
60 
61 		lvts_write_device_nodelay(lvts_data, data, tc_id);
62 	}
63 	dmbsy();
64 	for (tc_id = 0; tc_id < lvts_data->num_tc; tc_id++) {
65 		if (tc[tc_id].ctrl_on_off == CTRL_OFF)
66 			continue;
67 
68 		lvts_write_data_check(lvts_data, data, tc_id);
69 	}
70 }
71 
lvts_write_device(struct lvts_data * lvts_data,uint32_t data,unsigned int tc_id)72 void lvts_write_device(struct lvts_data *lvts_data, uint32_t data,
73 		       unsigned int tc_id)
74 {
75 	uintptr_t base;
76 	int ret;
77 	uint32_t temp;
78 
79 	base = GET_BASE_ADDR(lvts_data, tc_id);
80 
81 	mmio_write_32(LVTS_CONFIG_0 + base, data);
82 	dmbsy();
83 
84 	udelay(5);
85 
86 	ret = mmio_read_32_poll_timeout(
87 		LVTS_CONFIG_0 + base,
88 		temp,
89 		((temp & (0x1 << DEVICE_ACCESS_START_BIT)) == 0),
90 		20);
91 
92 	if (ret)
93 		INFO("write device err: LVTS %d didn't ready, data 0x%x\n",
94 		     tc_id, data);
95 
96 }
97 
lvts_read_device(struct lvts_data * lvts_data,uint32_t reg_idx,unsigned int tc_id)98 uint32_t lvts_read_device(struct lvts_data *lvts_data, uint32_t reg_idx,
99 			  unsigned int tc_id)
100 {
101 	uintptr_t base;
102 	uint32_t temp, data;
103 	uint32_t write_val = READ_DEVICE_REG(reg_idx);
104 	int ret;
105 
106 	base = GET_BASE_ADDR(lvts_data, tc_id);
107 	mmio_write_32(LVTS_CONFIG_0 + base, write_val);
108 	dmbsy();
109 
110 	ret = mmio_read_32_poll_timeout(
111 		LVTS_CONFIG_0 + base,
112 		temp,
113 		((temp & (0x1 << DEVICE_ACCESS_START_BIT)) == 0),
114 		20);
115 	if (ret)
116 		INFO("read device err: LVTS %d didn't ready, reg_idx 0x%x\n",
117 		     tc_id, reg_idx);
118 
119 	data = mmio_read_32(LVTSRDATA0_0 + base);
120 
121 	return data;
122 }
123 
124 #define THERMAL_SENSOR_IDLE_MASK (BIT(10) | BIT(7) | BIT(0))
125 #define HALF_WORD (16)
126 #define IDLE_CHECK_BIT1_MASK (BIT(10))
127 #define IDLE_CHECK_BIT2_MASK (BIT(7))
128 #define IDLE_CHECK_BIT3_MASK (BIT(0))
129 #define SHIFT_8 (8)
130 #define SHIFT_6 (6)
131 
lvts_thermal_check_all_sensing_point_idle(struct lvts_data * lvts_data)132 static uint32_t lvts_thermal_check_all_sensing_point_idle(
133 	struct lvts_data *lvts_data)
134 {
135 	unsigned int i;
136 	uintptr_t base;
137 	uint32_t temp, mask, error_code;
138 	struct tc_settings *tc = lvts_data->tc;
139 
140 	mask = THERMAL_SENSOR_IDLE_MASK;
141 
142 	for (i = 0; i < lvts_data->num_tc; i++) {
143 		if (tc[i].ctrl_on_off == CTRL_OFF)
144 			continue;
145 
146 		base = GET_BASE_ADDR(lvts_data, i);
147 		temp = mmio_read_32(base + LVTSMSRCTL1_0);
148 		/* Check if bit10=bit7=bit0=0 */
149 		if ((temp & mask) != 0) {
150 			error_code = (i << HALF_WORD)
151 				+ ((temp & IDLE_CHECK_BIT1_MASK) >> SHIFT_8)
152 				+ ((temp & IDLE_CHECK_BIT2_MASK) >> SHIFT_6)
153 				+ (temp & IDLE_CHECK_BIT3_MASK);
154 
155 			return error_code;
156 		}
157 	}
158 
159 	return 0;
160 }
161 
162 #define ITERATION_TIME (80)
163 #define DELAY_US       (2)
164 
wait_all_tc_sensing_point_idle(struct lvts_data * lvts_data)165 static void wait_all_tc_sensing_point_idle(struct lvts_data *lvts_data)
166 {
167 	unsigned int i;
168 	uintptr_t base;
169 	uint32_t temp, mask, error_code;
170 	int cnt = 0;
171 	struct tc_settings *tc = lvts_data->tc;
172 	static unsigned int no_idle_count;
173 
174 	mask = THERMAL_SENSOR_IDLE_MASK;
175 
176 	while (cnt < ITERATION_TIME) {
177 		temp = lvts_thermal_check_all_sensing_point_idle(lvts_data);
178 		if (temp == 0)
179 			goto TAIL;
180 
181 		udelay(DELAY_US);
182 		cnt++;
183 
184 	}
185 	no_idle_count++;
186 	mmio_write_32(THERMAL_CSRAM_BASE + NO_IDLE_COUNT_ADDR_OFFSET,
187 		no_idle_count);
188 
189 	for (i = 0; i < lvts_data->num_tc; i++) {
190 		if (tc[i].ctrl_on_off == CTRL_OFF)
191 			continue;
192 
193 		base = GET_BASE_ADDR(lvts_data, i);
194 		temp = mmio_read_32(LVTSMSRCTL1_0 + base);
195 		/*
196 		 * Error code
197 		 * 000: IDLE
198 		 * 001: Write transaction
199 		 * 010: Waiting for read after Write
200 		 * 011: Disable Continue fetching on Device
201 		 * 100: Read transaction
202 		 * 101: Set Device special Register for Voltage threshold
203 		 * 111: Set TSMCU number for Fetch
204 		 */
205 		if ((temp & mask) != 0) {
206 			error_code = ((temp & IDLE_CHECK_BIT1_MASK) >> SHIFT_8)
207 				+ ((temp & IDLE_CHECK_BIT2_MASK) >> SHIFT_6)
208 				+ (temp & IDLE_CHECK_BIT3_MASK);
209 
210 			INFO("LVTS %d sensing points not idle, error_code %d\n",
211 			     i, error_code);
212 		}
213 	}
214 TAIL:
215 	return;
216 }
217 
disable_all_sensing_points(struct lvts_data * lvts_data)218 static void disable_all_sensing_points(struct lvts_data *lvts_data)
219 {
220 	unsigned int i;
221 	uintptr_t base;
222 	struct tc_settings *tc = lvts_data->tc;
223 
224 	for (i = 0; i < lvts_data->num_tc; i++) {
225 		if (tc[i].ctrl_on_off == CTRL_OFF)
226 			continue;
227 
228 		base = GET_BASE_ADDR(lvts_data, i);
229 		mmio_write_32(LVTSMONCTL0_0 + base, DISABLE_SENSING_POINT);
230 	}
231 	dmbsy();
232 }
233 
enable_all_sensing_points(struct lvts_data * lvts_data)234 static void enable_all_sensing_points(struct lvts_data *lvts_data)
235 {
236 	struct tc_settings *tc = lvts_data->tc;
237 	unsigned int i, j, num;
238 	uintptr_t base;
239 	uint32_t flag;
240 
241 	for (i = 0; i < lvts_data->num_tc; i++) {
242 		if (tc[i].ctrl_on_off == CTRL_OFF)
243 			continue;
244 
245 		base = GET_BASE_ADDR(lvts_data, i);
246 		num = tc[i].num_sensor;
247 
248 		if (num > ALL_SENSING_POINTS) {
249 			INFO("%s, LVTS%d, illegal number of sensors: %d\n",
250 			     __func__, i, tc[i].num_sensor);
251 			continue;
252 		}
253 
254 		flag = LVTS_SINGLE_SENSE;
255 		for (j = 0; j < tc[i].num_sensor; j++) {
256 			if (tc[i].sensor_on_off[j] != SEN_ON)
257 				continue;
258 
259 			flag = flag | (0x1 << j);
260 		}
261 		mmio_write_32(LVTSMONCTL0_0 + base, flag);
262 	}
263 	dmbsy();
264 }
265 
set_polling_speed(struct lvts_data * lvts_data,unsigned int tc_id)266 void set_polling_speed(struct lvts_data *lvts_data, unsigned int tc_id)
267 {
268 	struct tc_settings *tc = lvts_data->tc;
269 	uint32_t lvts_mon_ctrl1, lvts_mon_ctrl2;
270 	uintptr_t base;
271 
272 	base = GET_BASE_ADDR(lvts_data, tc_id);
273 
274 	lvts_mon_ctrl1 = (((tc[tc_id].tc_speed.group_interval_delay
275 			<< 20) & GENMASK(29, 20)) |
276 			(tc[tc_id].tc_speed.period_unit &
277 			GENMASK(9, 0)));
278 	lvts_mon_ctrl2 = (((tc[tc_id].tc_speed.filter_interval_delay
279 			<< 16) & GENMASK(25, 16)) |
280 			(tc[tc_id].tc_speed.sensor_interval_delay
281 			& GENMASK(9, 0)));
282 	/*
283 	 * Clock source of LVTS thermal controller is 26MHz.
284 	 * Period unit is a base for all interval delays
285 	 * All interval delays must multiply it to convert a setting to time.
286 	 * Filter interval delay is a delay between two samples of the same
287 	 * sensor
288 	 * Sensor interval delay is a delay between two samples of differnet
289 	 * sensors
290 	 * Group interval delay is a delay between different rounds.
291 	 * For example:
292 	 *     If Period unit = C, filter delay = 1, sensor delay = 2, group
293 	 *     delay = 1,
294 	 *     and two sensors, TS1 and TS2, are in a LVTS thermal controller
295 	 *     and then
296 	 *     Period unit = C * 1/26M * 256 = 12 * 38.46ns * 256 = 118.149us
297 	 *     Filter interval delay = 1 * Period unit = 118.149us
298 	 *     Sensor interval delay = 2 * Period unit = 236.298us
299 	 *     Group interval delay = 1 * Period unit = 118.149us
300 	 *
301 	 *     TS1    TS1 ... TS1    TS2    TS2 ... TS2    TS1...
302 	 *        <--> Filter interval delay
303 	 *                       <--> Sensor interval delay
304 	 *                                             <--> Group interval delay
305 	 */
306 	mmio_write_32(LVTSMONCTL1_0 + base, lvts_mon_ctrl1);
307 	mmio_write_32(LVTSMONCTL2_0 + base, lvts_mon_ctrl2);
308 	dmbsy();
309 }
310 
set_hw_filter(struct lvts_data * lvts_data,unsigned int tc_id)311 void set_hw_filter(struct lvts_data *lvts_data, unsigned int tc_id)
312 {
313 	struct tc_settings *tc = lvts_data->tc;
314 	uint32_t option;
315 	uintptr_t base;
316 
317 	base = GET_BASE_ADDR(lvts_data, tc_id);
318 	option = tc[tc_id].hw_filter & 0x7;
319 	/* hw filter
320 	 * 000: Get one sample
321 	 * 001: Get 2 samples and average them
322 	 * 010: Get 4 samples, drop max&min and average the rest of 2 samples
323 	 * 011: Get 6 samples, drop max&min and average the rest of 4 samples
324 	 * 100: Get 10 samples, drop max&min and average the rest of 8 samples
325 	 * 101: Get 18 samples, drop max&min and average the rest of 16 samples
326 	 */
327 	option = (option << 9) | (option << 6) | (option << 3) | option;
328 
329 	mmio_write_32(LVTSMSRCTL0_0 + base, option);
330 	dmbsy();
331 }
332 
get_dominator_index(struct lvts_data * lvts_data,unsigned int tc_id)333 unsigned int get_dominator_index(struct lvts_data *lvts_data,
334 				 unsigned int tc_id)
335 {
336 	struct tc_settings *tc = lvts_data->tc;
337 	unsigned int d_index;
338 
339 	if (tc[tc_id].dominator_sensing_point == ALL_SENSING_POINTS) {
340 		d_index = ALL_SENSING_POINTS;
341 	} else if (tc[tc_id].dominator_sensing_point <
342 		tc[tc_id].num_sensor){
343 		d_index = tc[tc_id].dominator_sensing_point;
344 	} else {
345 		INFO("Error: LVTS%d, dominator_sensing_point= %d over %d\n",
346 		     tc_id, tc[tc_id].dominator_sensing_point,
347 		     tc[tc_id].num_sensor);
348 
349 		INFO("Use the sensing point 0 as the dominated sensor\n");
350 		d_index = SENSING_POINT0;
351 	}
352 
353 	return d_index;
354 }
355 
set_all_tc_hw_reboot(struct lvts_data * lvts_data)356 static void set_all_tc_hw_reboot(struct lvts_data *lvts_data)
357 {
358 	struct tc_settings *tc = lvts_data->tc;
359 	int trip_point;
360 	unsigned int i;
361 
362 	for (i = 0; i < lvts_data->num_tc; i++) {
363 		if (tc[i].ctrl_on_off == CTRL_OFF)
364 			continue;
365 
366 		trip_point = tc[i].hw_reboot_trip_point;
367 
368 		if (tc[i].num_sensor == 0)
369 			continue;
370 
371 		if (trip_point == DISABLE_THERMAL_HW_REBOOT) {
372 			disable_hw_reboot_interrupt(lvts_data, i);
373 			continue;
374 		}
375 
376 		set_tc_hw_reboot_threshold(lvts_data, trip_point, i);
377 	}
378 }
379 
lvts_lk_init_check(struct lvts_data * lvts_data)380 static bool lvts_lk_init_check(struct lvts_data *lvts_data)
381 {
382 	unsigned int i;
383 	uint32_t data;
384 	uintptr_t base;
385 	bool ret = false;
386 	struct tc_settings *tc = lvts_data->tc;
387 
388 	for (i = 0; i < lvts_data->num_tc; i++) {
389 		if (tc[i].ctrl_on_off == CTRL_OFF)
390 			continue;
391 
392 		base = GET_BASE_ADDR(lvts_data, i);
393 
394 		/* Check LVTS device ID */
395 		data = mmio_read_32(LVTSSPARE0_0 + base) & GENMASK(11, 0);
396 
397 		if (data == LK_LVTS_MAGIC) {
398 			mmio_write_32(LVTSSPARE0_0 + base, 0x0);
399 			ret = true;
400 		} else {
401 			ret = false;
402 			break;
403 		}
404 	}
405 	dmbsy();
406 	return ret;
407 }
408 
lvts_set_init_flag_tfa(struct lvts_data * lvts_data)409 static void lvts_set_init_flag_tfa(struct lvts_data *lvts_data)
410 {
411 	uintptr_t base;
412 	unsigned int i;
413 	struct tc_settings *tc = lvts_data->tc;
414 
415 	/* write TFA init done flag to inform kernel */
416 
417 	for (i = 0; i < lvts_data->num_tc; i++) {
418 		if (tc[i].ctrl_on_off == CTRL_OFF)
419 			continue;
420 
421 		base = GET_BASE_ADDR(lvts_data, i);
422 
423 		/* enable sensing point 0 */
424 		mmio_write_32(base + LVTSSPARE0_0, TFA_LVTS_MAGIC);
425 	}
426 	dmbsy();
427 }
428 
lvts_clear_init_flag_tfa(struct lvts_data * lvts_data)429 static void lvts_clear_init_flag_tfa(struct lvts_data *lvts_data)
430 {
431 	uintptr_t base;
432 	unsigned int i;
433 	struct tc_settings *tc = lvts_data->tc;
434 
435 	for (i = 0; i < lvts_data->num_tc; i++) {
436 		if (tc[i].ctrl_on_off == CTRL_OFF)
437 			continue;
438 
439 		base = GET_BASE_ADDR(lvts_data, i);
440 		mmio_write_32(LVTSSPARE0_0 + base, 0);
441 	}
442 	dmbsy();
443 }
444 
read_calibration_data(struct lvts_data * lvts_data)445 static int read_calibration_data(struct lvts_data *lvts_data)
446 {
447 	struct tc_settings *tc = lvts_data->tc;
448 	unsigned int i, j, s_index;
449 	uintptr_t base;
450 	struct sensor_cal_data *cal_data = &lvts_data->cal_data;
451 
452 	for (i = 0; i < lvts_data->num_tc; i++) {
453 		if (tc[i].ctrl_on_off == CTRL_OFF)
454 			continue;
455 
456 		base = GET_BASE_ADDR(lvts_data, i);
457 
458 		for (j = 0; j < tc[i].num_sensor; j++) {
459 			if (tc[i].sensor_on_off[j] != SEN_ON)
460 				continue;
461 
462 			s_index = tc[i].sensor_map[j];
463 
464 			cal_data->efuse_data[s_index] =
465 				mmio_read_32(LVTSEDATA00_0 + base + 0x4 * j);
466 
467 		}
468 	}
469 
470 	return 0;
471 }
472 
lvts_init(struct lvts_data * lvts_data)473 static int lvts_init(struct lvts_data *lvts_data)
474 {
475 	struct platform_ops *ops = &lvts_data->ops;
476 	int ret;
477 	bool lk_init = false;
478 
479 	mmio_write_32(THERMAL_CSRAM_BASE + CLOSE_FOOTPRINT_ADDR_OFFSET, 0x0);
480 
481 	thermal_clock_open();
482 
483 	lk_init = lvts_lk_init_check(lvts_data);
484 	if (lk_init == true) {
485 		ret = read_calibration_data(lvts_data);
486 
487 		lvts_set_init_flag_tfa(lvts_data);
488 		lvts_data->init_done = true;
489 		INFO("%s, LK init LVTS\n", __func__);
490 
491 		return ret;
492 	}
493 
494 	ops->lvts_reset(lvts_data);
495 
496 	if (ops->device_identification)
497 		ops->device_identification(lvts_data);
498 
499 	if (ops->device_enable_and_init)
500 		ops->device_enable_and_init(lvts_data);
501 
502 	if (IS_ENABLE(lvts_data, (int)FEATURE_DEVICE_AUTO_RCK)) {
503 		if (ops->device_enable_auto_rck)
504 			ops->device_enable_auto_rck(lvts_data);
505 	} else {
506 		if (ops->device_read_count_rc_n)
507 			ops->device_read_count_rc_n(lvts_data);
508 	}
509 
510 	if (ops->set_cal_data)
511 		ops->set_cal_data(lvts_data);
512 
513 	disable_all_sensing_points(lvts_data);
514 	wait_all_tc_sensing_point_idle(lvts_data);
515 	if (ops->init_controller)
516 		ops->init_controller(lvts_data);
517 
518 	set_all_tc_hw_reboot(lvts_data);
519 	enable_all_sensing_points(lvts_data);
520 	lvts_set_init_flag_tfa(lvts_data);
521 	lvts_data->init_done = true;
522 
523 	return 0;
524 }
525 
update_lvts_data_from_efuse(struct lvts_data * lvts_data)526 static int update_lvts_data_from_efuse(struct lvts_data *lvts_data)
527 {
528 	struct platform_ops *ops = &lvts_data->ops;
529 
530 	if (ops->get_calibration_data)
531 		ops->get_calibration_data(lvts_data);
532 
533 	if (ops->efuse_to_cal_data)
534 		ops->efuse_to_cal_data(lvts_data);
535 
536 	if (ops->check_cal_data)
537 		ops->check_cal_data(lvts_data);
538 
539 	if (ops->update_coef_data)
540 		ops->update_coef_data(lvts_data);
541 
542 	return 0;
543 }
544 
lvts_close(struct lvts_data * lvts_data)545 static void lvts_close(struct lvts_data *lvts_data)
546 {
547 	mmio_write_32(THERMAL_CSRAM_BASE + INIT_FOOTPRINT_ADDR_OFFSET, 0x0);
548 
549 	lvts_data->ops.lvts_reset(lvts_data);
550 
551 	lvts_clear_init_flag_tfa(lvts_data);
552 
553 	thermal_clock_close();
554 }
555 
set_calibration_data_v1(struct lvts_data * lvts_data)556 void set_calibration_data_v1(struct lvts_data *lvts_data)
557 {
558 	struct tc_settings *tc = lvts_data->tc;
559 	struct sensor_cal_data *cal_data = &lvts_data->cal_data;
560 	unsigned int i, j, s_index;
561 	uint32_t e_data;
562 	uintptr_t base;
563 
564 	for (i = 0; i < lvts_data->num_tc; i++) {
565 		if (tc[i].ctrl_on_off == CTRL_OFF)
566 			continue;
567 
568 		base = GET_BASE_ADDR(lvts_data, i);
569 
570 		for (j = 0; j < tc[i].num_sensor; j++) {
571 			if (tc[i].sensor_on_off[j] != SEN_ON)
572 				continue;
573 
574 			s_index = tc[i].sensor_map[j];
575 			if (IS_ENABLE(lvts_data, (int)FEATURE_DEVICE_AUTO_RCK))
576 				e_data = cal_data->count_r[s_index];
577 			else
578 				e_data = cal_data->efuse_data[s_index];
579 
580 			mmio_write_32(LVTSEDATA00_0 + base + 0x4 * j, e_data);
581 		}
582 	}
583 	dmbsy();
584 }
585 
lvts_thermal_init(void)586 static int lvts_thermal_init(void)
587 {
588 	struct lvts_data *lvts_data;
589 	int ret;
590 
591 	lvts_data = &lvts_data_instance;
592 
593 	ret = update_lvts_data_from_efuse(lvts_data);
594 	if (ret)
595 		return ret;
596 
597 	ret = lvts_init(lvts_data);
598 	if (ret)
599 		return ret;
600 
601 	return 0;
602 }
603 
604 /* suspend/resume */
lvts_suspend_callback(struct lvts_data * lvts_data)605 static int lvts_suspend_callback(struct lvts_data *lvts_data)
606 {
607 	lvts_close(lvts_data);
608 
609 	return 0;
610 }
611 
lvts_resume_callback(struct lvts_data * lvts_data)612 static int lvts_resume_callback(struct lvts_data *lvts_data)
613 {
614 	return lvts_init(lvts_data);
615 }
616 
lvts_pm_suspend_event_handler(const void * arg)617 static void *lvts_pm_suspend_event_handler(const void *arg)
618 {
619 	struct mt_lp_publish_event const *event =
620 		(struct mt_lp_publish_event const *) arg;
621 	struct lvts_data *lvts_data = &lvts_data_instance;
622 	int ret;
623 
624 	if (!event) {
625 		return NULL;
626 	}
627 
628 	if (event->id == MT_LPM_PUBEVENTS_SYS_POWER_OFF) {
629 		ret = lvts_suspend_callback(lvts_data);
630 		if (ret) {
631 			INFO("%s, %d, ret = %d\n", __func__, __LINE__, ret);
632 		}
633 		return (void *)arg;
634 
635 	} else if (event->id == MT_LPM_PUBEVENTS_SYS_POWER_ON) {
636 		ret = lvts_resume_callback(lvts_data);
637 		if (ret) {
638 			INFO("%s, %d, ret = %d\n", __func__, __LINE__, ret);
639 		}
640 		return (void *)arg;
641 	}
642 
643 	return NULL;
644 }
645 MT_LP_SUBSCRIBE_SUSPEND(lvts_pm_suspend_event_handler);
646 
647 MTK_PLAT_RUNTIME_INIT(lvts_thermal_init);
648