xref: /rk3399_ARM-atf/plat/mediatek/drivers/thermal/inc/thermal_lvts.h (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 #ifndef THERMAL_LVTS_H
8*3da2d29cSRaymond Sun #define THERMAL_LVTS_H
9*3da2d29cSRaymond Sun 
10*3da2d29cSRaymond Sun /* Definition or macro function */
11*3da2d29cSRaymond Sun #define LK_LVTS_MAGIC	(0x0000555)
12*3da2d29cSRaymond Sun #define TFA_LVTS_MAGIC	(0x0000777)
13*3da2d29cSRaymond Sun 
14*3da2d29cSRaymond Sun #define THERMAL_TEMP_INVALID	(-274000)
15*3da2d29cSRaymond Sun 
16*3da2d29cSRaymond Sun #define DEVICE_ACCESS_START_BIT	(24)
17*3da2d29cSRaymond Sun 
18*3da2d29cSRaymond Sun #define DISABLE_THERMAL_HW_REBOOT	(-274000)
19*3da2d29cSRaymond Sun 
20*3da2d29cSRaymond Sun #define CLOCK_26MHZ_CYCLE_NS	(38)
21*3da2d29cSRaymond Sun 
22*3da2d29cSRaymond Sun #define FEATURE_DEVICE_AUTO_RCK	(BIT(0))
23*3da2d29cSRaymond Sun 
24*3da2d29cSRaymond Sun #define IS_ENABLE(lvts_data, feature) \
25*3da2d29cSRaymond Sun 	(lvts_data->feature_bitmap & feature)
26*3da2d29cSRaymond Sun 
27*3da2d29cSRaymond Sun #define GET_BASE_ADDR(lvts_data, tc_id) \
28*3da2d29cSRaymond Sun 	(lvts_data->domain[lvts_data->tc[tc_id].domain_index].base \
29*3da2d29cSRaymond Sun 	+ lvts_data->tc[tc_id].addr_offset)
30*3da2d29cSRaymond Sun 
31*3da2d29cSRaymond Sun #define SET_TC_SPEED_IN_US(pu, gd, fd, sd) \
32*3da2d29cSRaymond Sun 	{ \
33*3da2d29cSRaymond Sun 		.period_unit = ((pu * 1000) / (256 * CLOCK_26MHZ_CYCLE_NS)), \
34*3da2d29cSRaymond Sun 		.group_interval_delay = (gd / pu), \
35*3da2d29cSRaymond Sun 		.filter_interval_delay = (fd / pu), \
36*3da2d29cSRaymond Sun 		.sensor_interval_delay = (sd / pu), \
37*3da2d29cSRaymond Sun 	}
38*3da2d29cSRaymond Sun 
39*3da2d29cSRaymond Sun #define GET_CAL_BITMASK(lvts_data, index, h, l) \
40*3da2d29cSRaymond Sun 	((index < lvts_data->num_efuse_addr) \
41*3da2d29cSRaymond Sun 	? ((lvts_data->efuse[index] & GENMASK(h, l)) >> l) \
42*3da2d29cSRaymond Sun 	: 0)
43*3da2d29cSRaymond Sun 
44*3da2d29cSRaymond Sun 
45*3da2d29cSRaymond Sun /* LVTS HW filter settings
46*3da2d29cSRaymond Sun  * 000: Get one sample
47*3da2d29cSRaymond Sun  * 001: Get 2 samples and average them
48*3da2d29cSRaymond Sun  * 010: Get 4 samples, drop max and min, then average the rest of 2 samples
49*3da2d29cSRaymond Sun  * 011: Get 6 samples, drop max and min, then average the rest of 4 samples
50*3da2d29cSRaymond Sun  * 100: Get 10 samples, drop max and min, then average the rest of 8 samples
51*3da2d29cSRaymond Sun  * 101: Get 18 samples, drop max and min, then average the rest of 16 samples
52*3da2d29cSRaymond Sun  */
53*3da2d29cSRaymond Sun enum lvts_hw_filter {
54*3da2d29cSRaymond Sun 	LVTS_FILTER_1,
55*3da2d29cSRaymond Sun 	LVTS_FILTER_2,
56*3da2d29cSRaymond Sun 	LVTS_FILTER_2_OF_4,
57*3da2d29cSRaymond Sun 	LVTS_FILTER_4_OF_6,
58*3da2d29cSRaymond Sun 	LVTS_FILTER_8_OF_10,
59*3da2d29cSRaymond Sun 	LVTS_FILTER_16_OF_18
60*3da2d29cSRaymond Sun };
61*3da2d29cSRaymond Sun 
62*3da2d29cSRaymond Sun enum lvts_sensing_point {
63*3da2d29cSRaymond Sun 	SENSING_POINT0,
64*3da2d29cSRaymond Sun 	SENSING_POINT1,
65*3da2d29cSRaymond Sun 	SENSING_POINT2,
66*3da2d29cSRaymond Sun 	SENSING_POINT3,
67*3da2d29cSRaymond Sun 	ALL_SENSING_POINTS
68*3da2d29cSRaymond Sun };
69*3da2d29cSRaymond Sun 
70*3da2d29cSRaymond Sun enum calibration_mode {
71*3da2d29cSRaymond Sun 	CALI_NT,
72*3da2d29cSRaymond Sun 	CALI_HT,
73*3da2d29cSRaymond Sun 	ALL_CALI_MODES
74*3da2d29cSRaymond Sun };
75*3da2d29cSRaymond Sun 
76*3da2d29cSRaymond Sun /* Data structure */
77*3da2d29cSRaymond Sun struct lvts_data;
78*3da2d29cSRaymond Sun 
79*3da2d29cSRaymond Sun struct speed_settings {
80*3da2d29cSRaymond Sun 	unsigned int period_unit;
81*3da2d29cSRaymond Sun 	unsigned int group_interval_delay;
82*3da2d29cSRaymond Sun 	unsigned int filter_interval_delay;
83*3da2d29cSRaymond Sun 	unsigned int sensor_interval_delay;
84*3da2d29cSRaymond Sun };
85*3da2d29cSRaymond Sun 
86*3da2d29cSRaymond Sun struct formula_coeff {
87*3da2d29cSRaymond Sun 	int a[ALL_SENSING_POINTS];
88*3da2d29cSRaymond Sun 	unsigned int golden_temp;
89*3da2d29cSRaymond Sun 	enum calibration_mode cali_mode;
90*3da2d29cSRaymond Sun };
91*3da2d29cSRaymond Sun 
92*3da2d29cSRaymond Sun enum sensor_switch_status {
93*3da2d29cSRaymond Sun 	SEN_OFF,
94*3da2d29cSRaymond Sun 	SEN_ON
95*3da2d29cSRaymond Sun };
96*3da2d29cSRaymond Sun 
97*3da2d29cSRaymond Sun enum controller_switch_status {
98*3da2d29cSRaymond Sun 	CTRL_OFF,
99*3da2d29cSRaymond Sun 	CTRL_ON
100*3da2d29cSRaymond Sun };
101*3da2d29cSRaymond Sun 
102*3da2d29cSRaymond Sun struct tc_settings {
103*3da2d29cSRaymond Sun 	unsigned int domain_index;
104*3da2d29cSRaymond Sun 	uintptr_t addr_offset;
105*3da2d29cSRaymond Sun 	unsigned int num_sensor;
106*3da2d29cSRaymond Sun 	unsigned int sensor_map[ALL_SENSING_POINTS]; /* In sensor ID */
107*3da2d29cSRaymond Sun 	enum controller_switch_status ctrl_on_off;
108*3da2d29cSRaymond Sun 	enum sensor_switch_status sensor_on_off[ALL_SENSING_POINTS];
109*3da2d29cSRaymond Sun 	struct speed_settings tc_speed;
110*3da2d29cSRaymond Sun 	/* HW filter setting
111*3da2d29cSRaymond Sun 	 * 000: Get one sample
112*3da2d29cSRaymond Sun 	 * 001: Get 2 samples and average them
113*3da2d29cSRaymond Sun 	 * 010: Get 4 samples, drop max&min and average the rest of 2 samples
114*3da2d29cSRaymond Sun 	 * 011: Get 6 samples, drop max&min and average the rest of 4 samples
115*3da2d29cSRaymond Sun 	 * 100: Get 10 samples, drop max&min and average the rest of 8 samples
116*3da2d29cSRaymond Sun 	 * 101: Get 18 samples, drop max&min and average the rest of 16 samples
117*3da2d29cSRaymond Sun 	 */
118*3da2d29cSRaymond Sun 	uint32_t hw_filter;
119*3da2d29cSRaymond Sun 	/* Dominator_sensing point is used to select a sensing point
120*3da2d29cSRaymond Sun 	 * and reference its temperature to trigger Thermal HW Reboot
121*3da2d29cSRaymond Sun 	 * When it is ALL_SENSING_POINTS, it will select all sensing points
122*3da2d29cSRaymond Sun 	 */
123*3da2d29cSRaymond Sun 	enum lvts_sensing_point dominator_sensing_point;
124*3da2d29cSRaymond Sun 	int hw_reboot_trip_point; /* -274000: Disable HW reboot */
125*3da2d29cSRaymond Sun 	uint32_t irq_bit;
126*3da2d29cSRaymond Sun 	struct formula_coeff coeff;
127*3da2d29cSRaymond Sun };
128*3da2d29cSRaymond Sun 
129*3da2d29cSRaymond Sun struct sensor_cal_data {
130*3da2d29cSRaymond Sun 	unsigned int golden_temp;
131*3da2d29cSRaymond Sun 	unsigned int golden_temp_ht;
132*3da2d29cSRaymond Sun 	uint32_t cali_mode;
133*3da2d29cSRaymond Sun 	uint32_t *count_r;
134*3da2d29cSRaymond Sun 	uint32_t *count_rc;
135*3da2d29cSRaymond Sun 	uint32_t *count_rc_now;
136*3da2d29cSRaymond Sun 	uint32_t *efuse_data;
137*3da2d29cSRaymond Sun 
138*3da2d29cSRaymond Sun 	unsigned int default_golden_temp;
139*3da2d29cSRaymond Sun 	unsigned int default_golden_temp_ht;
140*3da2d29cSRaymond Sun 	uint32_t default_count_r;
141*3da2d29cSRaymond Sun 	uint32_t default_count_rc;
142*3da2d29cSRaymond Sun };
143*3da2d29cSRaymond Sun 
144*3da2d29cSRaymond Sun struct platform_ops {
145*3da2d29cSRaymond Sun 	void (*lvts_reset)(struct lvts_data *lvts_data);
146*3da2d29cSRaymond Sun 	void (*device_identification)(struct lvts_data *lvts_data);
147*3da2d29cSRaymond Sun 	void (*get_calibration_data)(struct lvts_data *lvts_data);
148*3da2d29cSRaymond Sun 	void (*efuse_to_cal_data)(struct lvts_data *lvts_data);
149*3da2d29cSRaymond Sun 	void (*device_enable_and_init)(struct lvts_data *lvts_data);
150*3da2d29cSRaymond Sun 	void (*device_enable_auto_rck)(struct lvts_data *lvts_data);
151*3da2d29cSRaymond Sun 	int (*device_read_count_rc_n)(struct lvts_data *lvts_data);
152*3da2d29cSRaymond Sun 	void (*set_cal_data)(struct lvts_data *lvts_data);
153*3da2d29cSRaymond Sun 	void (*init_controller)(struct lvts_data *lvts_data);
154*3da2d29cSRaymond Sun 	int (*lvts_raw_to_temp)(const struct formula_coeff *co,
155*3da2d29cSRaymond Sun 				unsigned int id, unsigned int msr_raw);
156*3da2d29cSRaymond Sun 	unsigned int (*lvts_temp_to_raw)(const struct formula_coeff *co,
157*3da2d29cSRaymond Sun 					 unsigned int id, int temp);
158*3da2d29cSRaymond Sun 	void (*check_cal_data)(struct lvts_data *lvts_data);
159*3da2d29cSRaymond Sun 	void (*update_coef_data)(struct lvts_data *lvts_data);
160*3da2d29cSRaymond Sun };
161*3da2d29cSRaymond Sun 
162*3da2d29cSRaymond Sun struct power_domain {
163*3da2d29cSRaymond Sun 	uintptr_t base;	/* LVTS base addresses */
164*3da2d29cSRaymond Sun 	uintptr_t reset_base;
165*3da2d29cSRaymond Sun 	uintptr_t reset_set_offset;
166*3da2d29cSRaymond Sun 	uintptr_t reset_clr_offset;
167*3da2d29cSRaymond Sun 	uint32_t reset_set_bitnum;
168*3da2d29cSRaymond Sun 	uint32_t reset_clr_bitnum;
169*3da2d29cSRaymond Sun };
170*3da2d29cSRaymond Sun 
171*3da2d29cSRaymond Sun struct sensor_data {
172*3da2d29cSRaymond Sun 	int temp;		/* Current temperature */
173*3da2d29cSRaymond Sun 	unsigned int msr_raw;	/* MSR raw data from LVTS */
174*3da2d29cSRaymond Sun };
175*3da2d29cSRaymond Sun 
176*3da2d29cSRaymond Sun struct lvts_data {
177*3da2d29cSRaymond Sun 	unsigned int num_domain;
178*3da2d29cSRaymond Sun 	struct power_domain *domain;
179*3da2d29cSRaymond Sun 
180*3da2d29cSRaymond Sun 	unsigned int num_tc;		/* Number of LVTS thermal controllers */
181*3da2d29cSRaymond Sun 	struct tc_settings *tc;
182*3da2d29cSRaymond Sun 	int counting_window_us;		/* LVTS device counting window */
183*3da2d29cSRaymond Sun 
184*3da2d29cSRaymond Sun 	unsigned int num_sensor;	/* Number of sensors in this platform */
185*3da2d29cSRaymond Sun 	struct sensor_data *sen_data;
186*3da2d29cSRaymond Sun 
187*3da2d29cSRaymond Sun 	struct platform_ops ops;
188*3da2d29cSRaymond Sun 	int feature_bitmap;		/* Show what features are enabled */
189*3da2d29cSRaymond Sun 
190*3da2d29cSRaymond Sun 	unsigned int num_efuse_addr;
191*3da2d29cSRaymond Sun 	uint32_t *efuse;
192*3da2d29cSRaymond Sun 
193*3da2d29cSRaymond Sun 	uint32_t *irq_bitmap;
194*3da2d29cSRaymond Sun 
195*3da2d29cSRaymond Sun 	struct sensor_cal_data cal_data;
196*3da2d29cSRaymond Sun 	int enable_dump_log;
197*3da2d29cSRaymond Sun 	bool init_done;
198*3da2d29cSRaymond Sun };
199*3da2d29cSRaymond Sun 
200*3da2d29cSRaymond Sun /* LVTS device register */
201*3da2d29cSRaymond Sun #define RG_TSFM_CTRL_0		0x03
202*3da2d29cSRaymond Sun #define RG_TSFM_CTRL_3		0x06
203*3da2d29cSRaymond Sun #define RG_TSV2F_CTRL_0		0x08
204*3da2d29cSRaymond Sun #define RG_TSV2F_CTRL_1		0x09
205*3da2d29cSRaymond Sun #define RG_TSV2F_CTRL_2		0x0A
206*3da2d29cSRaymond Sun #define RG_TSV2F_CTRL_3		0x0B
207*3da2d29cSRaymond Sun #define RG_TSV2F_CTRL_4		0x0C
208*3da2d29cSRaymond Sun #define RG_TSV2F_CTRL_5		0x0D
209*3da2d29cSRaymond Sun #define RG_TSV2F_CTRL_6		0x0E
210*3da2d29cSRaymond Sun #define RG_DID_LVTS		0xFC
211*3da2d29cSRaymond Sun #define RG_TSFM_RST		0xFF
212*3da2d29cSRaymond Sun 
213*3da2d29cSRaymond Sun /* LVTS controller register */
214*3da2d29cSRaymond Sun #define LVTSMONCTL0_0	0x000
215*3da2d29cSRaymond Sun #define LVTS_SINGLE_SENSE	(1UL << 9)
216*3da2d29cSRaymond Sun #define DISABLE_SENSING_POINT	(LVTS_SINGLE_SENSE | 0x0)
217*3da2d29cSRaymond Sun #define LVTSMONCTL1_0		0x004
218*3da2d29cSRaymond Sun #define LVTSMONCTL2_0		0x008
219*3da2d29cSRaymond Sun #define LVTSMONINT_0		0x00C
220*3da2d29cSRaymond Sun #define STAGE3_INT_EN		(1UL << 31)
221*3da2d29cSRaymond Sun 
222*3da2d29cSRaymond Sun #define HIGH_OFFSET3_INT_EN	(1UL << 25)
223*3da2d29cSRaymond Sun #define HIGH_OFFSET2_INT_EN	(1UL << 13)
224*3da2d29cSRaymond Sun #define HIGH_OFFSET1_INT_EN	(1UL << 8)
225*3da2d29cSRaymond Sun #define HIGH_OFFSET0_INT_EN	(1UL << 3)
226*3da2d29cSRaymond Sun 
227*3da2d29cSRaymond Sun #define LOW_OFFSET3_INT_EN	(1UL << 24)
228*3da2d29cSRaymond Sun #define LOW_OFFSET2_INT_EN	(1UL << 12)
229*3da2d29cSRaymond Sun #define LOW_OFFSET1_INT_EN	(1UL << 7)
230*3da2d29cSRaymond Sun #define LOW_OFFSET0_INT_EN	(1UL << 2)
231*3da2d29cSRaymond Sun 
232*3da2d29cSRaymond Sun #define LVTSOFFSETH_0		0x030
233*3da2d29cSRaymond Sun #define LVTSOFFSETL_0		0x034
234*3da2d29cSRaymond Sun #define LVTSMSRCTL0_0		0x038
235*3da2d29cSRaymond Sun #define LVTSMSRCTL1_0		0x03C
236*3da2d29cSRaymond Sun #define LVTSTSSEL_0		0x040
237*3da2d29cSRaymond Sun #define LVTSCALSCALE_0		0x048
238*3da2d29cSRaymond Sun #define SET_CALC_SCALE_RULES	0x00000300
239*3da2d29cSRaymond Sun #define LVTS_ID_0		0x04C
240*3da2d29cSRaymond Sun #define LVTS_CONFIG_0		0x050
241*3da2d29cSRaymond Sun #define LVTSEDATA00_0		0x054
242*3da2d29cSRaymond Sun #define MRS_RAW_MASK		GENMASK(15, 0)
243*3da2d29cSRaymond Sun #define LVTSRDATA0_0		0x0B0
244*3da2d29cSRaymond Sun #define LVTSPROTCTL_0		0x0C0
245*3da2d29cSRaymond Sun #define PROTOFFSET		GENMASK(15, 0)
246*3da2d29cSRaymond Sun #define LVTSPROTTC_0		0x0CC
247*3da2d29cSRaymond Sun #define LVTSCLKEN_0		0x0E4
248*3da2d29cSRaymond Sun #define ENABLE_LVTS_CTRL_CLK	(1)
249*3da2d29cSRaymond Sun #define LVTSSPARE0_0		0x0F0
250*3da2d29cSRaymond Sun 
251*3da2d29cSRaymond Sun #define BROADCAST_ID_UPDATE	(1UL << 26)
252*3da2d29cSRaymond Sun #define DEVICE_SENSING_STATUS	(1UL << 25)
253*3da2d29cSRaymond Sun #define DEVICE_ACCESS_STARTUS	(1UL << 24)
254*3da2d29cSRaymond Sun #define WRITE_ACCESS		(1UL << 16)
255*3da2d29cSRaymond Sun 
256*3da2d29cSRaymond Sun #define DEVICE_WRITE		(1UL << 31 | 1UL << 30 | DEVICE_ACCESS_STARTUS \
257*3da2d29cSRaymond Sun 				| 1UL << 17 | WRITE_ACCESS)
258*3da2d29cSRaymond Sun 
259*3da2d29cSRaymond Sun 
260*3da2d29cSRaymond Sun #define DEVICE_READ		(1UL << 31 | 1UL << 30 | DEVICE_ACCESS_STARTUS \
261*3da2d29cSRaymond Sun 				| 1UL << 17)
262*3da2d29cSRaymond Sun #define RESET_ALL_DEVICES	(DEVICE_WRITE | RG_TSFM_RST << 8 | 0xFF)
263*3da2d29cSRaymond Sun #define READ_BACK_DEVICE_ID	(1UL << 31 | 1UL << 30 | BROADCAST_ID_UPDATE \
264*3da2d29cSRaymond Sun 				| DEVICE_ACCESS_STARTUS | 1UL << 17 \
265*3da2d29cSRaymond Sun 				| RG_DID_LVTS << 8)
266*3da2d29cSRaymond Sun 
267*3da2d29cSRaymond Sun #define READ_DEVICE_REG(reg_idx)	(DEVICE_READ | reg_idx << 8 | 0x00)
268*3da2d29cSRaymond Sun 
269*3da2d29cSRaymond Sun /* LVTS register mask */
270*3da2d29cSRaymond Sun #define INIT_FOOTPRINT_ADDR_OFFSET	(0x1F8)
271*3da2d29cSRaymond Sun #define CLOSE_FOOTPRINT_ADDR_OFFSET	(0x1FC)
272*3da2d29cSRaymond Sun #define NO_IDLE_COUNT_ADDR_OFFSET	(0x1E4)
273*3da2d29cSRaymond Sun 
274*3da2d29cSRaymond Sun void thermal_clock_open(void);
275*3da2d29cSRaymond Sun void thermal_clock_close(void);
276*3da2d29cSRaymond Sun void set_polling_speed(struct lvts_data *lvts_data, unsigned int tc_id);
277*3da2d29cSRaymond Sun void set_hw_filter(struct lvts_data *lvts_data, unsigned int tc_id);
278*3da2d29cSRaymond Sun void lvts_write_all_device(struct lvts_data *lvts_data, uint32_t data);
279*3da2d29cSRaymond Sun void lvts_write_device(struct lvts_data *lvts_data, uint32_t data,
280*3da2d29cSRaymond Sun 		       unsigned int tc_id);
281*3da2d29cSRaymond Sun uint32_t lvts_read_device(struct lvts_data *lvts_data, uint32_t reg_idx,
282*3da2d29cSRaymond Sun 			  unsigned int tc_id);
283*3da2d29cSRaymond Sun void set_calibration_data_v1(struct lvts_data *lvts_data);
284*3da2d29cSRaymond Sun unsigned int get_dominator_index(struct lvts_data *lvts_data,
285*3da2d29cSRaymond Sun 				 unsigned int tc_id);
286*3da2d29cSRaymond Sun void disable_hw_reboot_interrupt(struct lvts_data *lvts_data,
287*3da2d29cSRaymond Sun 				 unsigned int tc_id);
288*3da2d29cSRaymond Sun void enable_hw_reboot_interrupt(struct lvts_data *lvts_data,
289*3da2d29cSRaymond Sun 				unsigned int tc_id);
290*3da2d29cSRaymond Sun void set_tc_hw_reboot_threshold(struct lvts_data *lvts_data, int trip_point,
291*3da2d29cSRaymond Sun 				unsigned int tc_id);
292*3da2d29cSRaymond Sun 
293*3da2d29cSRaymond Sun extern struct lvts_data lvts_data_instance;
294*3da2d29cSRaymond Sun 
295*3da2d29cSRaymond Sun #endif /* THERMAL_LVTS_H */
296