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