#include "../../i915/i915_reg_defs.h"
+/**
+ * struct xe_reg - Register definition
+ *
+ * Register defintion to be used by the individual register. Although the same
+ * definition is used for xe_reg and xe_reg_mcr, they use different internal
+ * APIs for accesses.
+ */
+struct xe_reg {
+ union {
+ struct {
+ /** @reg: address */
+ u32 reg:22;
+ /**
+ * @masked: register is "masked", with upper 16bits used
+ * to identify the bits that are updated on the lower
+ * bits
+ */
+ u32 masked:1;
+ /**
+ * @mcr: register is multicast/replicated in the
+ * hardware and needs special handling. Any register
+ * with this set should also use a type of xe_reg_mcr_t.
+ * It's only here so the few places that deal with MCR
+ * registers specially (xe_sr.c) and tests using the raw
+ * value can inspect it.
+ */
+ u32 mcr:1;
+ };
+ /** @raw: Raw value with both address and options */
+ u32 raw;
+ };
+};
+
+/**
+ * struct xe_reg_mcr - MCR register definition
+ *
+ * MCR register is the same as a regular register, but uses another type since
+ * the internal API used for accessing them is different: it's never correct to
+ * use regular MMIO access.
+ */
+struct xe_reg_mcr {
+ /** @__reg: The register */
+ struct xe_reg __reg;
+};
+
+
+/**
+ * XE_REG_OPTION_MASKED - Register is "masked", with upper 16 bits marking the
+ * read/written bits on the lower 16 bits.
+ *
+ * To be used with XE_REG(). XE_REG_MCR() and XE_REG_INITIALIZER()
+ */
+#define XE_REG_OPTION_MASKED .masked = 1
+
+/**
+ * XE_REG_INITIALIZER - Initializer for xe_reg_t.
+ * @r_: Register offset
+ * @...: Additional options like access mode. See struct xe_reg for available
+ * options.
+ *
+ * Register field is mandatory, and additional options may be passed as
+ * arguments. Usually ``XE_REG()`` should be preferred since it creates an
+ * object of the right type. However when initializing static const storage,
+ * where a compound statement is not allowed, this can be used instead.
+ */
+#define XE_REG_INITIALIZER(r_, ...) { .reg = r_, __VA_ARGS__ }
+
+
+/**
+ * XE_REG - Create a struct xe_reg from offset and additional flags
+ * @r_: Register offset
+ * @...: Additional options like access mode. See struct xe_reg for available
+ * options.
+ */
+#define XE_REG(r_, ...) ((const struct xe_reg)XE_REG_INITIALIZER(r_, ##__VA_ARGS__))
+
+/**
+ * XE_REG_MCR - Create a struct xe_reg_mcr from offset and additional flags
+ * @r_: Register offset
+ * @...: Additional options like access mode. See struct xe_reg for available
+ * options.
+ */
+#define XE_REG_MCR(r_, ...) ((const struct xe_reg_mcr){ \
+ .__reg = XE_REG_INITIALIZER(r_, ##__VA_ARGS__, .mcr = 1) \
+ })
+
+/*
+ * TODO: remove these once the register declarations are not using them anymore
+ */
+#undef _MMIO
+#undef MCR_REG
+#define _MMIO(r_) ((const struct xe_reg){ .reg = r_ })
+#define MCR_REG(r_) ((const struct xe_reg_mcr){ .__reg.reg = r_, \
+ .__reg.mcr = 1 })
+
#endif
* non-terminated instance.
*/
+static inline struct xe_reg to_xe_reg(struct xe_reg_mcr reg_mcr)
+{
+ return reg_mcr.__reg;
+}
+
enum {
MCR_OP_READ,
MCR_OP_WRITE
* returned. Returns false if the caller need not perform any steering
*/
static bool xe_gt_mcr_get_nonterminated_steering(struct xe_gt *gt,
- i915_mcr_reg_t reg,
+ struct xe_reg_mcr reg_mcr,
u8 *group, u8 *instance)
{
+ const struct xe_reg reg = to_xe_reg(reg_mcr);
const struct xe_mmio_range *implicit_ranges;
for (int type = 0; type < IMPLICIT_STEERING; type++) {
*
* Caller needs to make sure the relevant forcewake wells are up.
*/
-static u32 rw_with_mcr_steering(struct xe_gt *gt, i915_mcr_reg_t reg, u8 rw_flag,
- int group, int instance, u32 value)
+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)
{
+ const struct xe_reg reg = to_xe_reg(reg_mcr);
u32 steer_reg, steer_val, val = 0;
lockdep_assert_held(>->mcr_lock);
/**
* xe_gt_mcr_unicast_read_any - reads a non-terminated instance of an MCR register
* @gt: GT structure
- * @reg: register to read
+ * @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).
*
* Returns the value from a non-terminated instance of @reg.
*/
-u32 xe_gt_mcr_unicast_read_any(struct xe_gt *gt, i915_mcr_reg_t reg)
+u32 xe_gt_mcr_unicast_read_any(struct xe_gt *gt, struct xe_reg_mcr reg_mcr)
{
+ const struct xe_reg reg = to_xe_reg(reg_mcr);
u8 group, instance;
u32 val;
bool steer;
- steer = xe_gt_mcr_get_nonterminated_steering(gt, reg, &group, &instance);
+ steer = xe_gt_mcr_get_nonterminated_steering(gt, reg_mcr,
+ &group, &instance);
if (steer) {
mcr_lock(gt);
- val = rw_with_mcr_steering(gt, reg, MCR_OP_READ,
+ val = rw_with_mcr_steering(gt, reg_mcr, MCR_OP_READ,
group, instance, 0);
mcr_unlock(gt);
} else {
/**
* xe_gt_mcr_unicast_read - read a specific instance of an MCR register
* @gt: GT structure
- * @reg: the MCR register to read
+ * @reg_mcr: the MCR register to read
* @group: the MCR group
* @instance: the MCR instance
*
* group/instance.
*/
u32 xe_gt_mcr_unicast_read(struct xe_gt *gt,
- i915_mcr_reg_t reg,
+ struct xe_reg_mcr reg_mcr,
int group, int instance)
{
u32 val;
mcr_lock(gt);
- val = rw_with_mcr_steering(gt, reg, MCR_OP_READ, group, instance, 0);
+ val = rw_with_mcr_steering(gt, reg_mcr, MCR_OP_READ, group, instance, 0);
mcr_unlock(gt);
return val;
/**
* xe_gt_mcr_unicast_write - write a specific instance of an MCR register
* @gt: GT structure
- * @reg: the MCR register to write
+ * @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, i915_mcr_reg_t reg, u32 value,
- int group, int instance)
+void xe_gt_mcr_unicast_write(struct xe_gt *gt, struct xe_reg_mcr reg_mcr,
+ u32 value, int group, int instance)
{
mcr_lock(gt);
- rw_with_mcr_steering(gt, reg, MCR_OP_WRITE, group, instance, value);
+ rw_with_mcr_steering(gt, reg_mcr, MCR_OP_WRITE, group, instance, value);
mcr_unlock(gt);
}
/**
* xe_gt_mcr_multicast_write - write a value to all instances of an MCR register
* @gt: GT structure
- * @reg: the MCR register to write
+ * @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, i915_mcr_reg_t reg, u32 value)
+void xe_gt_mcr_multicast_write(struct xe_gt *gt, struct xe_reg_mcr reg_mcr,
+ u32 value)
{
+ struct xe_reg reg = to_xe_reg(reg_mcr);
+
/*
* Synchronize with any unicast operations. Once we have exclusive
* access, the MULTICAST bit should already be set, so there's no need
void xe_gt_mcr_set_implicit_defaults(struct xe_gt *gt);
-u32 xe_gt_mcr_unicast_read(struct xe_gt *gt, i915_mcr_reg_t reg,
+u32 xe_gt_mcr_unicast_read(struct xe_gt *gt, struct xe_reg_mcr mcr_reg,
int group, int instance);
-u32 xe_gt_mcr_unicast_read_any(struct xe_gt *gt, i915_mcr_reg_t reg);
+u32 xe_gt_mcr_unicast_read_any(struct xe_gt *gt, struct xe_reg_mcr mcr_reg);
-void xe_gt_mcr_unicast_write(struct xe_gt *gt, i915_mcr_reg_t reg, u32 value,
- int group, int instance);
-void xe_gt_mcr_multicast_write(struct xe_gt *gt, i915_mcr_reg_t reg, u32 value);
+void xe_gt_mcr_unicast_write(struct xe_gt *gt, struct xe_reg_mcr mcr_reg,
+ u32 value, int group, int instance);
+void xe_gt_mcr_multicast_write(struct xe_gt *gt, struct xe_reg_mcr mcr_reg,
+ u32 value);
void xe_gt_mcr_steering_dump(struct xe_gt *gt, struct drm_printer *p);