xref: /linux-6.15/drivers/gpu/drm/xe/xe_pcode.c (revision 75fd04f2)
1dd08ebf6SMatthew Brost // SPDX-License-Identifier: MIT
2dd08ebf6SMatthew Brost /*
3dd08ebf6SMatthew Brost  * Copyright © 2022 Intel Corporation
4dd08ebf6SMatthew Brost  */
5dd08ebf6SMatthew Brost 
6dd08ebf6SMatthew Brost #include "xe_pcode.h"
7dd08ebf6SMatthew Brost 
8ea9f879dSLucas De Marchi #include <linux/delay.h>
9ea9f879dSLucas De Marchi #include <linux/errno.h>
10ea9f879dSLucas De Marchi 
1128b1d915SBommithi Sakeena #include <drm/drm_managed.h>
1228b1d915SBommithi Sakeena 
134c0be90eSHimal Prasad Ghimiray #include "xe_assert.h"
14933fd5ffSRiana Tauro #include "xe_device.h"
15dd08ebf6SMatthew Brost #include "xe_mmio.h"
16ea9f879dSLucas De Marchi #include "xe_pcode_api.h"
170f06dc10SRodrigo Vivi 
18dd08ebf6SMatthew Brost /**
19dd08ebf6SMatthew Brost  * DOC: PCODE
20dd08ebf6SMatthew Brost  *
21dd08ebf6SMatthew Brost  * Xe PCODE is the component responsible for interfacing with the PCODE
22dd08ebf6SMatthew Brost  * firmware.
23dd08ebf6SMatthew Brost  * It shall provide a very simple ABI to other Xe components, but be the
24dd08ebf6SMatthew Brost  * single and consolidated place that will communicate with PCODE. All read
25dd08ebf6SMatthew Brost  * and write operations to PCODE will be internal and private to this component.
26dd08ebf6SMatthew Brost  *
27dd08ebf6SMatthew Brost  * What's next:
28dd08ebf6SMatthew Brost  * - PCODE hw metrics
29dd08ebf6SMatthew Brost  * - PCODE for display operations
30dd08ebf6SMatthew Brost  */
31dd08ebf6SMatthew Brost 
pcode_mailbox_status(struct xe_tile * tile)323034cc81SMatt Roper static int pcode_mailbox_status(struct xe_tile *tile)
33dd08ebf6SMatthew Brost {
34dd08ebf6SMatthew Brost 	u32 err;
35dd08ebf6SMatthew Brost 	static const struct pcode_err_decode err_decode[] = {
36dd08ebf6SMatthew Brost 		[PCODE_ILLEGAL_CMD] = {-ENXIO, "Illegal Command"},
37dd08ebf6SMatthew Brost 		[PCODE_TIMEOUT] = {-ETIMEDOUT, "Timed out"},
38dd08ebf6SMatthew Brost 		[PCODE_ILLEGAL_DATA] = {-EINVAL, "Illegal Data"},
39dd08ebf6SMatthew Brost 		[PCODE_ILLEGAL_SUBCOMMAND] = {-ENXIO, "Illegal Subcommand"},
40dd08ebf6SMatthew Brost 		[PCODE_LOCKED] = {-EBUSY, "PCODE Locked"},
41dd08ebf6SMatthew Brost 		[PCODE_GT_RATIO_OUT_OF_RANGE] = {-EOVERFLOW,
42dd08ebf6SMatthew Brost 			"GT ratio out of range"},
43dd08ebf6SMatthew Brost 		[PCODE_REJECTED] = {-EACCES, "PCODE Rejected"},
44dd08ebf6SMatthew Brost 		[PCODE_ERROR_MASK] = {-EPROTO, "Unknown"},
45dd08ebf6SMatthew Brost 	};
46dd08ebf6SMatthew Brost 
47a3e7fcefSMatt Roper 	err = xe_mmio_read32(&tile->mmio, PCODE_MAILBOX) & PCODE_ERROR_MASK;
48dd08ebf6SMatthew Brost 	if (err) {
493034cc81SMatt Roper 		drm_err(&tile_to_xe(tile)->drm, "PCODE Mailbox failed: %d %s", err,
50dd08ebf6SMatthew Brost 			err_decode[err].str ?: "Unknown");
51dd08ebf6SMatthew Brost 		return err_decode[err].errno ?: -EPROTO;
52dd08ebf6SMatthew Brost 	}
53dd08ebf6SMatthew Brost 
54dd08ebf6SMatthew Brost 	return 0;
55dd08ebf6SMatthew Brost }
56dd08ebf6SMatthew Brost 
__pcode_mailbox_rw(struct xe_tile * tile,u32 mbox,u32 * data0,u32 * data1,unsigned int timeout_ms,bool return_data,bool atomic)573034cc81SMatt Roper static int __pcode_mailbox_rw(struct xe_tile *tile, u32 mbox, u32 *data0, u32 *data1,
587dc9b92dSRodrigo Vivi 			      unsigned int timeout_ms, bool return_data,
597dc9b92dSRodrigo Vivi 			      bool atomic)
60dd08ebf6SMatthew Brost {
61a3e7fcefSMatt Roper 	struct xe_mmio *mmio = &tile->mmio;
627dc9b92dSRodrigo Vivi 	int err;
633e8e7ee6SFrancois Dugast 
643034cc81SMatt Roper 	if (tile_to_xe(tile)->info.skip_pcode)
65082802a3SKoby Elbaz 		return 0;
66082802a3SKoby Elbaz 
673034cc81SMatt Roper 	if ((xe_mmio_read32(mmio, PCODE_MAILBOX) & PCODE_READY) != 0)
68dd08ebf6SMatthew Brost 		return -EAGAIN;
69dd08ebf6SMatthew Brost 
703034cc81SMatt Roper 	xe_mmio_write32(mmio, PCODE_DATA0, *data0);
713034cc81SMatt Roper 	xe_mmio_write32(mmio, PCODE_DATA1, data1 ? *data1 : 0);
723034cc81SMatt Roper 	xe_mmio_write32(mmio, PCODE_MAILBOX, PCODE_READY | mbox);
73dd08ebf6SMatthew Brost 
743034cc81SMatt Roper 	err = xe_mmio_wait32(mmio, PCODE_MAILBOX, PCODE_READY, 0,
75f20b7671SHimal Prasad Ghimiray 			     timeout_ms * USEC_PER_MSEC, NULL, atomic);
767dc9b92dSRodrigo Vivi 	if (err)
777dc9b92dSRodrigo Vivi 		return err;
78dd08ebf6SMatthew Brost 
79dd08ebf6SMatthew Brost 	if (return_data) {
803034cc81SMatt Roper 		*data0 = xe_mmio_read32(mmio, PCODE_DATA0);
81dd08ebf6SMatthew Brost 		if (data1)
823034cc81SMatt Roper 			*data1 = xe_mmio_read32(mmio, PCODE_DATA1);
83dd08ebf6SMatthew Brost 	}
84dd08ebf6SMatthew Brost 
853034cc81SMatt Roper 	return pcode_mailbox_status(tile);
86dd08ebf6SMatthew Brost }
87dd08ebf6SMatthew Brost 
pcode_mailbox_rw(struct xe_tile * tile,u32 mbox,u32 * data0,u32 * data1,unsigned int timeout_ms,bool return_data,bool atomic)883034cc81SMatt Roper static int pcode_mailbox_rw(struct xe_tile *tile, u32 mbox, u32 *data0, u32 *data1,
89933fd5ffSRiana Tauro 			    unsigned int timeout_ms, bool return_data,
90933fd5ffSRiana Tauro 			    bool atomic)
91933fd5ffSRiana Tauro {
923034cc81SMatt Roper 	if (tile_to_xe(tile)->info.skip_pcode)
93933fd5ffSRiana Tauro 		return 0;
94933fd5ffSRiana Tauro 
953034cc81SMatt Roper 	lockdep_assert_held(&tile->pcode.lock);
96933fd5ffSRiana Tauro 
973034cc81SMatt Roper 	return __pcode_mailbox_rw(tile, mbox, data0, data1, timeout_ms, return_data, atomic);
98933fd5ffSRiana Tauro }
99933fd5ffSRiana Tauro 
xe_pcode_write_timeout(struct xe_tile * tile,u32 mbox,u32 data,int timeout)1003034cc81SMatt Roper int xe_pcode_write_timeout(struct xe_tile *tile, u32 mbox, u32 data, int timeout)
101dd08ebf6SMatthew Brost {
102dd08ebf6SMatthew Brost 	int err;
103dd08ebf6SMatthew Brost 
1043034cc81SMatt Roper 	mutex_lock(&tile->pcode.lock);
1053034cc81SMatt Roper 	err = pcode_mailbox_rw(tile, mbox, &data, NULL, timeout, false, false);
1063034cc81SMatt Roper 	mutex_unlock(&tile->pcode.lock);
107dd08ebf6SMatthew Brost 
108dd08ebf6SMatthew Brost 	return err;
109dd08ebf6SMatthew Brost }
110dd08ebf6SMatthew Brost 
xe_pcode_read(struct xe_tile * tile,u32 mbox,u32 * val,u32 * val1)1113034cc81SMatt Roper int xe_pcode_read(struct xe_tile *tile, u32 mbox, u32 *val, u32 *val1)
112dd08ebf6SMatthew Brost {
113dd08ebf6SMatthew Brost 	int err;
114dd08ebf6SMatthew Brost 
1153034cc81SMatt Roper 	mutex_lock(&tile->pcode.lock);
1163034cc81SMatt Roper 	err = pcode_mailbox_rw(tile, mbox, val, val1, 1, true, false);
1173034cc81SMatt Roper 	mutex_unlock(&tile->pcode.lock);
118dd08ebf6SMatthew Brost 
119dd08ebf6SMatthew Brost 	return err;
120dd08ebf6SMatthew Brost }
121dd08ebf6SMatthew Brost 
pcode_try_request(struct xe_tile * tile,u32 mbox,u32 request,u32 reply_mask,u32 reply,u32 * status,bool atomic,int timeout_us,bool locked)1223034cc81SMatt Roper static int pcode_try_request(struct xe_tile *tile, u32 mbox,
123dd08ebf6SMatthew Brost 			     u32 request, u32 reply_mask, u32 reply,
124933fd5ffSRiana Tauro 			     u32 *status, bool atomic, int timeout_us, bool locked)
125dd08ebf6SMatthew Brost {
1267dc9b92dSRodrigo Vivi 	int slept, wait = 10;
127dd08ebf6SMatthew Brost 
1283034cc81SMatt Roper 	xe_tile_assert(tile, timeout_us > 0);
1294c0be90eSHimal Prasad Ghimiray 
1307dc9b92dSRodrigo Vivi 	for (slept = 0; slept < timeout_us; slept += wait) {
131933fd5ffSRiana Tauro 		if (locked)
1323034cc81SMatt Roper 			*status = pcode_mailbox_rw(tile, mbox, &request, NULL, 1, true,
1337dc9b92dSRodrigo Vivi 						   atomic);
134933fd5ffSRiana Tauro 		else
1353034cc81SMatt Roper 			*status = __pcode_mailbox_rw(tile, mbox, &request, NULL, 1, true,
136933fd5ffSRiana Tauro 						     atomic);
1377dc9b92dSRodrigo Vivi 		if ((*status == 0) && ((request & reply_mask) == reply))
1387dc9b92dSRodrigo Vivi 			return 0;
1397dc9b92dSRodrigo Vivi 
1407dc9b92dSRodrigo Vivi 		if (atomic)
1417dc9b92dSRodrigo Vivi 			udelay(wait);
1427dc9b92dSRodrigo Vivi 		else
1437dc9b92dSRodrigo Vivi 			usleep_range(wait, wait << 1);
1447dc9b92dSRodrigo Vivi 		wait <<= 1;
1457dc9b92dSRodrigo Vivi 	}
1467dc9b92dSRodrigo Vivi 
1477dc9b92dSRodrigo Vivi 	return -ETIMEDOUT;
148dd08ebf6SMatthew Brost }
149dd08ebf6SMatthew Brost 
150dd08ebf6SMatthew Brost /**
151dd08ebf6SMatthew Brost  * xe_pcode_request - send PCODE request until acknowledgment
1523034cc81SMatt Roper  * @tile: tile
153dd08ebf6SMatthew Brost  * @mbox: PCODE mailbox ID the request is targeted for
154dd08ebf6SMatthew Brost  * @request: request ID
155dd08ebf6SMatthew Brost  * @reply_mask: mask used to check for request acknowledgment
156dd08ebf6SMatthew Brost  * @reply: value used to check for request acknowledgment
157dd08ebf6SMatthew Brost  * @timeout_base_ms: timeout for polling with preemption enabled
158dd08ebf6SMatthew Brost  *
159dd08ebf6SMatthew Brost  * Keep resending the @request to @mbox until PCODE acknowledges it, PCODE
160dd08ebf6SMatthew Brost  * reports an error or an overall timeout of @timeout_base_ms+50 ms expires.
161dd08ebf6SMatthew Brost  * The request is acknowledged once the PCODE reply dword equals @reply after
162dd08ebf6SMatthew Brost  * applying @reply_mask. Polling is first attempted with preemption enabled
163dd08ebf6SMatthew Brost  * for @timeout_base_ms and if this times out for another 50 ms with
164dd08ebf6SMatthew Brost  * preemption disabled.
165dd08ebf6SMatthew Brost  *
166dd08ebf6SMatthew Brost  * Returns 0 on success, %-ETIMEDOUT in case of a timeout, <0 in case of some
167dd08ebf6SMatthew Brost  * other error as reported by PCODE.
168dd08ebf6SMatthew Brost  */
xe_pcode_request(struct xe_tile * tile,u32 mbox,u32 request,u32 reply_mask,u32 reply,int timeout_base_ms)1693034cc81SMatt Roper int xe_pcode_request(struct xe_tile *tile, u32 mbox, u32 request,
170dd08ebf6SMatthew Brost 		     u32 reply_mask, u32 reply, int timeout_base_ms)
171dd08ebf6SMatthew Brost {
172dd08ebf6SMatthew Brost 	u32 status;
173dd08ebf6SMatthew Brost 	int ret;
174dd08ebf6SMatthew Brost 
1753034cc81SMatt Roper 	xe_tile_assert(tile, timeout_base_ms <= 3);
1764c0be90eSHimal Prasad Ghimiray 
1773034cc81SMatt Roper 	mutex_lock(&tile->pcode.lock);
178dd08ebf6SMatthew Brost 
1793034cc81SMatt Roper 	ret = pcode_try_request(tile, mbox, request, reply_mask, reply, &status,
180933fd5ffSRiana Tauro 				false, timeout_base_ms * 1000, true);
181d8731500SMatthew Auld 	if (!ret)
182dd08ebf6SMatthew Brost 		goto out;
183dd08ebf6SMatthew Brost 
184dd08ebf6SMatthew Brost 	/*
185dd08ebf6SMatthew Brost 	 * The above can time out if the number of requests was low (2 in the
186dd08ebf6SMatthew Brost 	 * worst case) _and_ PCODE was busy for some reason even after a
187dd08ebf6SMatthew Brost 	 * (queued) request and @timeout_base_ms delay. As a workaround retry
188dd08ebf6SMatthew Brost 	 * the poll with preemption disabled to maximize the number of
189dd08ebf6SMatthew Brost 	 * requests. Increase the timeout from @timeout_base_ms to 50ms to
190dd08ebf6SMatthew Brost 	 * account for interrupts that could reduce the number of these
191dd08ebf6SMatthew Brost 	 * requests, and for any quirks of the PCODE firmware that delays
192dd08ebf6SMatthew Brost 	 * the request completion.
193dd08ebf6SMatthew Brost 	 */
1943034cc81SMatt Roper 	drm_err(&tile_to_xe(tile)->drm,
195dd08ebf6SMatthew Brost 		"PCODE timeout, retrying with preemption disabled\n");
196dd08ebf6SMatthew Brost 	preempt_disable();
1973034cc81SMatt Roper 	ret = pcode_try_request(tile, mbox, request, reply_mask, reply, &status,
198c81858ebSHimal Prasad Ghimiray 				true, 50 * 1000, true);
199dd08ebf6SMatthew Brost 	preempt_enable();
200dd08ebf6SMatthew Brost 
201dd08ebf6SMatthew Brost out:
2023034cc81SMatt Roper 	mutex_unlock(&tile->pcode.lock);
203dd08ebf6SMatthew Brost 	return status ? status : ret;
204dd08ebf6SMatthew Brost }
205dd08ebf6SMatthew Brost /**
206dd08ebf6SMatthew Brost  * xe_pcode_init_min_freq_table - Initialize PCODE's QOS frequency table
2073034cc81SMatt Roper  * @tile: tile instance
208dd08ebf6SMatthew Brost  * @min_gt_freq: Minimal (RPn) GT frequency in units of 50MHz.
209dd08ebf6SMatthew Brost  * @max_gt_freq: Maximal (RP0) GT frequency in units of 50MHz.
210dd08ebf6SMatthew Brost  *
211dd08ebf6SMatthew Brost  * This function initialize PCODE's QOS frequency table for a proper minimal
212dd08ebf6SMatthew Brost  * frequency/power steering decision, depending on the current requested GT
213dd08ebf6SMatthew Brost  * frequency. For older platforms this was a more complete table including
214dd08ebf6SMatthew Brost  * the IA freq. However for the latest platforms this table become a simple
215dd08ebf6SMatthew Brost  * 1-1 Ring vs GT frequency. Even though, without setting it, PCODE might
216dd08ebf6SMatthew Brost  * not take the right decisions for some memory frequencies and affect latency.
217dd08ebf6SMatthew Brost  *
218dd08ebf6SMatthew Brost  * It returns 0 on success, and -ERROR number on failure, -EINVAL if max
219dd08ebf6SMatthew Brost  * frequency is higher then the minimal, and other errors directly translated
220*75fd04f2SNitin Gote  * from the PCODE Error returns:
221dd08ebf6SMatthew Brost  * - -ENXIO: "Illegal Command"
222dd08ebf6SMatthew Brost  * - -ETIMEDOUT: "Timed out"
223dd08ebf6SMatthew Brost  * - -EINVAL: "Illegal Data"
224dd08ebf6SMatthew Brost  * - -ENXIO, "Illegal Subcommand"
225dd08ebf6SMatthew Brost  * - -EBUSY: "PCODE Locked"
226dd08ebf6SMatthew Brost  * - -EOVERFLOW, "GT ratio out of range"
227dd08ebf6SMatthew Brost  * - -EACCES, "PCODE Rejected"
228dd08ebf6SMatthew Brost  * - -EPROTO, "Unknown"
229dd08ebf6SMatthew Brost  */
xe_pcode_init_min_freq_table(struct xe_tile * tile,u32 min_gt_freq,u32 max_gt_freq)2303034cc81SMatt Roper int xe_pcode_init_min_freq_table(struct xe_tile *tile, u32 min_gt_freq,
231dd08ebf6SMatthew Brost 				 u32 max_gt_freq)
232dd08ebf6SMatthew Brost {
233dd08ebf6SMatthew Brost 	int ret;
234dd08ebf6SMatthew Brost 	u32 freq;
235dd08ebf6SMatthew Brost 
2363034cc81SMatt Roper 	if (!tile_to_xe(tile)->info.has_llc)
237dd08ebf6SMatthew Brost 		return 0;
238dd08ebf6SMatthew Brost 
239dd08ebf6SMatthew Brost 	if (max_gt_freq <= min_gt_freq)
240dd08ebf6SMatthew Brost 		return -EINVAL;
241dd08ebf6SMatthew Brost 
2423034cc81SMatt Roper 	mutex_lock(&tile->pcode.lock);
243dd08ebf6SMatthew Brost 	for (freq = min_gt_freq; freq <= max_gt_freq; freq++) {
244dd08ebf6SMatthew Brost 		u32 data = freq << PCODE_FREQ_RING_RATIO_SHIFT | freq;
245dd08ebf6SMatthew Brost 
2463034cc81SMatt Roper 		ret = pcode_mailbox_rw(tile, PCODE_WRITE_MIN_FREQ_TABLE,
247dd08ebf6SMatthew Brost 				       &data, NULL, 1, false, false);
248dd08ebf6SMatthew Brost 		if (ret)
249dd08ebf6SMatthew Brost 			goto unlock;
250dd08ebf6SMatthew Brost 	}
251dd08ebf6SMatthew Brost 
252dd08ebf6SMatthew Brost unlock:
2533034cc81SMatt Roper 	mutex_unlock(&tile->pcode.lock);
254dd08ebf6SMatthew Brost 	return ret;
255dd08ebf6SMatthew Brost }
256dd08ebf6SMatthew Brost 
257dd08ebf6SMatthew Brost /**
258933fd5ffSRiana Tauro  * xe_pcode_ready - Ensure PCODE is initialized
259933fd5ffSRiana Tauro  * @xe: xe instance
260933fd5ffSRiana Tauro  * @locked: true if lock held, false otherwise
261dd08ebf6SMatthew Brost  *
262933fd5ffSRiana Tauro  * PCODE init mailbox is polled only on root gt of root tile
263933fd5ffSRiana Tauro  * as the root tile provides the initialization is complete only
264933fd5ffSRiana Tauro  * after all the tiles have completed the initialization.
265933fd5ffSRiana Tauro  * Called only on early probe without locks and with locks in
266933fd5ffSRiana Tauro  * resume path.
267dd08ebf6SMatthew Brost  *
268933fd5ffSRiana Tauro  * Returns 0 on success, and -error number on failure.
269dd08ebf6SMatthew Brost  */
xe_pcode_ready(struct xe_device * xe,bool locked)270933fd5ffSRiana Tauro int xe_pcode_ready(struct xe_device *xe, bool locked)
271dd08ebf6SMatthew Brost {
2727dc9b92dSRodrigo Vivi 	u32 status, request = DGFX_GET_INIT_STATUS;
2733034cc81SMatt Roper 	struct xe_tile *tile = xe_device_get_root_tile(xe);
2747dc9b92dSRodrigo Vivi 	int timeout_us = 180000000; /* 3 min */
275dd08ebf6SMatthew Brost 	int ret;
276dd08ebf6SMatthew Brost 
277933fd5ffSRiana Tauro 	if (xe->info.skip_pcode)
278082802a3SKoby Elbaz 		return 0;
279082802a3SKoby Elbaz 
280933fd5ffSRiana Tauro 	if (!IS_DGFX(xe))
281dd08ebf6SMatthew Brost 		return 0;
282dd08ebf6SMatthew Brost 
283933fd5ffSRiana Tauro 	if (locked)
2843034cc81SMatt Roper 		mutex_lock(&tile->pcode.lock);
285933fd5ffSRiana Tauro 
2863034cc81SMatt Roper 	ret = pcode_try_request(tile, DGFX_PCODE_STATUS, request,
2877dc9b92dSRodrigo Vivi 				DGFX_INIT_STATUS_COMPLETE,
2887dc9b92dSRodrigo Vivi 				DGFX_INIT_STATUS_COMPLETE,
289933fd5ffSRiana Tauro 				&status, false, timeout_us, locked);
290933fd5ffSRiana Tauro 
291933fd5ffSRiana Tauro 	if (locked)
2923034cc81SMatt Roper 		mutex_unlock(&tile->pcode.lock);
293dd08ebf6SMatthew Brost 
294dd08ebf6SMatthew Brost 	if (ret)
295933fd5ffSRiana Tauro 		drm_err(&xe->drm,
2967dc9b92dSRodrigo Vivi 			"PCODE initialization timedout after: 3 min\n");
297dd08ebf6SMatthew Brost 
298dd08ebf6SMatthew Brost 	return ret;
299dd08ebf6SMatthew Brost }
300dd08ebf6SMatthew Brost 
301dd08ebf6SMatthew Brost /**
302933fd5ffSRiana Tauro  * xe_pcode_init: initialize components of PCODE
3033034cc81SMatt Roper  * @tile: tile instance
304dd08ebf6SMatthew Brost  *
305933fd5ffSRiana Tauro  * This function initializes the xe_pcode component.
306933fd5ffSRiana Tauro  * To be called once only during probe.
307dd08ebf6SMatthew Brost  */
xe_pcode_init(struct xe_tile * tile)3083034cc81SMatt Roper void xe_pcode_init(struct xe_tile *tile)
309dd08ebf6SMatthew Brost {
3103034cc81SMatt Roper 	drmm_mutex_init(&tile_to_xe(tile)->drm, &tile->pcode.lock);
311933fd5ffSRiana Tauro }
312dd08ebf6SMatthew Brost 
313933fd5ffSRiana Tauro /**
314933fd5ffSRiana Tauro  * xe_pcode_probe_early: initializes PCODE
315933fd5ffSRiana Tauro  * @xe: xe instance
316933fd5ffSRiana Tauro  *
317933fd5ffSRiana Tauro  * This function checks the initialization status of PCODE
318933fd5ffSRiana Tauro  * To be called once only during early probe without locks.
319933fd5ffSRiana Tauro  *
320933fd5ffSRiana Tauro  * Returns 0 on success, error code otherwise
321933fd5ffSRiana Tauro  */
xe_pcode_probe_early(struct xe_device * xe)322933fd5ffSRiana Tauro int xe_pcode_probe_early(struct xe_device *xe)
323933fd5ffSRiana Tauro {
324933fd5ffSRiana Tauro 	return xe_pcode_ready(xe, false);
325dd08ebf6SMatthew Brost }
326