linux/drivers/gpu/drm/xe/xe_gsc_proxy.c

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

#include "xe_gsc_proxy.h"

#include <linux/component.h>
#include <linux/delay.h>

#include <drm/drm_managed.h>
#include <drm/intel/i915_component.h>
#include <drm/intel/i915_gsc_proxy_mei_interface.h>

#include "abi/gsc_proxy_commands_abi.h"
#include "regs/xe_gsc_regs.h"
#include "xe_bo.h"
#include "xe_force_wake.h"
#include "xe_gsc.h"
#include "xe_gsc_submit.h"
#include "xe_gt.h"
#include "xe_gt_printk.h"
#include "xe_map.h"
#include "xe_mmio.h"
#include "xe_pm.h"

/*
 * GSC proxy:
 * The GSC uC needs to communicate with the CSME to perform certain operations.
 * Since the GSC can't perform this communication directly on platforms where it
 * is integrated in GT, the graphics driver needs to transfer the messages from
 * GSC to CSME and back. The proxy flow must be manually started after the GSC
 * is loaded to signal to GSC that we're ready to handle its messages and allow
 * it to query its init data from CSME; GSC will then trigger an HECI2 interrupt
 * if it needs to send messages to CSME again.
 * The proxy flow is as follow:
 * 1 - Xe submits a request to GSC asking for the message to CSME
 * 2 - GSC replies with the proxy header + payload for CSME
 * 3 - Xe sends the reply from GSC as-is to CSME via the mei proxy component
 * 4 - CSME replies with the proxy header + payload for GSC
 * 5 - Xe submits a request to GSC with the reply from CSME
 * 6 - GSC replies either with a new header + payload (same as step 2, so we
 *     restart from there) or with an end message.
 */

/*
 * The component should load quite quickly in most cases, but it could take
 * a bit. Using a very big timeout just to cover the worst case scenario
 */
#define GSC_PROXY_INIT_TIMEOUT_MS

/* shorthand define for code compactness */
#define PROXY_HDR_SIZE

/* the protocol supports up to 32K in each direction */
#define GSC_PROXY_BUFFER_SIZE
#define GSC_PROXY_CHANNEL_SIZE

static struct xe_gt *
gsc_to_gt(struct xe_gsc *gsc)
{}

static inline struct xe_device *kdev_to_xe(struct device *kdev)
{}

bool xe_gsc_proxy_init_done(struct xe_gsc *gsc)
{}

static void __gsc_proxy_irq_rmw(struct xe_gsc *gsc, u32 clr, u32 set)
{}

static void gsc_proxy_irq_clear(struct xe_gsc *gsc)
{}

static void gsc_proxy_irq_toggle(struct xe_gsc *gsc, bool enabled)
{}

static int proxy_send_to_csme(struct xe_gsc *gsc, u32 size)
{}

static int proxy_send_to_gsc(struct xe_gsc *gsc, u32 size)
{}

static int validate_proxy_header(struct xe_gsc_proxy_header *header,
				 u32 source, u32 dest, u32 max_size)
{}

#define proxy_header_wr(xe_, map_, offset_, field_, val_)

#define proxy_header_rd(xe_, map_, offset_, field_)

static u32 emit_proxy_header(struct xe_device *xe, struct iosys_map *map, u32 offset)
{}

static int proxy_query(struct xe_gsc *gsc)
{}

int xe_gsc_proxy_request_handler(struct xe_gsc *gsc)
{}

void xe_gsc_proxy_irq_handler(struct xe_gsc *gsc, u32 iir)
{}

static int xe_gsc_proxy_component_bind(struct device *xe_kdev,
				       struct device *mei_kdev, void *data)
{}

static void xe_gsc_proxy_component_unbind(struct device *xe_kdev,
					  struct device *mei_kdev, void *data)
{}

static const struct component_ops xe_gsc_proxy_component_ops =;

static void proxy_channel_free(struct drm_device *drm, void *arg)
{}

static int proxy_channel_alloc(struct xe_gsc *gsc)
{}

/**
 * xe_gsc_proxy_init() - init objects and MEI component required by GSC proxy
 * @gsc: the GSC uC
 *
 * Return: 0 if the initialization was successful, a negative errno otherwise.
 */
int xe_gsc_proxy_init(struct xe_gsc *gsc)
{}

/**
 * xe_gsc_proxy_remove() - remove the GSC proxy MEI component
 * @gsc: the GSC uC
 */
void xe_gsc_proxy_remove(struct xe_gsc *gsc)
{}

/**
 * xe_gsc_proxy_start() - start the proxy by submitting the first request
 * @gsc: the GSC uC
 *
 * Return: 0 if the proxy are now enabled, a negative errno otherwise.
 */
int xe_gsc_proxy_start(struct xe_gsc *gsc)
{}