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