xref: /rk3399_ARM-atf/plat/mediatek/drivers/thermal/src/thermal_lvts.c (revision c2fa83f97fab72a1f874aff8d4aeeeee7fb5240d)
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