xref: /linux/drivers/gpu/drm/xe/xe_gsc.c (revision ca220141fa8ebae09765a242076b2b77338106b0)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2023 Intel Corporation
4  */
5 
6 #include "xe_gsc.h"
7 
8 #include <linux/delay.h>
9 
10 #include <drm/drm_managed.h>
11 #include <drm/drm_print.h>
12 
13 #include <generated/xe_wa_oob.h>
14 
15 #include "abi/gsc_mkhi_commands_abi.h"
16 #include "xe_bb.h"
17 #include "xe_bo.h"
18 #include "xe_device.h"
19 #include "xe_exec_queue.h"
20 #include "xe_force_wake.h"
21 #include "xe_gsc_proxy.h"
22 #include "xe_gsc_submit.h"
23 #include "xe_gt.h"
24 #include "xe_gt_mcr.h"
25 #include "xe_gt_printk.h"
26 #include "xe_guc_pc.h"
27 #include "xe_huc.h"
28 #include "xe_map.h"
29 #include "xe_mmio.h"
30 #include "xe_pm.h"
31 #include "xe_sched_job.h"
32 #include "xe_uc_fw.h"
33 #include "xe_wa.h"
34 #include "instructions/xe_gsc_commands.h"
35 #include "regs/xe_gsc_regs.h"
36 #include "regs/xe_gt_regs.h"
37 #include "regs/xe_irq_regs.h"
38 
39 static struct xe_gt *
40 gsc_to_gt(struct xe_gsc *gsc)
41 {
42 	return container_of(gsc, struct xe_gt, uc.gsc);
43 }
44 
45 static int memcpy_fw(struct xe_gsc *gsc)
46 {
47 	struct xe_gt *gt = gsc_to_gt(gsc);
48 	struct xe_device *xe = gt_to_xe(gt);
49 	u32 fw_size = gsc->fw.size;
50 	void *storage;
51 
52 	/*
53 	 * FIXME: xe_migrate_copy does not work with stolen mem yet, so we use
54 	 * a memcpy for now.
55 	 */
56 	storage = kmalloc(fw_size, GFP_KERNEL);
57 	if (!storage)
58 		return -ENOMEM;
59 
60 	xe_map_memcpy_from(xe, storage, &gsc->fw.bo->vmap, 0, fw_size);
61 	xe_map_memcpy_to(xe, &gsc->private->vmap, 0, storage, fw_size);
62 	xe_map_memset(xe, &gsc->private->vmap, fw_size, 0,
63 		      xe_bo_size(gsc->private) - fw_size);
64 
65 	kfree(storage);
66 
67 	return 0;
68 }
69 
70 static int emit_gsc_upload(struct xe_gsc *gsc)
71 {
72 	struct xe_gt *gt = gsc_to_gt(gsc);
73 	u64 offset = xe_bo_ggtt_addr(gsc->private);
74 	struct xe_bb *bb;
75 	struct xe_sched_job *job;
76 	struct dma_fence *fence;
77 	long timeout;
78 
79 	bb = xe_bb_new(gt, 4, false);
80 	if (IS_ERR(bb))
81 		return PTR_ERR(bb);
82 
83 	bb->cs[bb->len++] = GSC_FW_LOAD;
84 	bb->cs[bb->len++] = lower_32_bits(offset);
85 	bb->cs[bb->len++] = upper_32_bits(offset);
86 	bb->cs[bb->len++] = (xe_bo_size(gsc->private) / SZ_4K) |
87 		GSC_FW_LOAD_LIMIT_VALID;
88 
89 	job = xe_bb_create_job(gsc->q, bb);
90 	if (IS_ERR(job)) {
91 		xe_bb_free(bb, NULL);
92 		return PTR_ERR(job);
93 	}
94 
95 	xe_sched_job_arm(job);
96 	fence = dma_fence_get(&job->drm.s_fence->finished);
97 	xe_sched_job_push(job);
98 
99 	timeout = dma_fence_wait_timeout(fence, false, HZ);
100 	dma_fence_put(fence);
101 	xe_bb_free(bb, NULL);
102 	if (timeout < 0)
103 		return timeout;
104 	else if (!timeout)
105 		return -ETIME;
106 
107 	return 0;
108 }
109 
110 #define version_query_wr(xe_, map_, offset_, field_, val_) \
111 	xe_map_wr_field(xe_, map_, offset_, struct gsc_get_compatibility_version_in, field_, val_)
112 #define version_query_rd(xe_, map_, offset_, field_) \
113 	xe_map_rd_field(xe_, map_, offset_, struct gsc_get_compatibility_version_out, field_)
114 
115 static u32 emit_version_query_msg(struct xe_device *xe, struct iosys_map *map, u32 wr_offset)
116 {
117 	xe_map_memset(xe, map, wr_offset, 0, sizeof(struct gsc_get_compatibility_version_in));
118 
119 	version_query_wr(xe, map, wr_offset, header.group_id, MKHI_GROUP_ID_GFX_SRV);
120 	version_query_wr(xe, map, wr_offset, header.command,
121 			 MKHI_GFX_SRV_GET_HOST_COMPATIBILITY_VERSION);
122 
123 	return wr_offset + sizeof(struct gsc_get_compatibility_version_in);
124 }
125 
126 #define GSC_VER_PKT_SZ SZ_4K /* 4K each for input and output */
127 static int query_compatibility_version(struct xe_gsc *gsc)
128 {
129 	struct xe_uc_fw_version *compat = &gsc->fw.versions.found[XE_UC_FW_VER_COMPATIBILITY];
130 	struct xe_gt *gt = gsc_to_gt(gsc);
131 	struct xe_tile *tile = gt_to_tile(gt);
132 	struct xe_device *xe = gt_to_xe(gt);
133 	struct xe_bo *bo;
134 	u32 wr_offset;
135 	u32 rd_offset;
136 	u64 ggtt_offset;
137 	int err;
138 
139 	bo = xe_bo_create_pin_map_novm(xe, tile, GSC_VER_PKT_SZ * 2,
140 				       ttm_bo_type_kernel,
141 				       XE_BO_FLAG_SYSTEM |
142 				       XE_BO_FLAG_GGTT, false);
143 	if (IS_ERR(bo)) {
144 		xe_gt_err(gt, "failed to allocate bo for GSC version query\n");
145 		return PTR_ERR(bo);
146 	}
147 
148 	ggtt_offset = xe_bo_ggtt_addr(bo);
149 
150 	wr_offset = xe_gsc_emit_header(xe, &bo->vmap, 0, HECI_MEADDRESS_MKHI, 0,
151 				       sizeof(struct gsc_get_compatibility_version_in));
152 	wr_offset = emit_version_query_msg(xe, &bo->vmap, wr_offset);
153 
154 	err = xe_gsc_pkt_submit_kernel(gsc, ggtt_offset, wr_offset,
155 				       ggtt_offset + GSC_VER_PKT_SZ,
156 				       GSC_VER_PKT_SZ);
157 	if (err) {
158 		xe_gt_err(gt,
159 			  "failed to submit GSC request for compatibility version: %d\n",
160 			  err);
161 		goto out_bo;
162 	}
163 
164 	err = xe_gsc_read_out_header(xe, &bo->vmap, GSC_VER_PKT_SZ,
165 				     sizeof(struct gsc_get_compatibility_version_out),
166 				     &rd_offset);
167 	if (err) {
168 		xe_gt_err(gt, "HuC: invalid GSC reply for version query (err=%d)\n", err);
169 		return err;
170 	}
171 
172 	compat->major = version_query_rd(xe, &bo->vmap, rd_offset, proj_major);
173 	compat->minor = version_query_rd(xe, &bo->vmap, rd_offset, compat_major);
174 	compat->patch = version_query_rd(xe, &bo->vmap, rd_offset, compat_minor);
175 
176 	xe_gt_info(gt, "found GSC cv%u.%u.%u\n", compat->major, compat->minor, compat->patch);
177 
178 out_bo:
179 	xe_bo_unpin_map_no_vm(bo);
180 	return err;
181 }
182 
183 static int gsc_fw_is_loaded(struct xe_gt *gt)
184 {
185 	return xe_mmio_read32(&gt->mmio, HECI_FWSTS1(MTL_GSC_HECI1_BASE)) &
186 			      HECI1_FWSTS1_INIT_COMPLETE;
187 }
188 
189 static int gsc_fw_wait(struct xe_gt *gt)
190 {
191 	/*
192 	 * GSC load can take up to 250ms from the moment the instruction is
193 	 * executed by the GSCCS. To account for possible submission delays or
194 	 * other issues, we use a 500ms timeout in the wait here.
195 	 */
196 	return xe_mmio_wait32(&gt->mmio, HECI_FWSTS1(MTL_GSC_HECI1_BASE),
197 			      HECI1_FWSTS1_INIT_COMPLETE,
198 			      HECI1_FWSTS1_INIT_COMPLETE,
199 			      500 * USEC_PER_MSEC, NULL, false);
200 }
201 
202 static int gsc_upload(struct xe_gsc *gsc)
203 {
204 	struct xe_gt *gt = gsc_to_gt(gsc);
205 	struct xe_device *xe = gt_to_xe(gt);
206 	int err;
207 
208 	/* we should only be here if the init step were successful */
209 	xe_assert(xe, xe_uc_fw_is_loadable(&gsc->fw) && gsc->q);
210 
211 	if (gsc_fw_is_loaded(gt)) {
212 		xe_gt_err(gt, "GSC already loaded at upload time\n");
213 		return -EEXIST;
214 	}
215 
216 	err = memcpy_fw(gsc);
217 	if (err) {
218 		xe_gt_err(gt, "Failed to memcpy GSC FW\n");
219 		return err;
220 	}
221 
222 	/*
223 	 * GSC is only killed by an FLR, so we need to trigger one on unload to
224 	 * make sure we stop it. This is because we assign a chunk of memory to
225 	 * the GSC as part of the FW load, so we need to make sure it stops
226 	 * using it when we release it to the system on driver unload. Note that
227 	 * this is not a problem of the unload per-se, because the GSC will not
228 	 * touch that memory unless there are requests for it coming from the
229 	 * driver; therefore, no accesses will happen while Xe is not loaded,
230 	 * but if we re-load the driver then the GSC might wake up and try to
231 	 * access that old memory location again.
232 	 * Given that an FLR is a very disruptive action (see the FLR function
233 	 * for details), we want to do it as the last action before releasing
234 	 * the access to the MMIO bar, which means we need to do it as part of
235 	 * mmio cleanup.
236 	 */
237 	xe->needs_flr_on_fini = true;
238 
239 	err = emit_gsc_upload(gsc);
240 	if (err) {
241 		xe_gt_err(gt, "Failed to emit GSC FW upload (%pe)\n", ERR_PTR(err));
242 		return err;
243 	}
244 
245 	err = gsc_fw_wait(gt);
246 	if (err) {
247 		xe_gt_err(gt, "Failed to wait for GSC load (%pe)\n", ERR_PTR(err));
248 		return err;
249 	}
250 
251 	err = query_compatibility_version(gsc);
252 	if (err)
253 		return err;
254 
255 	err = xe_uc_fw_check_version_requirements(&gsc->fw);
256 	if (err)
257 		return err;
258 
259 	return 0;
260 }
261 
262 static int gsc_upload_and_init(struct xe_gsc *gsc)
263 {
264 	struct xe_gt *gt = gsc_to_gt(gsc);
265 	struct xe_tile *tile = gt_to_tile(gt);
266 	unsigned int fw_ref;
267 	int ret;
268 
269 	if (tile->primary_gt && XE_GT_WA(tile->primary_gt, 14018094691)) {
270 		fw_ref = xe_force_wake_get(gt_to_fw(tile->primary_gt), XE_FORCEWAKE_ALL);
271 
272 		/*
273 		 * If the forcewake fails we want to keep going, because the worst
274 		 * case outcome in failing to apply the WA is that PXP won't work,
275 		 * which is not fatal. Forcewake get warns implicitly in case of failure
276 		 */
277 		xe_gt_mcr_multicast_write(tile->primary_gt,
278 					  EU_SYSTOLIC_LIC_THROTTLE_CTL_WITH_LOCK,
279 					  EU_SYSTOLIC_LIC_THROTTLE_CTL_LOCK_BIT);
280 	}
281 
282 	ret = gsc_upload(gsc);
283 
284 	if (tile->primary_gt && XE_GT_WA(tile->primary_gt, 14018094691))
285 		xe_force_wake_put(gt_to_fw(tile->primary_gt), fw_ref);
286 
287 	if (ret)
288 		return ret;
289 
290 	xe_uc_fw_change_status(&gsc->fw, XE_UC_FIRMWARE_TRANSFERRED);
291 
292 	/* GSC load is done, restore expected GT frequencies */
293 	xe_gt_sanitize_freq(gt);
294 
295 	xe_gt_dbg(gt, "GSC FW async load completed\n");
296 
297 	/* HuC auth failure is not fatal */
298 	if (xe_huc_is_authenticated(&gt->uc.huc, XE_HUC_AUTH_VIA_GUC))
299 		xe_huc_auth(&gt->uc.huc, XE_HUC_AUTH_VIA_GSC);
300 
301 	ret = xe_gsc_proxy_start(gsc);
302 	if (ret)
303 		return ret;
304 
305 	xe_gt_dbg(gt, "GSC proxy init completed\n");
306 
307 	return 0;
308 }
309 
310 static int gsc_er_complete(struct xe_gt *gt)
311 {
312 	u32 er_status;
313 
314 	if (!gsc_fw_is_loaded(gt))
315 		return 0;
316 
317 	/*
318 	 * Starting on Xe2, the GSCCS engine reset is a 2-step process. When the
319 	 * driver or the GuC hit the GDRST register, the CS is immediately reset
320 	 * and a success is reported, but the GSC shim keeps resetting in the
321 	 * background. While the shim reset is ongoing, the CS is able to accept
322 	 * new context submission, but any commands that require the shim will
323 	 * be stalled until the reset is completed. This means that we can keep
324 	 * submitting to the GSCCS as long as we make sure that the preemption
325 	 * timeout is big enough to cover any delay introduced by the reset.
326 	 * When the shim reset completes, a specific CS interrupt is triggered,
327 	 * in response to which we need to check the GSCI_TIMER_STATUS register
328 	 * to see if the reset was successful or not.
329 	 * Note that the GSCI_TIMER_STATUS register is not power save/restored,
330 	 * so it gets reset on MC6 entry. However, a reset failure stops MC6,
331 	 * so in that scenario we're always guaranteed to find the correct
332 	 * value.
333 	 */
334 	er_status = xe_mmio_read32(&gt->mmio, GSCI_TIMER_STATUS) & GSCI_TIMER_STATUS_VALUE;
335 
336 	if (er_status == GSCI_TIMER_STATUS_TIMER_EXPIRED) {
337 		/*
338 		 * XXX: we should trigger an FLR here, but we don't have support
339 		 * for that yet. Since we can't recover from the error, we
340 		 * declare the device as wedged.
341 		 */
342 		xe_gt_err(gt, "GSC ER timed out!\n");
343 		xe_device_declare_wedged(gt_to_xe(gt));
344 		return -EIO;
345 	}
346 
347 	return 0;
348 }
349 
350 static void gsc_work(struct work_struct *work)
351 {
352 	struct xe_gsc *gsc = container_of(work, typeof(*gsc), work);
353 	struct xe_gt *gt = gsc_to_gt(gsc);
354 	struct xe_device *xe = gt_to_xe(gt);
355 	u32 actions;
356 	int ret;
357 
358 	spin_lock_irq(&gsc->lock);
359 	actions = gsc->work_actions;
360 	gsc->work_actions = 0;
361 	spin_unlock_irq(&gsc->lock);
362 
363 	guard(xe_pm_runtime)(xe);
364 	CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GSC);
365 
366 	if (actions & GSC_ACTION_ER_COMPLETE) {
367 		if (gsc_er_complete(gt))
368 			return;
369 	}
370 
371 	if (actions & GSC_ACTION_FW_LOAD) {
372 		ret = gsc_upload_and_init(gsc);
373 		if (ret && ret != -EEXIST)
374 			xe_uc_fw_change_status(&gsc->fw, XE_UC_FIRMWARE_LOAD_FAIL);
375 		else
376 			xe_uc_fw_change_status(&gsc->fw, XE_UC_FIRMWARE_RUNNING);
377 	}
378 
379 	if (actions & GSC_ACTION_SW_PROXY)
380 		xe_gsc_proxy_request_handler(gsc);
381 }
382 
383 void xe_gsc_hwe_irq_handler(struct xe_hw_engine *hwe, u16 intr_vec)
384 {
385 	struct xe_gt *gt = hwe->gt;
386 	struct xe_gsc *gsc = &gt->uc.gsc;
387 
388 	if (unlikely(!intr_vec))
389 		return;
390 
391 	if (intr_vec & GSC_ER_COMPLETE) {
392 		spin_lock(&gsc->lock);
393 		gsc->work_actions |= GSC_ACTION_ER_COMPLETE;
394 		spin_unlock(&gsc->lock);
395 
396 		queue_work(gsc->wq, &gsc->work);
397 	}
398 }
399 
400 int xe_gsc_init(struct xe_gsc *gsc)
401 {
402 	struct xe_gt *gt = gsc_to_gt(gsc);
403 	struct xe_tile *tile = gt_to_tile(gt);
404 	int ret;
405 
406 	gsc->fw.type = XE_UC_FW_TYPE_GSC;
407 	INIT_WORK(&gsc->work, gsc_work);
408 	spin_lock_init(&gsc->lock);
409 
410 	/* The GSC uC is only available on the media GT */
411 	if (tile->media_gt && (gt != tile->media_gt)) {
412 		xe_uc_fw_change_status(&gsc->fw, XE_UC_FIRMWARE_NOT_SUPPORTED);
413 		return 0;
414 	}
415 
416 	/*
417 	 * Starting from BMG the GSC is no longer needed for MC6 entry, so the
418 	 * only missing features if the FW is lacking would be the content
419 	 * protection ones. This is acceptable, so we allow the driver load to
420 	 * continue if the GSC FW is missing.
421 	 */
422 	ret = xe_uc_fw_init(&gsc->fw);
423 	if (!xe_uc_fw_is_enabled(&gsc->fw))
424 		return 0;
425 	else if (gt_to_xe(gt)->info.platform >= XE_BATTLEMAGE && !xe_uc_fw_is_available(&gsc->fw))
426 		return 0;
427 	else if (ret)
428 		goto out;
429 
430 	ret = xe_gsc_proxy_init(gsc);
431 	if (ret && ret != -ENODEV)
432 		goto out;
433 
434 	return 0;
435 
436 out:
437 	xe_gt_err(gt, "GSC init failed with %d", ret);
438 	return ret;
439 }
440 
441 static void free_resources(void *arg)
442 {
443 	struct xe_gsc *gsc = arg;
444 
445 	if (gsc->wq) {
446 		destroy_workqueue(gsc->wq);
447 		gsc->wq = NULL;
448 	}
449 
450 	if (gsc->q) {
451 		xe_exec_queue_put(gsc->q);
452 		gsc->q = NULL;
453 	}
454 }
455 
456 int xe_gsc_init_post_hwconfig(struct xe_gsc *gsc)
457 {
458 	struct xe_gt *gt = gsc_to_gt(gsc);
459 	struct xe_tile *tile = gt_to_tile(gt);
460 	struct xe_device *xe = gt_to_xe(gt);
461 	struct xe_hw_engine *hwe = xe_gt_hw_engine(gt, XE_ENGINE_CLASS_OTHER, 0, true);
462 	struct xe_exec_queue *q;
463 	struct workqueue_struct *wq;
464 	struct xe_bo *bo;
465 	int err;
466 
467 	if (!xe_uc_fw_is_available(&gsc->fw))
468 		return 0;
469 
470 	if (!hwe)
471 		return -ENODEV;
472 
473 	bo = xe_managed_bo_create_pin_map(xe, tile, SZ_4M,
474 					  XE_BO_FLAG_STOLEN |
475 					  XE_BO_FLAG_GGTT);
476 	if (IS_ERR(bo))
477 		return PTR_ERR(bo);
478 
479 	q = xe_exec_queue_create(xe, NULL,
480 				 BIT(hwe->logical_instance), 1, hwe,
481 				 EXEC_QUEUE_FLAG_KERNEL |
482 				 EXEC_QUEUE_FLAG_PERMANENT, 0);
483 	if (IS_ERR(q)) {
484 		xe_gt_err(gt, "Failed to create queue for GSC submission\n");
485 		err = PTR_ERR(q);
486 		goto out_bo;
487 	}
488 
489 	wq = alloc_ordered_workqueue("gsc-ordered-wq", 0);
490 	if (!wq) {
491 		err = -ENOMEM;
492 		goto out_q;
493 	}
494 
495 	gsc->private = bo;
496 	gsc->q = q;
497 	gsc->wq = wq;
498 
499 	err = devm_add_action_or_reset(xe->drm.dev, free_resources, gsc);
500 	if (err)
501 		return err;
502 
503 	xe_uc_fw_change_status(&gsc->fw, XE_UC_FIRMWARE_LOADABLE);
504 
505 	return 0;
506 
507 out_q:
508 	xe_exec_queue_put(q);
509 out_bo:
510 	xe_bo_unpin_map_no_vm(bo);
511 	return err;
512 }
513 
514 void xe_gsc_load_start(struct xe_gsc *gsc)
515 {
516 	struct xe_gt *gt = gsc_to_gt(gsc);
517 	struct xe_device *xe = gt_to_xe(gt);
518 
519 	if (!xe_uc_fw_is_loadable(&gsc->fw) || !gsc->q)
520 		return;
521 
522 	/*
523 	 * The GSC HW is only reset by driver FLR or D3cold entry. We don't
524 	 * support the former at runtime, while the latter is only supported on
525 	 * DGFX, for which we don't support GSC. Therefore, if GSC failed to
526 	 * load previously there is no need to try again because the HW is
527 	 * stuck in the error state.
528 	 */
529 	xe_assert(xe, !IS_DGFX(xe));
530 	if (xe_uc_fw_is_in_error_state(&gsc->fw))
531 		return;
532 
533 	/* GSC FW survives GT reset and D3Hot */
534 	if (gsc_fw_is_loaded(gt)) {
535 		if (xe_gsc_proxy_init_done(gsc))
536 			xe_uc_fw_change_status(&gsc->fw, XE_UC_FIRMWARE_RUNNING);
537 		else
538 			xe_uc_fw_change_status(&gsc->fw, XE_UC_FIRMWARE_TRANSFERRED);
539 		return;
540 	}
541 
542 	spin_lock_irq(&gsc->lock);
543 	gsc->work_actions |= GSC_ACTION_FW_LOAD;
544 	spin_unlock_irq(&gsc->lock);
545 
546 	queue_work(gsc->wq, &gsc->work);
547 }
548 
549 void xe_gsc_wait_for_worker_completion(struct xe_gsc *gsc)
550 {
551 	if (xe_uc_fw_is_loadable(&gsc->fw) && gsc->wq)
552 		flush_work(&gsc->work);
553 }
554 
555 void xe_gsc_stop_prepare(struct xe_gsc *gsc)
556 {
557 	struct xe_gt *gt = gsc_to_gt(gsc);
558 	int ret;
559 
560 	if (!xe_uc_fw_is_loadable(&gsc->fw) || xe_uc_fw_is_in_error_state(&gsc->fw))
561 		return;
562 
563 	xe_force_wake_assert_held(gt_to_fw(gt), XE_FW_GSC);
564 
565 	/*
566 	 * If the GSC FW load or the proxy init are interrupted, the only way
567 	 * to recover it is to do an FLR and reload the GSC from scratch.
568 	 * Therefore, let's wait for the init to complete before stopping
569 	 * operations. The proxy init is the last step, so we can just wait on
570 	 * that
571 	 */
572 	ret = xe_gsc_wait_for_proxy_init_done(gsc);
573 	if (ret)
574 		xe_gt_err(gt, "failed to wait for GSC init completion before uc stop\n");
575 }
576 
577 /*
578  * wa_14015076503: if the GSC FW is loaded, we need to alert it before doing a
579  * GSC engine reset by writing a notification bit in the GS1 register and then
580  * triggering an interrupt to GSC; from the interrupt it will take up to 200ms
581  * for the FW to get prepare for the reset, so we need to wait for that amount
582  * of time.
583  * After the reset is complete we need to then clear the GS1 register.
584  */
585 void xe_gsc_wa_14015076503(struct xe_gt *gt, bool prep)
586 {
587 	u32 gs1_set = prep ? HECI_H_GS1_ER_PREP : 0;
588 	u32 gs1_clr = prep ? 0 : HECI_H_GS1_ER_PREP;
589 
590 	/* WA only applies if the GSC is loaded */
591 	if (!XE_GT_WA(gt, 14015076503) || !gsc_fw_is_loaded(gt))
592 		return;
593 
594 	xe_mmio_rmw32(&gt->mmio, HECI_H_GS1(MTL_GSC_HECI2_BASE), gs1_clr, gs1_set);
595 
596 	if (prep) {
597 		/* make sure the reset bit is clear when writing the CSR reg */
598 		xe_mmio_rmw32(&gt->mmio, HECI_H_CSR(MTL_GSC_HECI2_BASE),
599 			      HECI_H_CSR_RST, HECI_H_CSR_IG);
600 		msleep(200);
601 	}
602 }
603 
604 /**
605  * xe_gsc_print_info - print info about GSC FW status
606  * @gsc: the GSC structure
607  * @p: the printer to be used to print the info
608  */
609 void xe_gsc_print_info(struct xe_gsc *gsc, struct drm_printer *p)
610 {
611 	struct xe_gt *gt = gsc_to_gt(gsc);
612 	struct xe_mmio *mmio = &gt->mmio;
613 
614 	xe_uc_fw_print(&gsc->fw, p);
615 
616 	drm_printf(p, "\tfound security version %u\n", gsc->security_version);
617 
618 	if (!xe_uc_fw_is_available(&gsc->fw))
619 		return;
620 
621 	CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GSC);
622 	if (!fw_ref.domains)
623 		return;
624 
625 	drm_printf(p, "\nHECI1 FWSTS: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
626 			xe_mmio_read32(mmio, HECI_FWSTS1(MTL_GSC_HECI1_BASE)),
627 			xe_mmio_read32(mmio, HECI_FWSTS2(MTL_GSC_HECI1_BASE)),
628 			xe_mmio_read32(mmio, HECI_FWSTS3(MTL_GSC_HECI1_BASE)),
629 			xe_mmio_read32(mmio, HECI_FWSTS4(MTL_GSC_HECI1_BASE)),
630 			xe_mmio_read32(mmio, HECI_FWSTS5(MTL_GSC_HECI1_BASE)),
631 			xe_mmio_read32(mmio, HECI_FWSTS6(MTL_GSC_HECI1_BASE)));
632 }
633