Commit 330ce9d3 authored by Alex Elder's avatar Alex Elder Committed by Jakub Kicinski
Browse files

net: ipa: define more fields for GSI registers



Beyond the CH_C_QOS register, two other registers whose offset is
related to channel number have fields within them.

Define the fields within the CH_C_CNTXT_0 GSI register, using an
enumerated type to identify the register's fields, and define an
array of field masks to use for that register's reg structure.

For the CH_C_CNTXT_1 GSI register, ch_c_cntxt_1_length_encode()
previously hid the difference in bit width in the channel ring
length field.  Instead, define a new field CH_R_LENGTH and encode
the ring size with reg_encode().

Signed-off-by: default avatarAlex Elder <elder@linaro.org>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent f50ca7ce
Loading
Loading
Loading
Loading
+10 −21
Original line number Diff line number Diff line
@@ -164,9 +164,6 @@ static void gsi_validate_build(void)
	 */
	BUILD_BUG_ON(!is_power_of_2(GSI_RING_ELEMENT_SIZE));

	/* The channel element size must fit in this field */
	BUILD_BUG_ON(GSI_RING_ELEMENT_SIZE > field_max(ELEMENT_SIZE_FMASK));

	/* The event ring element size must fit in this field */
	BUILD_BUG_ON(GSI_RING_ELEMENT_SIZE > field_max(EV_ELEMENT_SIZE_FMASK));
}
@@ -185,26 +182,18 @@ static bool gsi_channel_initialized(struct gsi_channel *channel)

/* Encode the channel protocol for the CH_C_CNTXT_0 register */
static u32 ch_c_cntxt_0_type_encode(enum ipa_version version,
				    const struct reg *reg,
				    enum gsi_channel_type type)
{
	u32 val;

	val = u32_encode_bits(type, CHTYPE_PROTOCOL_FMASK);
	val = reg_encode(reg, CHTYPE_PROTOCOL, type);
	if (version < IPA_VERSION_4_5)
		return val;

	type >>= hweight32(CHTYPE_PROTOCOL_FMASK);

	return val | u32_encode_bits(type, CHTYPE_PROTOCOL_MSB_FMASK);
}

/* Encode a channel ring buffer length for the CH_C_CNTXT_1 register */
static u32 ch_c_cntxt_1_length_encode(enum ipa_version version, u32 length)
{
	if (version < IPA_VERSION_4_9)
		return u32_encode_bits(length, GENMASK(15, 0));
	type >>= hweight32(reg_fmask(reg, CHTYPE_PROTOCOL));

	return u32_encode_bits(length, GENMASK(19, 0));
	return val | reg_encode(reg, CHTYPE_PROTOCOL_MSB, type);
}

/* Encode the length of the event channel ring buffer for the
@@ -544,7 +533,7 @@ static enum gsi_channel_state gsi_channel_state(struct gsi_channel *channel)
	reg = gsi_reg(gsi, CH_C_CNTXT_0);
	val = ioread32(virt + reg_n_offset(reg, channel_id));

	return u32_get_bits(val, CHSTATE_FMASK);
	return reg_decode(reg, CHSTATE, val);
}

/* Issue a channel command and wait for it to complete */
@@ -862,15 +851,15 @@ static void gsi_channel_program(struct gsi_channel *channel, bool doorbell)
	reg = gsi_reg(gsi, CH_C_CNTXT_0);

	/* We program all channels as GPI type/protocol */
	val = ch_c_cntxt_0_type_encode(gsi->version, GSI_CHANNEL_TYPE_GPI);
	val = ch_c_cntxt_0_type_encode(gsi->version, reg, GSI_CHANNEL_TYPE_GPI);
	if (channel->toward_ipa)
		val |= CHTYPE_DIR_FMASK;
	val |= u32_encode_bits(channel->evt_ring_id, ERINDEX_FMASK);
	val |= u32_encode_bits(GSI_RING_ELEMENT_SIZE, ELEMENT_SIZE_FMASK);
		val |= reg_bit(reg, CHTYPE_DIR);
	val |= reg_encode(reg, ERINDEX, channel->evt_ring_id);
	val |= reg_encode(reg, ELEMENT_SIZE, GSI_RING_ELEMENT_SIZE);
	iowrite32(val, gsi->virt + reg_n_offset(reg, channel_id));

	reg = gsi_reg(gsi, CH_C_CNTXT_1);
	val = ch_c_cntxt_1_length_encode(gsi->version, size);
	val = reg_encode(reg, CH_R_LENGTH, size);
	iowrite32(val, gsi->virt + reg_n_offset(reg, channel_id));

	/* The context 2 and 3 registers store the low-order and
+15 −9
Original line number Diff line number Diff line
@@ -96,15 +96,16 @@ enum gsi_reg_id {
};

/* CH_C_CNTXT_0 register */
#define CHTYPE_PROTOCOL_FMASK		GENMASK(2, 0)
#define CHTYPE_DIR_FMASK		GENMASK(3, 3)
#define EE_FMASK			GENMASK(7, 4)
#define CHID_FMASK			GENMASK(12, 8)
/* The next field is present for IPA v4.5 and above */
#define CHTYPE_PROTOCOL_MSB_FMASK	GENMASK(13, 13)
#define ERINDEX_FMASK			GENMASK(18, 14)
#define CHSTATE_FMASK			GENMASK(23, 20)
#define ELEMENT_SIZE_FMASK		GENMASK(31, 24)
enum gsi_reg_ch_c_cntxt_0_field_id {
	CHTYPE_PROTOCOL,
	CHTYPE_DIR,
	CH_EE,
	CHID,
	CHTYPE_PROTOCOL_MSB,				/* IPA v4.9+ */
	ERINDEX,
	CHSTATE,
	ELEMENT_SIZE,
};

/** enum gsi_channel_type - CHTYPE_PROTOCOL field values in CH_C_CNTXT_0 */
enum gsi_channel_type {
@@ -120,6 +121,11 @@ enum gsi_channel_type {
	GSI_CHANNEL_TYPE_11AD			= 0x9,
};

/* CH_C_CNTXT_1 register */
enum gsi_reg_ch_c_cntxt_1_field_id {
	CH_R_LENGTH,
};

/* CH_C_QOS register */
enum gsi_reg_ch_c_qos_field_id {
	WRR_WEIGHT,
+21 −2
Original line number Diff line number Diff line
@@ -18,9 +18,28 @@ REG(INTER_EE_SRC_EV_CH_IRQ_MSK, inter_ee_src_ev_ch_irq_msk,

/* All other register offsets are relative to gsi->virt */

REG_STRIDE(CH_C_CNTXT_0, ch_c_cntxt_0, 0x0001c000 + 0x4000 * GSI_EE_AP, 0x80);
static const u32 reg_ch_c_cntxt_0_fmask[] = {
	[CHTYPE_PROTOCOL]				= GENMASK(2, 0),
	[CHTYPE_DIR]					= BIT(3),
	[CH_EE]						= GENMASK(7, 4),
	[CHID]						= GENMASK(12, 8),
						/* Bit 13 reserved */
	[ERINDEX]					= GENMASK(18, 14),
						/* Bit 19 reserved */
	[CHSTATE]					= GENMASK(23, 20),
	[ELEMENT_SIZE]					= GENMASK(31, 24),
};

REG_STRIDE_FIELDS(CH_C_CNTXT_0, ch_c_cntxt_0,
		  0x0001c000 + 0x4000 * GSI_EE_AP, 0x80);

static const u32 reg_ch_c_cntxt_1_fmask[] = {
	[CH_R_LENGTH]					= GENMASK(15, 0),
						/* Bits 16-31 reserved */
};

REG_STRIDE(CH_C_CNTXT_1, ch_c_cntxt_1, 0x0001c004 + 0x4000 * GSI_EE_AP, 0x80);
REG_STRIDE_FIELDS(CH_C_CNTXT_1, ch_c_cntxt_1,
		  0x0001c004 + 0x4000 * GSI_EE_AP, 0x80);

REG_STRIDE(CH_C_CNTXT_2, ch_c_cntxt_2, 0x0001c008 + 0x4000 * GSI_EE_AP, 0x80);

+21 −2
Original line number Diff line number Diff line
@@ -18,9 +18,28 @@ REG(INTER_EE_SRC_EV_CH_IRQ_MSK, inter_ee_src_ev_ch_irq_msk,

/* All other register offsets are relative to gsi->virt */

REG_STRIDE(CH_C_CNTXT_0, ch_c_cntxt_0, 0x0001c000 + 0x4000 * GSI_EE_AP, 0x80);
static const u32 reg_ch_c_cntxt_0_fmask[] = {
	[CHTYPE_PROTOCOL]				= GENMASK(2, 0),
	[CHTYPE_DIR]					= BIT(3),
	[CH_EE]						= GENMASK(7, 4),
	[CHID]						= GENMASK(12, 8),
						/* Bit 13 reserved */
	[ERINDEX]					= GENMASK(18, 14),
						/* Bit 19 reserved */
	[CHSTATE]					= GENMASK(23, 20),
	[ELEMENT_SIZE]					= GENMASK(31, 24),
};

REG_STRIDE_FIELDS(CH_C_CNTXT_0, ch_c_cntxt_0,
		  0x0001c000 + 0x4000 * GSI_EE_AP, 0x80);

static const u32 reg_ch_c_cntxt_1_fmask[] = {
	[CH_R_LENGTH]					= GENMASK(15, 0),
						/* Bits 16-31 reserved */
};

REG_STRIDE(CH_C_CNTXT_1, ch_c_cntxt_1, 0x0001c004 + 0x4000 * GSI_EE_AP, 0x80);
REG_STRIDE_FIELDS(CH_C_CNTXT_1, ch_c_cntxt_1,
		  0x0001c004 + 0x4000 * GSI_EE_AP, 0x80);

REG_STRIDE(CH_C_CNTXT_2, ch_c_cntxt_2, 0x0001c008 + 0x4000 * GSI_EE_AP, 0x80);

+21 −2
Original line number Diff line number Diff line
@@ -18,9 +18,28 @@ REG(INTER_EE_SRC_EV_CH_IRQ_MSK, inter_ee_src_ev_ch_irq_msk,

/* All other register offsets are relative to gsi->virt */

REG_STRIDE(CH_C_CNTXT_0, ch_c_cntxt_0, 0x0001c000 + 0x4000 * GSI_EE_AP, 0x80);
static const u32 reg_ch_c_cntxt_0_fmask[] = {
	[CHTYPE_PROTOCOL]				= GENMASK(2, 0),
	[CHTYPE_DIR]					= BIT(3),
	[CH_EE]						= GENMASK(7, 4),
	[CHID]						= GENMASK(12, 8),
						/* Bit 13 reserved */
	[ERINDEX]					= GENMASK(18, 14),
						/* Bit 19 reserved */
	[CHSTATE]					= GENMASK(23, 20),
	[ELEMENT_SIZE]					= GENMASK(31, 24),
};

REG_STRIDE_FIELDS(CH_C_CNTXT_0, ch_c_cntxt_0,
		  0x0001c000 + 0x4000 * GSI_EE_AP, 0x80);

static const u32 reg_ch_c_cntxt_1_fmask[] = {
	[CH_R_LENGTH]					= GENMASK(15, 0),
						/* Bits 16-31 reserved */
};

REG_STRIDE(CH_C_CNTXT_1, ch_c_cntxt_1, 0x0001c004 + 0x4000 * GSI_EE_AP, 0x80);
REG_STRIDE_FIELDS(CH_C_CNTXT_1, ch_c_cntxt_1,
		  0x0001c004 + 0x4000 * GSI_EE_AP, 0x80);

REG_STRIDE(CH_C_CNTXT_2, ch_c_cntxt_2, 0x0001c008 + 0x4000 * GSI_EE_AP, 0x80);

Loading