xref: /linux/drivers/accel/ivpu/ivpu_hw_btrs.c (revision fab183d632628381b466a41479489541ac0e29a0)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2020-2026 Intel Corporation
4  */
5 
6 #include <linux/units.h>
7 
8 #include "ivpu_drv.h"
9 #include "ivpu_hw.h"
10 #include "ivpu_hw_btrs.h"
11 #include "ivpu_hw_btrs_lnl_reg.h"
12 #include "ivpu_hw_btrs_mtl_reg.h"
13 #include "ivpu_hw_reg_io.h"
14 #include "ivpu_jsm_msg.h"
15 #include "ivpu_pm.h"
16 
17 #define BTRS_MTL_IRQ_MASK ((REG_FLD(VPU_HW_BTRS_MTL_INTERRUPT_STAT, ATS_ERR)) | \
18 			   (REG_FLD(VPU_HW_BTRS_MTL_INTERRUPT_STAT, UFI_ERR)))
19 
20 #define BTRS_LNL_IRQ_MASK ((REG_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, ATS_ERR)) | \
21 			   (REG_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, CFI0_ERR)) | \
22 			   (REG_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, CFI1_ERR)) | \
23 			   (REG_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, IMR0_ERR)) | \
24 			   (REG_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, IMR1_ERR)) | \
25 			   (REG_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, SURV_ERR)))
26 
27 #define BTRS_MTL_ALL_IRQ_MASK (BTRS_MTL_IRQ_MASK | (REG_FLD(VPU_HW_BTRS_MTL_INTERRUPT_STAT, \
28 			       FREQ_CHANGE)))
29 
30 #define BTRS_IRQ_DISABLE_MASK ((u32)-1)
31 
32 #define BTRS_LNL_ALL_IRQ_MASK ((u32)-1)
33 
34 
35 #define PLL_CDYN_DEFAULT               0x80
36 #define PLL_EPP_DEFAULT                0x80
37 #define PLL_REF_CLK_FREQ_MHZ           50
38 
39 #define PLL_TIMEOUT_US		       (1500 * USEC_PER_MSEC)
40 #define IDLE_TIMEOUT_US		       (5 * USEC_PER_MSEC)
41 #define TIMEOUT_US                     (150 * USEC_PER_MSEC)
42 
43 /* Work point configuration values */
44 #define WP_CONFIG(tile, ratio)         (((tile) << 8) | (ratio))
45 #define MTL_CONFIG_1_TILE              0x01
46 #define MTL_CONFIG_2_TILE              0x02
47 #define MTL_PLL_RATIO_5_3              0x01
48 #define MTL_PLL_RATIO_4_3              0x02
49 #define BTRS_MTL_TILE_FUSE_ENABLE_BOTH 0x0
50 #define BTRS_MTL_TILE_SKU_BOTH         0x3630
51 
52 #define BTRS_LNL_TILE_MAX_NUM          6
53 #define BTRS_LNL_TILE_MAX_MASK         0x3f
54 
55 #define WEIGHTS_DEFAULT                0xf711f711u
56 #define WEIGHTS_ATS_DEFAULT            0x0000f711u
57 
58 #define DCT_REQ                        0x2
59 #define DCT_ENABLE                     0x1
60 #define DCT_DISABLE                    0x0
61 
ivpu_hw_btrs_irqs_clear_with_0_mtl(struct ivpu_device * vdev)62 int ivpu_hw_btrs_irqs_clear_with_0_mtl(struct ivpu_device *vdev)
63 {
64 	REGB_WR32(VPU_HW_BTRS_MTL_INTERRUPT_STAT, BTRS_MTL_ALL_IRQ_MASK);
65 	if (REGB_RD32(VPU_HW_BTRS_MTL_INTERRUPT_STAT) == BTRS_MTL_ALL_IRQ_MASK) {
66 		/* Writing 1s does not clear the interrupt status register */
67 		REGB_WR32(VPU_HW_BTRS_MTL_INTERRUPT_STAT, 0x0);
68 		return true;
69 	}
70 
71 	return false;
72 }
73 
freq_ratios_init_mtl(struct ivpu_device * vdev)74 static void freq_ratios_init_mtl(struct ivpu_device *vdev)
75 {
76 	struct ivpu_hw_info *hw = vdev->hw;
77 	u32 fmin_fuse, fmax_fuse;
78 
79 	fmin_fuse = REGB_RD32(VPU_HW_BTRS_MTL_FMIN_FUSE);
80 	hw->pll.min_ratio = REG_GET_FLD(VPU_HW_BTRS_MTL_FMIN_FUSE, MIN_RATIO, fmin_fuse);
81 	hw->pll.pn_ratio = REG_GET_FLD(VPU_HW_BTRS_MTL_FMIN_FUSE, PN_RATIO, fmin_fuse);
82 
83 	fmax_fuse = REGB_RD32(VPU_HW_BTRS_MTL_FMAX_FUSE);
84 	hw->pll.max_ratio = REG_GET_FLD(VPU_HW_BTRS_MTL_FMAX_FUSE, MAX_RATIO, fmax_fuse);
85 }
86 
freq_ratios_init_lnl(struct ivpu_device * vdev)87 static void freq_ratios_init_lnl(struct ivpu_device *vdev)
88 {
89 	struct ivpu_hw_info *hw = vdev->hw;
90 	u32 fmin_fuse, fmax_fuse;
91 
92 	fmin_fuse = REGB_RD32(VPU_HW_BTRS_LNL_FMIN_FUSE);
93 	hw->pll.min_ratio = REG_GET_FLD(VPU_HW_BTRS_LNL_FMIN_FUSE, MIN_RATIO, fmin_fuse);
94 	hw->pll.pn_ratio = REG_GET_FLD(VPU_HW_BTRS_LNL_FMIN_FUSE, PN_RATIO, fmin_fuse);
95 
96 	fmax_fuse = REGB_RD32(VPU_HW_BTRS_LNL_FMAX_FUSE);
97 	hw->pll.max_ratio = REG_GET_FLD(VPU_HW_BTRS_LNL_FMAX_FUSE, MAX_RATIO, fmax_fuse);
98 }
99 
ivpu_hw_btrs_freq_ratios_init(struct ivpu_device * vdev)100 void ivpu_hw_btrs_freq_ratios_init(struct ivpu_device *vdev)
101 {
102 	struct ivpu_hw_info *hw = vdev->hw;
103 
104 	if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
105 		freq_ratios_init_mtl(vdev);
106 	else
107 		freq_ratios_init_lnl(vdev);
108 
109 	hw->pll.min_ratio = clamp_t(u8, ivpu_pll_min_ratio, hw->pll.min_ratio, hw->pll.max_ratio);
110 	hw->pll.max_ratio = clamp_t(u8, ivpu_pll_max_ratio, hw->pll.min_ratio, hw->pll.max_ratio);
111 	hw->pll.pn_ratio = clamp_t(u8, hw->pll.pn_ratio, hw->pll.min_ratio, hw->pll.max_ratio);
112 	hw->pll.cfg_max_ratio = hw->pll.max_ratio;
113 	hw->pll.cfg_min_ratio = hw->pll.min_ratio;
114 }
115 
tile_disable_check(u32 config)116 static bool tile_disable_check(u32 config)
117 {
118 	/* Allowed values: 0 or one bit from range 0-5 (6 tiles) */
119 	if (config == 0)
120 		return true;
121 
122 	if (config > BIT(BTRS_LNL_TILE_MAX_NUM - 1))
123 		return false;
124 
125 	if ((config & (config - 1)) == 0)
126 		return true;
127 
128 	return false;
129 }
130 
read_tile_config_fuse(struct ivpu_device * vdev,u32 * tile_fuse_config)131 static int read_tile_config_fuse(struct ivpu_device *vdev, u32 *tile_fuse_config)
132 {
133 	u32 fuse;
134 	u32 config;
135 
136 	fuse = REGB_RD32(VPU_HW_BTRS_LNL_TILE_FUSE);
137 	if (!REG_TEST_FLD(VPU_HW_BTRS_LNL_TILE_FUSE, VALID, fuse)) {
138 		ivpu_err(vdev, "Fuse: invalid (0x%x)\n", fuse);
139 		return -EIO;
140 	}
141 
142 	config = REG_GET_FLD(VPU_HW_BTRS_LNL_TILE_FUSE, CONFIG, fuse);
143 	if (!tile_disable_check(config))
144 		ivpu_warn(vdev, "More than 1 tile disabled, tile fuse config mask: 0x%x\n", config);
145 
146 	ivpu_dbg(vdev, MISC, "Tile disable config mask: 0x%x\n", config);
147 
148 	*tile_fuse_config = config;
149 	return 0;
150 }
151 
info_init_mtl(struct ivpu_device * vdev)152 static int info_init_mtl(struct ivpu_device *vdev)
153 {
154 	struct ivpu_hw_info *hw = vdev->hw;
155 
156 	hw->tile_fuse = BTRS_MTL_TILE_FUSE_ENABLE_BOTH;
157 	hw->sku = BTRS_MTL_TILE_SKU_BOTH;
158 	hw->config = WP_CONFIG(MTL_CONFIG_2_TILE, MTL_PLL_RATIO_4_3);
159 
160 	return 0;
161 }
162 
info_init_lnl(struct ivpu_device * vdev)163 static int info_init_lnl(struct ivpu_device *vdev)
164 {
165 	struct ivpu_hw_info *hw = vdev->hw;
166 	u32 tile_fuse_config;
167 	int ret;
168 
169 	ret = read_tile_config_fuse(vdev, &tile_fuse_config);
170 	if (ret)
171 		return ret;
172 
173 	hw->tile_fuse = tile_fuse_config;
174 	hw->pll.profiling_freq = PLL_PROFILING_FREQ_DEFAULT;
175 
176 	return 0;
177 }
178 
ivpu_hw_btrs_info_init(struct ivpu_device * vdev)179 int ivpu_hw_btrs_info_init(struct ivpu_device *vdev)
180 {
181 	if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
182 		return info_init_mtl(vdev);
183 	else
184 		return info_init_lnl(vdev);
185 }
186 
wp_request_sync(struct ivpu_device * vdev)187 static int wp_request_sync(struct ivpu_device *vdev)
188 {
189 	if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
190 		return REGB_POLL_FLD(VPU_HW_BTRS_MTL_WP_REQ_CMD, SEND, 0, PLL_TIMEOUT_US);
191 	else
192 		return REGB_POLL_FLD(VPU_HW_BTRS_LNL_WP_REQ_CMD, SEND, 0, PLL_TIMEOUT_US);
193 }
194 
wait_for_status_ready(struct ivpu_device * vdev,bool enable)195 static int wait_for_status_ready(struct ivpu_device *vdev, bool enable)
196 {
197 	u32 exp_val = enable ? 0x1 : 0x0;
198 
199 	if (IVPU_WA(punit_disabled))
200 		return 0;
201 
202 	if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
203 		return REGB_POLL_FLD(VPU_HW_BTRS_MTL_VPU_STATUS, READY, exp_val, PLL_TIMEOUT_US);
204 	else
205 		return REGB_POLL_FLD(VPU_HW_BTRS_LNL_VPU_STATUS, READY, exp_val, PLL_TIMEOUT_US);
206 }
207 
208 struct wp_request {
209 	u16 min;
210 	u16 max;
211 	u16 target;
212 	u16 cfg;
213 	u16 epp;
214 	u16 cdyn;
215 };
216 
wp_request_mtl(struct ivpu_device * vdev,struct wp_request * wp)217 static void wp_request_mtl(struct ivpu_device *vdev, struct wp_request *wp)
218 {
219 	u32 val;
220 
221 	val = REGB_RD32(VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD0);
222 	val = REG_SET_FLD_NUM(VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD0, MIN_RATIO, wp->min, val);
223 	val = REG_SET_FLD_NUM(VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD0, MAX_RATIO, wp->max, val);
224 	REGB_WR32(VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD0, val);
225 
226 	val = REGB_RD32(VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD1);
227 	val = REG_SET_FLD_NUM(VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD1, TARGET_RATIO, wp->target, val);
228 	val = REG_SET_FLD_NUM(VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD1, EPP, PLL_EPP_DEFAULT, val);
229 	REGB_WR32(VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD1, val);
230 
231 	val = REGB_RD32(VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD2);
232 	val = REG_SET_FLD_NUM(VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD2, CONFIG, wp->cfg, val);
233 	REGB_WR32(VPU_HW_BTRS_MTL_WP_REQ_PAYLOAD2, val);
234 
235 	val = REGB_RD32(VPU_HW_BTRS_MTL_WP_REQ_CMD);
236 	val = REG_SET_FLD(VPU_HW_BTRS_MTL_WP_REQ_CMD, SEND, val);
237 	REGB_WR32(VPU_HW_BTRS_MTL_WP_REQ_CMD, val);
238 }
239 
wp_request_lnl(struct ivpu_device * vdev,struct wp_request * wp)240 static void wp_request_lnl(struct ivpu_device *vdev, struct wp_request *wp)
241 {
242 	u32 val;
243 
244 	val = REGB_RD32(VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD0);
245 	val = REG_SET_FLD_NUM(VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD0, MIN_RATIO, wp->min, val);
246 	val = REG_SET_FLD_NUM(VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD0, MAX_RATIO, wp->max, val);
247 	REGB_WR32(VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD0, val);
248 
249 	val = REGB_RD32(VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD1);
250 	val = REG_SET_FLD_NUM(VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD1, TARGET_RATIO, wp->target, val);
251 	val = REG_SET_FLD_NUM(VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD1, EPP, wp->epp, val);
252 	REGB_WR32(VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD1, val);
253 
254 	val = REGB_RD32(VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD2);
255 	val = REG_SET_FLD_NUM(VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD2, CONFIG, wp->cfg, val);
256 	val = REG_SET_FLD_NUM(VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD2, CDYN, wp->cdyn, val);
257 	REGB_WR32(VPU_HW_BTRS_LNL_WP_REQ_PAYLOAD2, val);
258 
259 	val = REGB_RD32(VPU_HW_BTRS_LNL_WP_REQ_CMD);
260 	val = REG_SET_FLD(VPU_HW_BTRS_LNL_WP_REQ_CMD, SEND, val);
261 	REGB_WR32(VPU_HW_BTRS_LNL_WP_REQ_CMD, val);
262 }
263 
wp_request(struct ivpu_device * vdev,struct wp_request * wp)264 static void wp_request(struct ivpu_device *vdev, struct wp_request *wp)
265 {
266 	if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
267 		wp_request_mtl(vdev, wp);
268 	else
269 		wp_request_lnl(vdev, wp);
270 }
271 
wp_request_send(struct ivpu_device * vdev,struct wp_request * wp)272 static int wp_request_send(struct ivpu_device *vdev, struct wp_request *wp)
273 {
274 	int ret;
275 
276 	ret = wp_request_sync(vdev);
277 	if (ret) {
278 		ivpu_err(vdev, "Failed to sync before workpoint request: %d\n", ret);
279 		return ret;
280 	}
281 
282 	wp_request(vdev, wp);
283 
284 	ret = wp_request_sync(vdev);
285 	if (ret)
286 		ivpu_err(vdev, "Failed to sync after workpoint request: %d\n", ret);
287 
288 	return ret;
289 }
290 
prepare_wp_request(struct ivpu_device * vdev,struct wp_request * wp,bool enable)291 static void prepare_wp_request(struct ivpu_device *vdev, struct wp_request *wp, bool enable)
292 {
293 	struct ivpu_hw_info *hw = vdev->hw;
294 
295 	wp->min = hw->pll.min_ratio;
296 	wp->max = hw->pll.max_ratio;
297 
298 	if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL) {
299 		wp->target = enable ? hw->pll.pn_ratio : 0;
300 		wp->cfg = enable ? hw->config : 0;
301 		wp->cdyn = 0;
302 		wp->epp = 0;
303 	} else {
304 		wp->target = hw->pll.pn_ratio;
305 		wp->cfg = 0;
306 		wp->cdyn = enable ? PLL_CDYN_DEFAULT : 0;
307 		wp->epp = enable ? PLL_EPP_DEFAULT : 0;
308 	}
309 }
310 
wait_for_pll_lock(struct ivpu_device * vdev,bool enable)311 static int wait_for_pll_lock(struct ivpu_device *vdev, bool enable)
312 {
313 	u32 exp_val = enable ? 0x1 : 0x0;
314 
315 	if (ivpu_hw_btrs_gen(vdev) != IVPU_HW_BTRS_MTL)
316 		return 0;
317 
318 	if (IVPU_WA(punit_disabled))
319 		return 0;
320 
321 	return REGB_POLL_FLD(VPU_HW_BTRS_MTL_PLL_STATUS, LOCK, exp_val, PLL_TIMEOUT_US);
322 }
323 
wait_for_cdyn_deassert(struct ivpu_device * vdev)324 static int wait_for_cdyn_deassert(struct ivpu_device *vdev)
325 {
326 	if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
327 		return 0;
328 
329 	return REGB_POLL_FLD(VPU_HW_BTRS_LNL_CDYN, CDYN, 0, PLL_TIMEOUT_US);
330 }
331 
ivpu_hw_btrs_wp_drive(struct ivpu_device * vdev,bool enable)332 int ivpu_hw_btrs_wp_drive(struct ivpu_device *vdev, bool enable)
333 {
334 	struct wp_request wp;
335 	int ret;
336 
337 	if (IVPU_WA(punit_disabled)) {
338 		ivpu_dbg(vdev, PM, "Skipping workpoint request\n");
339 		return 0;
340 	}
341 
342 	prepare_wp_request(vdev, &wp, enable);
343 
344 	ivpu_dbg(vdev, PM, "PLL workpoint request: %u MHz, config: 0x%x, epp: 0x%x, cdyn: 0x%x\n",
345 		 ivpu_hw_btrs_pll_ratio_to_mhz(vdev, wp.target), wp.cfg, wp.epp, wp.cdyn);
346 
347 	ret = wp_request_send(vdev, &wp);
348 	if (ret) {
349 		ivpu_err(vdev, "Failed to send workpoint request: %d\n", ret);
350 		return ret;
351 	}
352 
353 	ret = wait_for_pll_lock(vdev, enable);
354 	if (ret) {
355 		ivpu_err(vdev, "Timed out waiting for PLL lock\n");
356 		return ret;
357 	}
358 
359 	ret = wait_for_status_ready(vdev, enable);
360 	if (ret) {
361 		ivpu_err(vdev, "Timed out waiting for NPU ready status\n");
362 		return ret;
363 	}
364 
365 	if (!enable) {
366 		ret = wait_for_cdyn_deassert(vdev);
367 		if (ret) {
368 			ivpu_err(vdev, "Timed out waiting for CDYN deassert\n");
369 			return ret;
370 		}
371 	}
372 
373 	return 0;
374 }
375 
d0i3_drive_mtl(struct ivpu_device * vdev,bool enable)376 static int d0i3_drive_mtl(struct ivpu_device *vdev, bool enable)
377 {
378 	int ret;
379 	u32 val;
380 
381 	ret = REGB_POLL_FLD(VPU_HW_BTRS_MTL_VPU_D0I3_CONTROL, INPROGRESS, 0, TIMEOUT_US);
382 	if (ret) {
383 		ivpu_err(vdev, "Failed to sync before D0i3 transition: %d\n", ret);
384 		return ret;
385 	}
386 
387 	val = REGB_RD32(VPU_HW_BTRS_MTL_VPU_D0I3_CONTROL);
388 	if (enable)
389 		val = REG_SET_FLD(VPU_HW_BTRS_MTL_VPU_D0I3_CONTROL, I3, val);
390 	else
391 		val = REG_CLR_FLD(VPU_HW_BTRS_MTL_VPU_D0I3_CONTROL, I3, val);
392 	REGB_WR32(VPU_HW_BTRS_MTL_VPU_D0I3_CONTROL, val);
393 
394 	ret = REGB_POLL_FLD(VPU_HW_BTRS_MTL_VPU_D0I3_CONTROL, INPROGRESS, 0, TIMEOUT_US);
395 	if (ret)
396 		ivpu_err(vdev, "Failed to sync after D0i3 transition: %d\n", ret);
397 
398 	return ret;
399 }
400 
d0i3_drive_lnl(struct ivpu_device * vdev,bool enable)401 static int d0i3_drive_lnl(struct ivpu_device *vdev, bool enable)
402 {
403 	int ret;
404 	u32 val;
405 
406 	ret = REGB_POLL_FLD(VPU_HW_BTRS_LNL_D0I3_CONTROL, INPROGRESS, 0, TIMEOUT_US);
407 	if (ret) {
408 		ivpu_err(vdev, "Failed to sync before D0i3 transition: %d\n", ret);
409 		return ret;
410 	}
411 
412 	val = REGB_RD32(VPU_HW_BTRS_LNL_D0I3_CONTROL);
413 	if (enable)
414 		val = REG_SET_FLD(VPU_HW_BTRS_LNL_D0I3_CONTROL, I3, val);
415 	else
416 		val = REG_CLR_FLD(VPU_HW_BTRS_LNL_D0I3_CONTROL, I3, val);
417 	REGB_WR32(VPU_HW_BTRS_LNL_D0I3_CONTROL, val);
418 
419 	ret = REGB_POLL_FLD(VPU_HW_BTRS_LNL_D0I3_CONTROL, INPROGRESS, 0, TIMEOUT_US);
420 	if (ret) {
421 		ivpu_err(vdev, "Failed to sync after D0i3 transition: %d\n", ret);
422 		return ret;
423 	}
424 
425 	return 0;
426 }
427 
d0i3_drive(struct ivpu_device * vdev,bool enable)428 static int d0i3_drive(struct ivpu_device *vdev, bool enable)
429 {
430 	if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
431 		return d0i3_drive_mtl(vdev, enable);
432 	else
433 		return d0i3_drive_lnl(vdev, enable);
434 }
435 
ivpu_hw_btrs_d0i3_enable(struct ivpu_device * vdev)436 int ivpu_hw_btrs_d0i3_enable(struct ivpu_device *vdev)
437 {
438 	int ret;
439 
440 	if (IVPU_WA(punit_disabled))
441 		return 0;
442 
443 	ret = d0i3_drive(vdev, true);
444 	if (ret)
445 		ivpu_err(vdev, "Failed to enable D0i3: %d\n", ret);
446 
447 	udelay(5); /* VPU requires 5 us to complete the transition */
448 
449 	return ret;
450 }
451 
ivpu_hw_btrs_d0i3_disable(struct ivpu_device * vdev)452 int ivpu_hw_btrs_d0i3_disable(struct ivpu_device *vdev)
453 {
454 	int ret;
455 
456 	if (IVPU_WA(punit_disabled))
457 		return 0;
458 
459 	ret = d0i3_drive(vdev, false);
460 	if (ret)
461 		ivpu_err(vdev, "Failed to disable D0i3: %d\n", ret);
462 
463 	return ret;
464 }
465 
ivpu_hw_btrs_wait_for_clock_res_own_ack(struct ivpu_device * vdev)466 int ivpu_hw_btrs_wait_for_clock_res_own_ack(struct ivpu_device *vdev)
467 {
468 	if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
469 		return 0;
470 
471 	return REGB_POLL_FLD(VPU_HW_BTRS_LNL_VPU_STATUS, CLOCK_RESOURCE_OWN_ACK, 1, TIMEOUT_US);
472 }
473 
ivpu_hw_btrs_set_port_arbitration_weights_lnl(struct ivpu_device * vdev)474 void ivpu_hw_btrs_set_port_arbitration_weights_lnl(struct ivpu_device *vdev)
475 {
476 	REGB_WR32(VPU_HW_BTRS_LNL_PORT_ARBITRATION_WEIGHTS, WEIGHTS_DEFAULT);
477 	REGB_WR32(VPU_HW_BTRS_LNL_PORT_ARBITRATION_WEIGHTS_ATS, WEIGHTS_ATS_DEFAULT);
478 }
479 
ip_reset_mtl(struct ivpu_device * vdev)480 static int ip_reset_mtl(struct ivpu_device *vdev)
481 {
482 	int ret;
483 	u32 val;
484 
485 	ret = REGB_POLL_FLD(VPU_HW_BTRS_MTL_VPU_IP_RESET, TRIGGER, 0, TIMEOUT_US);
486 	if (ret) {
487 		ivpu_err(vdev, "Timed out waiting for TRIGGER bit\n");
488 		return ret;
489 	}
490 
491 	val = REGB_RD32(VPU_HW_BTRS_MTL_VPU_IP_RESET);
492 	val = REG_SET_FLD(VPU_HW_BTRS_MTL_VPU_IP_RESET, TRIGGER, val);
493 	REGB_WR32(VPU_HW_BTRS_MTL_VPU_IP_RESET, val);
494 
495 	ret = REGB_POLL_FLD(VPU_HW_BTRS_MTL_VPU_IP_RESET, TRIGGER, 0, TIMEOUT_US);
496 	if (ret)
497 		ivpu_err(vdev, "Timed out waiting for RESET completion\n");
498 
499 	return ret;
500 }
501 
ip_reset_lnl(struct ivpu_device * vdev)502 static int ip_reset_lnl(struct ivpu_device *vdev)
503 {
504 	int ret;
505 	u32 val;
506 
507 	ivpu_hw_btrs_clock_relinquish_disable_lnl(vdev);
508 
509 	ret = REGB_POLL_FLD(VPU_HW_BTRS_LNL_IP_RESET, TRIGGER, 0, TIMEOUT_US);
510 	if (ret) {
511 		ivpu_err(vdev, "Wait for *_TRIGGER timed out\n");
512 		return ret;
513 	}
514 
515 	val = REGB_RD32(VPU_HW_BTRS_LNL_IP_RESET);
516 	val = REG_SET_FLD(VPU_HW_BTRS_LNL_IP_RESET, TRIGGER, val);
517 	REGB_WR32(VPU_HW_BTRS_LNL_IP_RESET, val);
518 
519 	ret = REGB_POLL_FLD(VPU_HW_BTRS_LNL_IP_RESET, TRIGGER, 0, TIMEOUT_US);
520 	if (ret)
521 		ivpu_err(vdev, "Timed out waiting for RESET completion\n");
522 
523 	return ret;
524 }
525 
ivpu_hw_btrs_ip_reset(struct ivpu_device * vdev)526 int ivpu_hw_btrs_ip_reset(struct ivpu_device *vdev)
527 {
528 	if (IVPU_WA(punit_disabled))
529 		return 0;
530 
531 	if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
532 		return ip_reset_mtl(vdev);
533 	else
534 		return ip_reset_lnl(vdev);
535 }
536 
ivpu_hw_btrs_profiling_freq_reg_set_lnl(struct ivpu_device * vdev)537 void ivpu_hw_btrs_profiling_freq_reg_set_lnl(struct ivpu_device *vdev)
538 {
539 	u32 val = REGB_RD32(VPU_HW_BTRS_LNL_VPU_STATUS);
540 
541 	if (vdev->hw->pll.profiling_freq == PLL_PROFILING_FREQ_DEFAULT)
542 		val = REG_CLR_FLD(VPU_HW_BTRS_LNL_VPU_STATUS, PERF_CLK, val);
543 	else
544 		val = REG_SET_FLD(VPU_HW_BTRS_LNL_VPU_STATUS, PERF_CLK, val);
545 
546 	REGB_WR32(VPU_HW_BTRS_LNL_VPU_STATUS, val);
547 }
548 
ivpu_hw_btrs_ats_print_lnl(struct ivpu_device * vdev)549 void ivpu_hw_btrs_ats_print_lnl(struct ivpu_device *vdev)
550 {
551 	ivpu_dbg(vdev, MISC, "Buttress ATS: %s\n",
552 		 REGB_RD32(VPU_HW_BTRS_LNL_HM_ATS) ? "Enable" : "Disable");
553 }
554 
ivpu_hw_btrs_clock_relinquish_disable_lnl(struct ivpu_device * vdev)555 void ivpu_hw_btrs_clock_relinquish_disable_lnl(struct ivpu_device *vdev)
556 {
557 	u32 val = REGB_RD32(VPU_HW_BTRS_LNL_VPU_STATUS);
558 
559 	val = REG_SET_FLD(VPU_HW_BTRS_LNL_VPU_STATUS, DISABLE_CLK_RELINQUISH, val);
560 	REGB_WR32(VPU_HW_BTRS_LNL_VPU_STATUS, val);
561 }
562 
ivpu_hw_btrs_is_idle(struct ivpu_device * vdev)563 bool ivpu_hw_btrs_is_idle(struct ivpu_device *vdev)
564 {
565 	u32 val;
566 
567 	if (IVPU_WA(punit_disabled))
568 		return true;
569 
570 	if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL) {
571 		val = REGB_RD32(VPU_HW_BTRS_MTL_VPU_STATUS);
572 
573 		return REG_TEST_FLD(VPU_HW_BTRS_MTL_VPU_STATUS, READY, val) &&
574 		       REG_TEST_FLD(VPU_HW_BTRS_MTL_VPU_STATUS, IDLE, val);
575 	} else {
576 		val = REGB_RD32(VPU_HW_BTRS_LNL_VPU_STATUS);
577 
578 		return REG_TEST_FLD(VPU_HW_BTRS_LNL_VPU_STATUS, READY, val) &&
579 		       REG_TEST_FLD(VPU_HW_BTRS_LNL_VPU_STATUS, IDLE, val);
580 	}
581 }
582 
ivpu_hw_btrs_wait_for_idle(struct ivpu_device * vdev)583 int ivpu_hw_btrs_wait_for_idle(struct ivpu_device *vdev)
584 {
585 	if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
586 		return REGB_POLL_FLD(VPU_HW_BTRS_MTL_VPU_STATUS, IDLE, 0x1, IDLE_TIMEOUT_US);
587 	else
588 		return REGB_POLL_FLD(VPU_HW_BTRS_LNL_VPU_STATUS, IDLE, 0x1, IDLE_TIMEOUT_US);
589 }
590 
pll_config_get_mtl(struct ivpu_device * vdev)591 static u32 pll_config_get_mtl(struct ivpu_device *vdev)
592 {
593 	return REGB_RD32(VPU_HW_BTRS_MTL_CURRENT_PLL);
594 }
595 
pll_config_get_lnl(struct ivpu_device * vdev)596 static u32 pll_config_get_lnl(struct ivpu_device *vdev)
597 {
598 	return REGB_RD32(VPU_HW_BTRS_LNL_PLL_FREQ);
599 }
600 
pll_ratio_to_mhz_mtl(u8 pll_ratio)601 static u32 pll_ratio_to_mhz_mtl(u8 pll_ratio)
602 {
603 	return (pll_ratio * PLL_REF_CLK_FREQ_MHZ * 2) / 3;
604 }
605 
pll_ratio_to_mhz_lnl(u8 pll_ratio)606 static u32 pll_ratio_to_mhz_lnl(u8 pll_ratio)
607 {
608 	return (pll_ratio * PLL_REF_CLK_FREQ_MHZ) / 2;
609 }
610 
ivpu_hw_btrs_pll_ratio_to_mhz(struct ivpu_device * vdev,u8 pll_ratio)611 u32 ivpu_hw_btrs_pll_ratio_to_mhz(struct ivpu_device *vdev, u8 pll_ratio)
612 {
613 	if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
614 		return pll_ratio_to_mhz_mtl(pll_ratio);
615 	else
616 		return pll_ratio_to_mhz_lnl(pll_ratio);
617 }
618 
ivpu_hw_btrs_pll_ratio_to_hz(struct ivpu_device * vdev,u8 pll_ratio)619 u32 ivpu_hw_btrs_pll_ratio_to_hz(struct ivpu_device *vdev, u8 pll_ratio)
620 {
621 	return ivpu_hw_btrs_pll_ratio_to_mhz(vdev, pll_ratio) * HZ_PER_MHZ;
622 }
623 
ivpu_hw_btrs_current_freq_get(struct ivpu_device * vdev)624 u32 ivpu_hw_btrs_current_freq_get(struct ivpu_device *vdev)
625 {
626 	if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
627 		return pll_ratio_to_mhz_mtl(pll_config_get_mtl(vdev));
628 	else
629 		return pll_ratio_to_mhz_lnl(pll_config_get_lnl(vdev));
630 }
631 
ivpu_hw_btrs_cfg_freq_set(struct ivpu_device * vdev,u8 cfg_min_ratio,u8 cfg_max_ratio)632 static int ivpu_hw_btrs_cfg_freq_set(struct ivpu_device *vdev, u8 cfg_min_ratio, u8 cfg_max_ratio)
633 {
634 	u8 min_ratio = clamp_t(u8, cfg_min_ratio, vdev->hw->pll.min_ratio, cfg_max_ratio);
635 	u8 pn_ratio = clamp_t(u8, vdev->hw->pll.pn_ratio, min_ratio, cfg_max_ratio);
636 	int ret;
637 
638 	ivpu_dbg(vdev, PM, "Set frequency range to min: %u, pn: %u, max: %u MHz\n",
639 		 ivpu_hw_btrs_pll_ratio_to_mhz(vdev, min_ratio),
640 		 ivpu_hw_btrs_pll_ratio_to_mhz(vdev, pn_ratio),
641 		 ivpu_hw_btrs_pll_ratio_to_mhz(vdev, cfg_max_ratio));
642 
643 	ret = ivpu_rpm_get(vdev);
644 	if (ret < 0)
645 		return ret;
646 
647 	ret = ivpu_jsm_msg_freq_config(vdev, min_ratio, pn_ratio, cfg_max_ratio);
648 	ivpu_rpm_put(vdev);
649 
650 	if (ret) {
651 		ivpu_warn(vdev,
652 			  "Failed to set frequency to min: %u, pn: %u, max: %u MHz, ret %d\n",
653 			  ivpu_hw_btrs_pll_ratio_to_mhz(vdev, min_ratio),
654 			  ivpu_hw_btrs_pll_ratio_to_mhz(vdev, pn_ratio),
655 			  ivpu_hw_btrs_pll_ratio_to_mhz(vdev, cfg_max_ratio),
656 			  ret);
657 		return ret;
658 	}
659 
660 	vdev->hw->pll.cfg_min_ratio = cfg_min_ratio;
661 	vdev->hw->pll.cfg_max_ratio = cfg_max_ratio;
662 
663 	return 0;
664 }
665 
dpu_mhz_to_pll_ratio_lnl(u32 freq_mhz)666 static u8 dpu_mhz_to_pll_ratio_lnl(u32 freq_mhz)
667 {
668 	return clamp_t(u32, freq_mhz / (PLL_REF_CLK_FREQ_MHZ / 2), 0, U8_MAX);
669 }
670 
ivpu_hw_btrs_cfg_max_freq_set(struct ivpu_device * vdev,u32 max_freq_mhz)671 int ivpu_hw_btrs_cfg_max_freq_set(struct ivpu_device *vdev, u32 max_freq_mhz)
672 {
673 	u8 ratio = dpu_mhz_to_pll_ratio_lnl(max_freq_mhz);
674 	u8 cfg_max_ratio = clamp_t(u8, ratio, vdev->hw->pll.min_ratio, vdev->hw->pll.max_ratio);
675 
676 	return ivpu_hw_btrs_cfg_freq_set(vdev, vdev->hw->pll.cfg_min_ratio, cfg_max_ratio);
677 }
678 
ivpu_hw_btrs_cfg_min_freq_set(struct ivpu_device * vdev,u32 min_freq_mhz)679 int ivpu_hw_btrs_cfg_min_freq_set(struct ivpu_device *vdev, u32 min_freq_mhz)
680 {
681 	u8 ratio = dpu_mhz_to_pll_ratio_lnl(min_freq_mhz);
682 	u8 cfg_min_ratio = clamp_t(u8, ratio, vdev->hw->pll.min_ratio, vdev->hw->pll.max_ratio);
683 
684 	return ivpu_hw_btrs_cfg_freq_set(vdev, cfg_min_ratio, vdev->hw->pll.cfg_max_ratio);
685 }
686 
ivpu_hw_btrs_cfg_freq_init(struct ivpu_device * vdev)687 int ivpu_hw_btrs_cfg_freq_init(struct ivpu_device *vdev)
688 {
689 	if (vdev->hw->pll.min_ratio == vdev->hw->pll.cfg_min_ratio &&
690 	    vdev->hw->pll.max_ratio == vdev->hw->pll.cfg_max_ratio)
691 		return 0;
692 
693 	return ivpu_hw_btrs_cfg_freq_set(vdev,
694 					 vdev->hw->pll.cfg_min_ratio,
695 					 vdev->hw->pll.cfg_max_ratio);
696 }
697 
698 /* Handler for IRQs from Buttress core (irqB) */
ivpu_hw_btrs_irq_handler_mtl(struct ivpu_device * vdev,int irq)699 bool ivpu_hw_btrs_irq_handler_mtl(struct ivpu_device *vdev, int irq)
700 {
701 	u32 status = REGB_RD32(VPU_HW_BTRS_MTL_INTERRUPT_STAT) & BTRS_MTL_IRQ_MASK;
702 	bool schedule_recovery = false;
703 
704 	if (!status)
705 		return false;
706 
707 	if (REG_TEST_FLD(VPU_HW_BTRS_MTL_INTERRUPT_STAT, FREQ_CHANGE, status)) {
708 		u32 pll = pll_config_get_mtl(vdev);
709 
710 		ivpu_dbg(vdev, IRQ, "FREQ_CHANGE irq, wp %08x, %u MHz",
711 			 pll, pll_ratio_to_mhz_mtl(pll));
712 	}
713 
714 	if (REG_TEST_FLD(VPU_HW_BTRS_MTL_INTERRUPT_STAT, ATS_ERR, status)) {
715 		ivpu_err(vdev, "ATS_ERR irq 0x%016llx", REGB_RD64(VPU_HW_BTRS_MTL_ATS_ERR_LOG_0));
716 		REGB_WR32(VPU_HW_BTRS_MTL_ATS_ERR_CLEAR, 0x1);
717 		schedule_recovery = true;
718 	}
719 
720 	if (REG_TEST_FLD(VPU_HW_BTRS_MTL_INTERRUPT_STAT, UFI_ERR, status)) {
721 		u32 ufi_log = REGB_RD32(VPU_HW_BTRS_MTL_UFI_ERR_LOG);
722 
723 		ivpu_err(vdev, "UFI_ERR irq (0x%08x) opcode: 0x%02lx axi_id: 0x%02lx cq_id: 0x%03lx",
724 			 ufi_log, REG_GET_FLD(VPU_HW_BTRS_MTL_UFI_ERR_LOG, OPCODE, ufi_log),
725 			 REG_GET_FLD(VPU_HW_BTRS_MTL_UFI_ERR_LOG, AXI_ID, ufi_log),
726 			 REG_GET_FLD(VPU_HW_BTRS_MTL_UFI_ERR_LOG, CQ_ID, ufi_log));
727 		REGB_WR32(VPU_HW_BTRS_MTL_UFI_ERR_CLEAR, 0x1);
728 		schedule_recovery = true;
729 	}
730 
731 	/* This must be done after interrupts are cleared at the source. */
732 	if (IVPU_WA(interrupt_clear_with_0))
733 		/*
734 		 * Writing 1 triggers an interrupt, so we can't perform read update write.
735 		 * Clear local interrupt status by writing 0 to all bits.
736 		 */
737 		REGB_WR32(VPU_HW_BTRS_MTL_INTERRUPT_STAT, 0x0);
738 	else
739 		REGB_WR32(VPU_HW_BTRS_MTL_INTERRUPT_STAT, status);
740 
741 	if (schedule_recovery)
742 		ivpu_pm_trigger_recovery(vdev, "Buttress IRQ");
743 
744 	return true;
745 }
746 
747 /* Handler for IRQs from Buttress core (irqB) */
ivpu_hw_btrs_irq_handler_lnl(struct ivpu_device * vdev,int irq)748 bool ivpu_hw_btrs_irq_handler_lnl(struct ivpu_device *vdev, int irq)
749 {
750 	u32 status = REGB_RD32(VPU_HW_BTRS_LNL_INTERRUPT_STAT) & BTRS_LNL_IRQ_MASK;
751 	bool schedule_recovery = false;
752 
753 	if (!status)
754 		return false;
755 
756 	if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, SURV_ERR, status)) {
757 		ivpu_dbg(vdev, IRQ, "Survivability IRQ\n");
758 		queue_work(system_percpu_wq, &vdev->irq_dct_work);
759 	}
760 
761 	if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, FREQ_CHANGE, status)) {
762 		u32 pll = pll_config_get_lnl(vdev);
763 
764 		ivpu_dbg(vdev, IRQ, "FREQ_CHANGE irq, wp %08x, %u MHz",
765 			 pll, pll_ratio_to_mhz_lnl(pll));
766 	}
767 
768 	if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, ATS_ERR, status)) {
769 		ivpu_err(vdev, "ATS_ERR LOG1 0x%08x ATS_ERR_LOG2 0x%08x\n",
770 			 REGB_RD32(VPU_HW_BTRS_LNL_ATS_ERR_LOG1),
771 			 REGB_RD32(VPU_HW_BTRS_LNL_ATS_ERR_LOG2));
772 		REGB_WR32(VPU_HW_BTRS_LNL_ATS_ERR_CLEAR, 0x1);
773 		schedule_recovery = true;
774 	}
775 
776 	if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, CFI0_ERR, status)) {
777 		ivpu_err(vdev, "CFI0_ERR 0x%08x", REGB_RD32(VPU_HW_BTRS_LNL_CFI0_ERR_LOG));
778 		REGB_WR32(VPU_HW_BTRS_LNL_CFI0_ERR_CLEAR, 0x1);
779 		schedule_recovery = true;
780 	}
781 
782 	if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, CFI1_ERR, status)) {
783 		ivpu_err(vdev, "CFI1_ERR 0x%08x", REGB_RD32(VPU_HW_BTRS_LNL_CFI1_ERR_LOG));
784 		REGB_WR32(VPU_HW_BTRS_LNL_CFI1_ERR_CLEAR, 0x1);
785 		schedule_recovery = true;
786 	}
787 
788 	if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, IMR0_ERR, status)) {
789 		ivpu_err(vdev, "IMR_ERR_CFI0 LOW: 0x%08x HIGH: 0x%08x",
790 			 REGB_RD32(VPU_HW_BTRS_LNL_IMR_ERR_CFI0_LOW),
791 			 REGB_RD32(VPU_HW_BTRS_LNL_IMR_ERR_CFI0_HIGH));
792 		REGB_WR32(VPU_HW_BTRS_LNL_IMR_ERR_CFI0_CLEAR, 0x1);
793 		schedule_recovery = true;
794 	}
795 
796 	if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, IMR1_ERR, status)) {
797 		ivpu_err(vdev, "IMR_ERR_CFI1 LOW: 0x%08x HIGH: 0x%08x",
798 			 REGB_RD32(VPU_HW_BTRS_LNL_IMR_ERR_CFI1_LOW),
799 			 REGB_RD32(VPU_HW_BTRS_LNL_IMR_ERR_CFI1_HIGH));
800 		REGB_WR32(VPU_HW_BTRS_LNL_IMR_ERR_CFI1_CLEAR, 0x1);
801 		schedule_recovery = true;
802 	}
803 
804 	/* This must be done after interrupts are cleared at the source. */
805 	REGB_WR32(VPU_HW_BTRS_LNL_INTERRUPT_STAT, status);
806 
807 	if (schedule_recovery)
808 		ivpu_pm_trigger_recovery(vdev, "Buttress IRQ");
809 
810 	return true;
811 }
812 
ivpu_hw_btrs_dct_get_request(struct ivpu_device * vdev,bool * enable)813 int ivpu_hw_btrs_dct_get_request(struct ivpu_device *vdev, bool *enable)
814 {
815 	u32 val = REGB_RD32(VPU_HW_BTRS_LNL_PCODE_MAILBOX_SHADOW);
816 	u32 cmd = REG_GET_FLD(VPU_HW_BTRS_LNL_PCODE_MAILBOX_SHADOW, CMD, val);
817 	u32 param1 = REG_GET_FLD(VPU_HW_BTRS_LNL_PCODE_MAILBOX_SHADOW, PARAM1, val);
818 
819 	if (cmd != DCT_REQ) {
820 		ivpu_err_ratelimited(vdev, "Unsupported PCODE command: 0x%x\n", cmd);
821 		return -EBADR;
822 	}
823 
824 	switch (param1) {
825 	case DCT_ENABLE:
826 		*enable = true;
827 		return 0;
828 	case DCT_DISABLE:
829 		*enable = false;
830 		return 0;
831 	default:
832 		ivpu_err_ratelimited(vdev, "Invalid PARAM1 value: %u\n", param1);
833 		return -EINVAL;
834 	}
835 }
836 
ivpu_hw_btrs_dct_set_status(struct ivpu_device * vdev,bool enable,u8 active_percent)837 void ivpu_hw_btrs_dct_set_status(struct ivpu_device *vdev, bool enable, u8 active_percent)
838 {
839 	u32 val = 0;
840 	u32 cmd = enable ? DCT_ENABLE : DCT_DISABLE;
841 
842 	val = REG_SET_FLD_NUM(VPU_HW_BTRS_LNL_PCODE_MAILBOX_STATUS, CMD, DCT_REQ, val);
843 	val = REG_SET_FLD_NUM(VPU_HW_BTRS_LNL_PCODE_MAILBOX_STATUS, PARAM1, cmd, val);
844 	val = REG_SET_FLD_NUM(VPU_HW_BTRS_LNL_PCODE_MAILBOX_STATUS, PARAM2, active_percent, val);
845 
846 	REGB_WR32(VPU_HW_BTRS_LNL_PCODE_MAILBOX_STATUS, val);
847 }
848 
ivpu_hw_btrs_telemetry_offset_get(struct ivpu_device * vdev)849 u32 ivpu_hw_btrs_telemetry_offset_get(struct ivpu_device *vdev)
850 {
851 	if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
852 		return REGB_RD32(VPU_HW_BTRS_MTL_VPU_TELEMETRY_OFFSET);
853 	else
854 		return REGB_RD32(VPU_HW_BTRS_LNL_VPU_TELEMETRY_OFFSET);
855 }
856 
ivpu_hw_btrs_telemetry_size_get(struct ivpu_device * vdev)857 u32 ivpu_hw_btrs_telemetry_size_get(struct ivpu_device *vdev)
858 {
859 	if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
860 		return REGB_RD32(VPU_HW_BTRS_MTL_VPU_TELEMETRY_SIZE);
861 	else
862 		return REGB_RD32(VPU_HW_BTRS_LNL_VPU_TELEMETRY_SIZE);
863 }
864 
ivpu_hw_btrs_telemetry_enable_get(struct ivpu_device * vdev)865 u32 ivpu_hw_btrs_telemetry_enable_get(struct ivpu_device *vdev)
866 {
867 	if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
868 		return REGB_RD32(VPU_HW_BTRS_MTL_VPU_TELEMETRY_ENABLE);
869 	else
870 		return REGB_RD32(VPU_HW_BTRS_LNL_VPU_TELEMETRY_ENABLE);
871 }
872 
ivpu_hw_btrs_global_int_disable(struct ivpu_device * vdev)873 void ivpu_hw_btrs_global_int_disable(struct ivpu_device *vdev)
874 {
875 	if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
876 		REGB_WR32(VPU_HW_BTRS_MTL_GLOBAL_INT_MASK, 0x1);
877 	else
878 		REGB_WR32(VPU_HW_BTRS_LNL_GLOBAL_INT_MASK, 0x1);
879 }
880 
ivpu_hw_btrs_global_int_enable(struct ivpu_device * vdev)881 void ivpu_hw_btrs_global_int_enable(struct ivpu_device *vdev)
882 {
883 	if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
884 		REGB_WR32(VPU_HW_BTRS_MTL_GLOBAL_INT_MASK, 0x0);
885 	else
886 		REGB_WR32(VPU_HW_BTRS_LNL_GLOBAL_INT_MASK, 0x0);
887 }
888 
ivpu_hw_btrs_irq_enable(struct ivpu_device * vdev)889 void ivpu_hw_btrs_irq_enable(struct ivpu_device *vdev)
890 {
891 	if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL) {
892 		REGB_WR32(VPU_HW_BTRS_MTL_LOCAL_INT_MASK, (u32)(~BTRS_MTL_IRQ_MASK));
893 		REGB_WR32(VPU_HW_BTRS_MTL_GLOBAL_INT_MASK, 0x0);
894 	} else {
895 		REGB_WR32(VPU_HW_BTRS_LNL_LOCAL_INT_MASK, (u32)(~BTRS_LNL_IRQ_MASK));
896 		REGB_WR32(VPU_HW_BTRS_LNL_GLOBAL_INT_MASK, 0x0);
897 	}
898 }
899 
ivpu_hw_btrs_irq_disable(struct ivpu_device * vdev)900 void ivpu_hw_btrs_irq_disable(struct ivpu_device *vdev)
901 {
902 	if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL) {
903 		REGB_WR32(VPU_HW_BTRS_MTL_GLOBAL_INT_MASK, 0x1);
904 		REGB_WR32(VPU_HW_BTRS_MTL_LOCAL_INT_MASK, BTRS_IRQ_DISABLE_MASK);
905 	} else {
906 		REGB_WR32(VPU_HW_BTRS_LNL_GLOBAL_INT_MASK, 0x1);
907 		REGB_WR32(VPU_HW_BTRS_LNL_LOCAL_INT_MASK, BTRS_IRQ_DISABLE_MASK);
908 	}
909 }
910 
diagnose_failure_mtl(struct ivpu_device * vdev)911 static void diagnose_failure_mtl(struct ivpu_device *vdev)
912 {
913 	u32 reg = REGB_RD32(VPU_HW_BTRS_MTL_INTERRUPT_STAT) & BTRS_MTL_IRQ_MASK;
914 
915 	if (REG_TEST_FLD(VPU_HW_BTRS_MTL_INTERRUPT_STAT, ATS_ERR, reg))
916 		ivpu_err(vdev, "ATS_ERR irq 0x%016llx", REGB_RD64(VPU_HW_BTRS_MTL_ATS_ERR_LOG_0));
917 
918 	if (REG_TEST_FLD(VPU_HW_BTRS_MTL_INTERRUPT_STAT, UFI_ERR, reg)) {
919 		u32 log = REGB_RD32(VPU_HW_BTRS_MTL_UFI_ERR_LOG);
920 
921 		ivpu_err(vdev, "UFI_ERR irq (0x%08x) opcode: 0x%02lx axi_id: 0x%02lx cq_id: 0x%03lx",
922 			 log, REG_GET_FLD(VPU_HW_BTRS_MTL_UFI_ERR_LOG, OPCODE, log),
923 			 REG_GET_FLD(VPU_HW_BTRS_MTL_UFI_ERR_LOG, AXI_ID, log),
924 			 REG_GET_FLD(VPU_HW_BTRS_MTL_UFI_ERR_LOG, CQ_ID, log));
925 	}
926 }
927 
diagnose_failure_lnl(struct ivpu_device * vdev)928 static void diagnose_failure_lnl(struct ivpu_device *vdev)
929 {
930 	u32 reg = REGB_RD32(VPU_HW_BTRS_LNL_INTERRUPT_STAT) & BTRS_LNL_IRQ_MASK;
931 
932 	if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, ATS_ERR, reg)) {
933 		ivpu_err(vdev, "ATS_ERR_LOG1 0x%08x ATS_ERR_LOG2 0x%08x\n",
934 			 REGB_RD32(VPU_HW_BTRS_LNL_ATS_ERR_LOG1),
935 			 REGB_RD32(VPU_HW_BTRS_LNL_ATS_ERR_LOG2));
936 	}
937 
938 	if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, CFI0_ERR, reg))
939 		ivpu_err(vdev, "CFI0_ERR_LOG 0x%08x\n", REGB_RD32(VPU_HW_BTRS_LNL_CFI0_ERR_LOG));
940 
941 	if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, CFI1_ERR, reg))
942 		ivpu_err(vdev, "CFI1_ERR_LOG 0x%08x\n", REGB_RD32(VPU_HW_BTRS_LNL_CFI1_ERR_LOG));
943 
944 	if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, IMR0_ERR, reg))
945 		ivpu_err(vdev, "IMR_ERR_CFI0 LOW: 0x%08x HIGH: 0x%08x\n",
946 			 REGB_RD32(VPU_HW_BTRS_LNL_IMR_ERR_CFI0_LOW),
947 			 REGB_RD32(VPU_HW_BTRS_LNL_IMR_ERR_CFI0_HIGH));
948 
949 	if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, IMR1_ERR, reg))
950 		ivpu_err(vdev, "IMR_ERR_CFI1 LOW: 0x%08x HIGH: 0x%08x\n",
951 			 REGB_RD32(VPU_HW_BTRS_LNL_IMR_ERR_CFI1_LOW),
952 			 REGB_RD32(VPU_HW_BTRS_LNL_IMR_ERR_CFI1_HIGH));
953 
954 	if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, SURV_ERR, reg))
955 		ivpu_err(vdev, "Survivability IRQ\n");
956 }
957 
ivpu_hw_btrs_diagnose_failure(struct ivpu_device * vdev)958 void ivpu_hw_btrs_diagnose_failure(struct ivpu_device *vdev)
959 {
960 	if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
961 		return diagnose_failure_mtl(vdev);
962 	else
963 		return diagnose_failure_lnl(vdev);
964 }
965 
ivpu_hw_btrs_platform_read(struct ivpu_device * vdev)966 int ivpu_hw_btrs_platform_read(struct ivpu_device *vdev)
967 {
968 	u32 reg = REGB_RD32(VPU_HW_BTRS_LNL_VPU_STATUS);
969 
970 	return REG_GET_FLD(VPU_HW_BTRS_LNL_VPU_STATUS, PLATFORM, reg);
971 }
972