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