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

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

#include "xe_gt_mcr.h"

#include "regs/xe_gt_regs.h"
#include "xe_assert.h"
#include "xe_gt.h"
#include "xe_gt_topology.h"
#include "xe_gt_types.h"
#include "xe_mmio.h"
#include "xe_sriov.h"

/**
 * DOC: GT Multicast/Replicated (MCR) Register Support
 *
 * Some GT registers are designed as "multicast" or "replicated" registers:
 * multiple instances of the same register share a single MMIO offset.  MCR
 * registers are generally used when the hardware needs to potentially track
 * independent values of a register per hardware unit (e.g., per-subslice,
 * per-L3bank, etc.).  The specific types of replication that exist vary
 * per-platform.
 *
 * MMIO accesses to MCR registers are controlled according to the settings
 * programmed in the platform's MCR_SELECTOR register(s).  MMIO writes to MCR
 * registers can be done in either multicast (a single write updates all
 * instances of the register to the same value) or unicast (a write updates only
 * one specific instance) form.  Reads of MCR registers always operate in a
 * unicast manner regardless of how the multicast/unicast bit is set in
 * MCR_SELECTOR.  Selection of a specific MCR instance for unicast operations is
 * referred to as "steering."
 *
 * If MCR register operations are steered toward a hardware unit that is
 * fused off or currently powered down due to power gating, the MMIO operation
 * is "terminated" by the hardware.  Terminated read operations will return a
 * value of zero and terminated unicast write operations will be silently
 * ignored. During device initialization, the goal of the various
 * ``init_steering_*()`` functions is to apply the platform-specific rules for
 * each MCR register type to identify a steering target that will select a
 * non-terminated instance.
 *
 * MCR registers are not available on Virtual Function (VF).
 */

#define STEER_SEMAPHORE

static inline struct xe_reg to_xe_reg(struct xe_reg_mcr reg_mcr)
{}

enum {};

static const struct xe_mmio_range xelp_l3bank_steering_table[] =;

static const struct xe_mmio_range xehp_l3bank_steering_table[] =;

/*
 * Although the bspec lists more "MSLICE" ranges than shown here, some of those
 * are of a "GAM" subclass that has special rules and doesn't need to be
 * included here.
 */
static const struct xe_mmio_range xehp_mslice_steering_table[] =;

static const struct xe_mmio_range xehp_lncf_steering_table[] =;

/*
 * We have several types of MCR registers where steering to (0,0) will always
 * provide us with a non-terminated value.  We'll stick them all in the same
 * table for simplicity.
 */
static const struct xe_mmio_range xehpc_instance0_steering_table[] =;

static const struct xe_mmio_range xelpg_instance0_steering_table[] =;

static const struct xe_mmio_range xelpg_l3bank_steering_table[] =;

static const struct xe_mmio_range xelp_dss_steering_table[] =;

/* DSS steering is used for GSLICE ranges as well */
static const struct xe_mmio_range xehp_dss_steering_table[] =;

/* DSS steering is used for COMPUTE ranges as well */
static const struct xe_mmio_range xehpc_dss_steering_table[] =;

/* DSS steering is used for SLICE ranges as well */
static const struct xe_mmio_range xelpg_dss_steering_table[] =;

static const struct xe_mmio_range xelpmp_oaddrm_steering_table[] =;

static const struct xe_mmio_range dg2_implicit_steering_table[] =;

static const struct xe_mmio_range xe2lpg_dss_steering_table[] =;

static const struct xe_mmio_range xe2lpg_sqidi_psmi_steering_table[] =;

static const struct xe_mmio_range xe2lpg_instance0_steering_table[] =;

static const struct xe_mmio_range xe2lpm_gpmxmt_steering_table[] =;

static const struct xe_mmio_range xe2lpm_instance0_steering_table[] =;

static void init_steering_l3bank(struct xe_gt *gt)
{}

static void init_steering_mslice(struct xe_gt *gt)
{}

static unsigned int dss_per_group(struct xe_gt *gt)
{}

/**
 * xe_gt_mcr_get_dss_steering - Get the group/instance steering for a DSS
 * @gt: GT structure
 * @dss: DSS ID to obtain steering for
 * @group: pointer to storage for steering group ID
 * @instance: pointer to storage for steering instance ID
 */
void xe_gt_mcr_get_dss_steering(struct xe_gt *gt, unsigned int dss, u16 *group, u16 *instance)
{}

static void init_steering_dss(struct xe_gt *gt)
{}

static void init_steering_oaddrm(struct xe_gt *gt)
{}

static void init_steering_sqidi_psmi(struct xe_gt *gt)
{}

static void init_steering_inst0(struct xe_gt *gt)
{}

static const struct {} xe_steering_types[] =;

/**
 * xe_gt_mcr_init_early - Early initialization of the MCR support
 * @gt: GT structure
 *
 * Perform early software only initialization of the MCR lock to allow
 * the synchronization on accessing the STEER_SEMAPHORE register and
 * use the xe_gt_mcr_multicast_write() function.
 */
void xe_gt_mcr_init_early(struct xe_gt *gt)
{}

/**
 * xe_gt_mcr_init - Normal initialization of the MCR support
 * @gt: GT structure
 *
 * Perform normal initialization of the MCR for all usages.
 */
void xe_gt_mcr_init(struct xe_gt *gt)
{}

/**
 * xe_gt_mcr_set_implicit_defaults - Initialize steer control registers
 * @gt: GT structure
 *
 * Some register ranges don't need to have their steering control registers
 * changed on each access - it's sufficient to set them once on initialization.
 * This function sets those registers for each platform *
 */
void xe_gt_mcr_set_implicit_defaults(struct xe_gt *gt)
{}

/*
 * xe_gt_mcr_get_nonterminated_steering - find group/instance values that
 *    will steer a register to a non-terminated instance
 * @gt: GT structure
 * @reg: register for which the steering is required
 * @group: return variable for group steering
 * @instance: return variable for instance steering
 *
 * This function returns a group/instance pair that is guaranteed to work for
 * read steering of the given register. Note that a value will be returned even
 * if the register is not replicated and therefore does not actually require
 * steering.
 *
 * Returns true if the caller should steer to the @group/@instance values
 * returned.  Returns false if the caller need not perform any steering
 */
static bool xe_gt_mcr_get_nonterminated_steering(struct xe_gt *gt,
						 struct xe_reg_mcr reg_mcr,
						 u8 *group, u8 *instance)
{}

/*
 * Obtain exclusive access to MCR steering.  On MTL and beyond we also need
 * to synchronize with external clients (e.g., firmware), so a semaphore
 * register will also need to be taken.
 */
static void mcr_lock(struct xe_gt *gt) __acquires(&gt->mcr_lock)
{}

static void mcr_unlock(struct xe_gt *gt) __releases(&gt->mcr_lock)
{}

/*
 * Access a register with specific MCR steering
 *
 * Caller needs to make sure the relevant forcewake wells are up.
 */
static u32 rw_with_mcr_steering(struct xe_gt *gt, struct xe_reg_mcr reg_mcr,
				u8 rw_flag, int group, int instance, u32 value)
{}

/**
 * xe_gt_mcr_unicast_read_any - reads a non-terminated instance of an MCR register
 * @gt: GT structure
 * @reg_mcr: register to read
 *
 * Reads a GT MCR register.  The read will be steered to a non-terminated
 * instance (i.e., one that isn't fused off or powered down by power gating).
 * This function assumes the caller is already holding any necessary forcewake
 * domains.
 *
 * Returns the value from a non-terminated instance of @reg.
 */
u32 xe_gt_mcr_unicast_read_any(struct xe_gt *gt, struct xe_reg_mcr reg_mcr)
{}

/**
 * xe_gt_mcr_unicast_read - read a specific instance of an MCR register
 * @gt: GT structure
 * @reg_mcr: the MCR register to read
 * @group: the MCR group
 * @instance: the MCR instance
 *
 * Returns the value read from an MCR register after steering toward a specific
 * group/instance.
 */
u32 xe_gt_mcr_unicast_read(struct xe_gt *gt,
			   struct xe_reg_mcr reg_mcr,
			   int group, int instance)
{}

/**
 * xe_gt_mcr_unicast_write - write a specific instance of an MCR register
 * @gt: GT structure
 * @reg_mcr: the MCR register to write
 * @value: value to write
 * @group: the MCR group
 * @instance: the MCR instance
 *
 * Write an MCR register in unicast mode after steering toward a specific
 * group/instance.
 */
void xe_gt_mcr_unicast_write(struct xe_gt *gt, struct xe_reg_mcr reg_mcr,
			     u32 value, int group, int instance)
{}

/**
 * xe_gt_mcr_multicast_write - write a value to all instances of an MCR register
 * @gt: GT structure
 * @reg_mcr: the MCR register to write
 * @value: value to write
 *
 * Write an MCR register in multicast mode to update all instances.
 */
void xe_gt_mcr_multicast_write(struct xe_gt *gt, struct xe_reg_mcr reg_mcr,
			       u32 value)
{}

void xe_gt_mcr_steering_dump(struct xe_gt *gt, struct drm_printer *p)
{}