drivers/gpu/drm/xe/xe_pcode.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/xe/xe_pcode.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/xe/xe_pcode.c
Extension
.c
Size
9836 bytes
Lines
351
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: MIT
/*
 * Copyright © 2022 Intel Corporation
 */

#include "xe_pcode.h"

#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/error-injection.h>

#include <drm/drm_managed.h>

#include "xe_assert.h"
#include "xe_device.h"
#include "xe_mmio.h"
#include "xe_pcode_api.h"

/**
 * DOC: PCODE
 *
 * Xe PCODE is the component responsible for interfacing with the PCODE
 * firmware.
 * It shall provide a very simple ABI to other Xe components, but be the
 * single and consolidated place that will communicate with PCODE. All read
 * and write operations to PCODE will be internal and private to this component.
 *
 * What's next:
 * - PCODE hw metrics
 * - PCODE for display operations
 */

static int pcode_mailbox_status(struct xe_tile *tile)
{
	const char *err_str;
	int err_decode;
	u32 err;

#define CASE_ERR(_err, _err_decode, _err_str)	\
	case _err:				\
		err_decode = _err_decode;	\
		err_str = _err_str;		\
		break

	err = xe_mmio_read32(&tile->mmio, PCODE_MAILBOX) & PCODE_ERROR_MASK;
	switch (err) {
	CASE_ERR(PCODE_ILLEGAL_CMD,           -ENXIO,     "Illegal Command");
	CASE_ERR(PCODE_TIMEOUT,               -ETIMEDOUT, "Timed out");
	CASE_ERR(PCODE_ILLEGAL_DATA,          -EINVAL,    "Illegal Data");
	CASE_ERR(PCODE_ILLEGAL_SUBCOMMAND,    -ENXIO,     "Illegal Subcommand");
	CASE_ERR(PCODE_LOCKED,                -EBUSY,     "PCODE Locked");
	CASE_ERR(PCODE_GT_RATIO_OUT_OF_RANGE, -EOVERFLOW, "GT ratio out of range");
	CASE_ERR(PCODE_REJECTED,              -EACCES,    "PCODE Rejected");
	default:
		err_decode = -EPROTO;
		err_str = "Unknown";
	}

	if (err) {
		drm_err(&tile_to_xe(tile)->drm, "PCODE Mailbox failed: %d %s",
			err_decode, err_str);

		return err_decode;
	}

	return 0;
#undef CASE_ERR
}

static int __pcode_mailbox_rw(struct xe_tile *tile, u32 mbox, u32 *data0, u32 *data1,
			      unsigned int timeout_ms, bool return_data,
			      bool atomic)
{
	struct xe_mmio *mmio = &tile->mmio;
	int err;

	if (tile_to_xe(tile)->info.skip_pcode)
		return 0;

	if ((xe_mmio_read32(mmio, PCODE_MAILBOX) & PCODE_READY) != 0)
		return -EAGAIN;

	xe_mmio_write32(mmio, PCODE_DATA0, *data0);
	xe_mmio_write32(mmio, PCODE_DATA1, data1 ? *data1 : 0);
	xe_mmio_write32(mmio, PCODE_MAILBOX, PCODE_READY | mbox);

	err = xe_mmio_wait32(mmio, PCODE_MAILBOX, PCODE_READY, 0,
			     timeout_ms * USEC_PER_MSEC, NULL, atomic);
	if (err)
		return err;

Annotation

Implementation Notes