Skip to content

Commit

Permalink
Merge branch 'net-ipa-GSI'
Browse files Browse the repository at this point in the history
Alex Elder says:

====================
net: ipa: prepare for GSI register updtaes

An upcoming series (or two) will convert the definitions of GSI
registers used by IPA so they use the "IPA reg" mechanism to specify
register offsets and their fields.  This will simplify implementing
the fairly large number of changes required in GSI registers to
support more than 32 GSI channels (introduced in IPA v5.0).

A few minor problems and inconsistencies were found, and they're
fixed here.  The last three patches in this series change the
"ipa_reg" code to separate the IPA-specific part (the base virtual
address, basically) from the generic register part, and the now-
generic code is renamed to use just "reg_" or "REG_" as a prefix
rather than "ipa_reg" or "IPA_REG_".
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Feb 10, 2023
2 parents 47400aa + f1470fd commit 01a7ee3
Show file tree
Hide file tree
Showing 22 changed files with 1,471 additions and 1,422 deletions.
82 changes: 59 additions & 23 deletions drivers/net/ipa/gsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,41 @@ static bool gsi_channel_initialized(struct gsi_channel *channel)
return !!channel->gsi;
}

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

val = u32_encode_bits(type, CHTYPE_PROTOCOL_FMASK);
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));

return u32_encode_bits(length, GENMASK(19, 0));
}

/* Encode the length of the event channel ring buffer for the
* EV_CH_E_CNTXT_1 register.
*/
static u32 ev_ch_e_cntxt_1_length_encode(enum ipa_version version, u32 length)
{
if (version < IPA_VERSION_4_9)
return u32_encode_bits(length, GENMASK(15, 0));

return u32_encode_bits(length, GENMASK(19, 0));
}

/* Update the GSI IRQ type register with the cached value */
static void gsi_irq_type_update(struct gsi *gsi, u32 val)
{
Expand All @@ -191,12 +226,12 @@ static void gsi_irq_type_update(struct gsi *gsi, u32 val)

static void gsi_irq_type_enable(struct gsi *gsi, enum gsi_irq_type_id type_id)
{
gsi_irq_type_update(gsi, gsi->type_enabled_bitmap | BIT(type_id));
gsi_irq_type_update(gsi, gsi->type_enabled_bitmap | type_id);
}

static void gsi_irq_type_disable(struct gsi *gsi, enum gsi_irq_type_id type_id)
{
gsi_irq_type_update(gsi, gsi->type_enabled_bitmap & ~BIT(type_id));
gsi_irq_type_update(gsi, gsi->type_enabled_bitmap & ~type_id);
}

/* Event ring commands are performed one at a time. Their completion
Expand Down Expand Up @@ -292,19 +327,19 @@ static void gsi_irq_enable(struct gsi *gsi)
/* Global interrupts include hardware error reports. Enable
* that so we can at least report the error should it occur.
*/
iowrite32(BIT(ERROR_INT), gsi->virt + GSI_CNTXT_GLOB_IRQ_EN_OFFSET);
gsi_irq_type_update(gsi, gsi->type_enabled_bitmap | BIT(GSI_GLOB_EE));
iowrite32(ERROR_INT, gsi->virt + GSI_CNTXT_GLOB_IRQ_EN_OFFSET);
gsi_irq_type_update(gsi, gsi->type_enabled_bitmap | GSI_GLOB_EE);

/* General GSI interrupts are reported to all EEs; if they occur
* they are unrecoverable (without reset). A breakpoint interrupt
* also exists, but we don't support that. We want to be notified
* of errors so we can report them, even if they can't be handled.
*/
val = BIT(BUS_ERROR);
val |= BIT(CMD_FIFO_OVRFLOW);
val |= BIT(MCS_STACK_OVRFLOW);
val = BUS_ERROR;
val |= CMD_FIFO_OVRFLOW;
val |= MCS_STACK_OVRFLOW;
iowrite32(val, gsi->virt + GSI_CNTXT_GSI_IRQ_EN_OFFSET);
gsi_irq_type_update(gsi, gsi->type_enabled_bitmap | BIT(GSI_GENERAL));
gsi_irq_type_update(gsi, gsi->type_enabled_bitmap | GSI_GENERAL);
}

/* Disable all GSI interrupt types */
Expand Down Expand Up @@ -676,7 +711,7 @@ static void gsi_evt_ring_program(struct gsi *gsi, u32 evt_ring_id)
iowrite32(val, gsi->virt + GSI_EV_CH_E_CNTXT_0_OFFSET(evt_ring_id));

size = ring->count * GSI_RING_ELEMENT_SIZE;
val = ev_r_length_encoded(gsi->version, size);
val = ev_ch_e_cntxt_1_length_encode(gsi->version, size);
iowrite32(val, gsi->virt + GSI_EV_CH_E_CNTXT_1_OFFSET(evt_ring_id));

/* The context 2 and 3 registers store the low-order and
Expand Down Expand Up @@ -765,14 +800,14 @@ static void gsi_channel_program(struct gsi_channel *channel, bool doorbell)
u32 val;

/* We program all channels as GPI type/protocol */
val = chtype_protocol_encoded(gsi->version, GSI_CHANNEL_TYPE_GPI);
val = ch_c_cntxt_0_type_encode(gsi->version, 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);
iowrite32(val, gsi->virt + GSI_CH_C_CNTXT_0_OFFSET(channel_id));

val = r_length_encoded(gsi->version, size);
val = ch_c_cntxt_1_length_encode(gsi->version, size);
iowrite32(val, gsi->virt + GSI_CH_C_CNTXT_1_OFFSET(channel_id));

/* The context 2 and 3 registers store the low-order and
Expand Down Expand Up @@ -1195,15 +1230,15 @@ static void gsi_isr_glob_ee(struct gsi *gsi)

val = ioread32(gsi->virt + GSI_CNTXT_GLOB_IRQ_STTS_OFFSET);

if (val & BIT(ERROR_INT))
if (val & ERROR_INT)
gsi_isr_glob_err(gsi);

iowrite32(val, gsi->virt + GSI_CNTXT_GLOB_IRQ_CLR_OFFSET);

val &= ~BIT(ERROR_INT);
val &= ~ERROR_INT;

if (val & BIT(GP_INT1)) {
val ^= BIT(GP_INT1);
if (val & GP_INT1) {
val ^= GP_INT1;
gsi_isr_gp_int1(gsi);
}

Expand Down Expand Up @@ -1264,19 +1299,19 @@ static irqreturn_t gsi_isr(int irq, void *dev_id)
intr_mask ^= gsi_intr;

switch (gsi_intr) {
case BIT(GSI_CH_CTRL):
case GSI_CH_CTRL:
gsi_isr_chan_ctrl(gsi);
break;
case BIT(GSI_EV_CTRL):
case GSI_EV_CTRL:
gsi_isr_evt_ctrl(gsi);
break;
case BIT(GSI_GLOB_EE):
case GSI_GLOB_EE:
gsi_isr_glob_ee(gsi);
break;
case BIT(GSI_IEOB):
case GSI_IEOB:
gsi_isr_ieob(gsi);
break;
case BIT(GSI_GENERAL):
case GSI_GENERAL:
gsi_isr_general(gsi);
break;
default:
Expand Down Expand Up @@ -1654,7 +1689,7 @@ static int gsi_generic_command(struct gsi *gsi, u32 channel_id,
* channel), and only from this function. So we enable the GP_INT1
* IRQ type here, and disable it again after the command completes.
*/
val = BIT(ERROR_INT) | BIT(GP_INT1);
val = ERROR_INT | GP_INT1;
iowrite32(val, gsi->virt + GSI_CNTXT_GLOB_IRQ_EN_OFFSET);

/* First zero the result code field */
Expand All @@ -1666,12 +1701,13 @@ static int gsi_generic_command(struct gsi *gsi, u32 channel_id,
val = u32_encode_bits(opcode, GENERIC_OPCODE_FMASK);
val |= u32_encode_bits(channel_id, GENERIC_CHID_FMASK);
val |= u32_encode_bits(GSI_EE_MODEM, GENERIC_EE_FMASK);
val |= u32_encode_bits(params, GENERIC_PARAMS_FMASK);
if (gsi->version >= IPA_VERSION_4_11)
val |= u32_encode_bits(params, GENERIC_PARAMS_FMASK);

timeout = !gsi_command(gsi, GSI_GENERIC_CMD_OFFSET, val);

/* Disable the GP_INT1 IRQ type again */
iowrite32(BIT(ERROR_INT), gsi->virt + GSI_CNTXT_GLOB_IRQ_EN_OFFSET);
iowrite32(ERROR_INT, gsi->virt + GSI_CNTXT_GLOB_IRQ_EN_OFFSET);

if (!timeout)
return gsi->result;
Expand Down
109 changes: 45 additions & 64 deletions drivers/net/ipa/gsi_reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,18 @@

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

#define GSI_CH_C_CNTXT_0_OFFSET(ch) \
(0x0001c000 + 0x4000 * GSI_EE_AP + 0x80 * (ch))
#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_channel_type - CHTYPE_PROTOCOL field values in CH_C_CNTXT_0 */
enum gsi_channel_type {
GSI_CHANNEL_TYPE_MHI = 0x0,
Expand All @@ -76,46 +88,9 @@ enum gsi_channel_type {
GSI_CHANNEL_TYPE_11AD = 0x9,
};

#define GSI_CH_C_CNTXT_0_OFFSET(ch) \
(0x0001c000 + 0x4000 * GSI_EE_AP + 0x80 * (ch))
#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)

/* Encoded value for CH_C_CNTXT_0 register channel protocol fields */
static inline u32
chtype_protocol_encoded(enum ipa_version version, enum gsi_channel_type type)
{
u32 val;

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

/* Encode upper bit(s) as well */
type >>= hweight32(CHTYPE_PROTOCOL_FMASK);
val |= u32_encode_bits(type, CHTYPE_PROTOCOL_MSB_FMASK);

return val;
}

#define GSI_CH_C_CNTXT_1_OFFSET(ch) \
(0x0001c004 + 0x4000 * GSI_EE_AP + 0x80 * (ch))

/* Encoded value for CH_C_CNTXT_1 register R_LENGTH field */
static inline u32 r_length_encoded(enum ipa_version version, u32 length)
{
if (version < IPA_VERSION_4_9)
return u32_encode_bits(length, GENMASK(15, 0));
return u32_encode_bits(length, GENMASK(19, 0));
}

#define GSI_CH_C_CNTXT_2_OFFSET(ch) \
(0x0001c008 + 0x4000 * GSI_EE_AP + 0x80 * (ch))

Expand Down Expand Up @@ -167,13 +142,6 @@ enum gsi_prefetch_mode {

#define GSI_EV_CH_E_CNTXT_1_OFFSET(ev) \
(0x0001d004 + 0x4000 * GSI_EE_AP + 0x80 * (ev))
/* Encoded value for EV_CH_C_CNTXT_1 register EV_R_LENGTH field */
static inline u32 ev_r_length_encoded(enum ipa_version version, u32 length)
{
if (version < IPA_VERSION_4_9)
return u32_encode_bits(length, GENMASK(15, 0));
return u32_encode_bits(length, GENMASK(19, 0));
}

#define GSI_EV_CH_E_CNTXT_2_OFFSET(ev) \
(0x0001d008 + 0x4000 * GSI_EE_AP + 0x80 * (ev))
Expand Down Expand Up @@ -299,15 +267,25 @@ enum gsi_iram_size {
#define GSI_CNTXT_TYPE_IRQ_MSK_OFFSET \
(0x0001f088 + 0x4000 * GSI_EE_AP)

/* Values here are bit positions in the TYPE_IRQ and TYPE_IRQ_MSK registers */
/**
* enum gsi_irq_type_id: GSI IRQ types
* @GSI_CH_CTRL: Channel allocation, deallocation, etc.
* @GSI_EV_CTRL: Event ring allocation, deallocation, etc.
* @GSI_GLOB_EE: Global/general event
* @GSI_IEOB: Transfer (TRE) completion
* @GSI_INTER_EE_CH_CTRL: Remote-issued stop/reset (unused)
* @GSI_INTER_EE_EV_CTRL: Remote-issued event reset (unused)
* @GSI_GENERAL: General hardware event (bus error, etc.)
*/
enum gsi_irq_type_id {
GSI_CH_CTRL = 0x0, /* channel allocation, etc. */
GSI_EV_CTRL = 0x1, /* event ring allocation, etc. */
GSI_GLOB_EE = 0x2, /* global/general event */
GSI_IEOB = 0x3, /* TRE completion */
GSI_INTER_EE_CH_CTRL = 0x4, /* remote-issued stop/reset (unused) */
GSI_INTER_EE_EV_CTRL = 0x5, /* remote-issued event reset (unused) */
GSI_GENERAL = 0x6, /* general-purpose event */
GSI_CH_CTRL = BIT(0),
GSI_EV_CTRL = BIT(1),
GSI_GLOB_EE = BIT(2),
GSI_IEOB = BIT(3),
GSI_INTER_EE_CH_CTRL = BIT(4),
GSI_INTER_EE_EV_CTRL = BIT(5),
GSI_GENERAL = BIT(6),
/* IRQ types 7-31 (and their bit values) are reserved */
};

#define GSI_CNTXT_SRC_CH_IRQ_OFFSET \
Expand Down Expand Up @@ -343,12 +321,14 @@ enum gsi_irq_type_id {
(0x0001f108 + 0x4000 * GSI_EE_AP)
#define GSI_CNTXT_GLOB_IRQ_CLR_OFFSET \
(0x0001f110 + 0x4000 * GSI_EE_AP)
/* Values here are bit positions in the GLOB_IRQ_* registers */

/** enum gsi_global_irq_id: Global GSI interrupt events */
enum gsi_global_irq_id {
ERROR_INT = 0x0,
GP_INT1 = 0x1,
GP_INT2 = 0x2,
GP_INT3 = 0x3,
ERROR_INT = BIT(0),
GP_INT1 = BIT(1),
GP_INT2 = BIT(2),
GP_INT3 = BIT(3),
/* Global IRQ types 4-31 (and their bit values) are reserved */
};

#define GSI_CNTXT_GSI_IRQ_STTS_OFFSET \
Expand All @@ -357,12 +337,14 @@ enum gsi_global_irq_id {
(0x0001f120 + 0x4000 * GSI_EE_AP)
#define GSI_CNTXT_GSI_IRQ_CLR_OFFSET \
(0x0001f128 + 0x4000 * GSI_EE_AP)
/* Values here are bit positions in the (general) GSI_IRQ_* registers */
enum gsi_general_id {
BREAK_POINT = 0x0,
BUS_ERROR = 0x1,
CMD_FIFO_OVRFLOW = 0x2,
MCS_STACK_OVRFLOW = 0x3,

/** enum gsi_general_irq_id: GSI general IRQ conditions */
enum gsi_general_irq_id {
BREAK_POINT = BIT(0),
BUS_ERROR = BIT(1),
CMD_FIFO_OVRFLOW = BIT(2),
MCS_STACK_OVRFLOW = BIT(3),
/* General IRQ types 4-31 (and their bit values) are reserved */
};

#define GSI_CNTXT_INTSET_OFFSET \
Expand All @@ -372,7 +354,6 @@ enum gsi_general_id {
#define GSI_ERROR_LOG_OFFSET \
(0x0001f200 + 0x4000 * GSI_EE_AP)

/* Fields below are present for IPA v3.5.1 and above */
#define ERR_ARG3_FMASK GENMASK(3, 0)
#define ERR_ARG2_FMASK GENMASK(7, 4)
#define ERR_ARG1_FMASK GENMASK(11, 8)
Expand Down
4 changes: 1 addition & 3 deletions drivers/net/ipa/ipa.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ struct ipa_interrupt;
* @interrupt: IPA Interrupt information
* @uc_powered: true if power is active by proxy for microcontroller
* @uc_loaded: true after microcontroller has reported it's ready
* @reg_addr: DMA address used for IPA register access
* @reg_virt: Virtual address used for IPA register access
* @regs: IPA register definitions
* @mem_addr: DMA address of IPA-local memory space
Expand Down Expand Up @@ -97,9 +96,8 @@ struct ipa {
bool uc_powered;
bool uc_loaded;

dma_addr_t reg_addr;
void __iomem *reg_virt;
const struct ipa_regs *regs;
const struct regs *regs;

dma_addr_t mem_addr;
void *mem_virt;
Expand Down
6 changes: 3 additions & 3 deletions drivers/net/ipa/ipa_cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ static bool ipa_cmd_register_write_offset_valid(struct ipa *ipa,
/* Check whether offsets passed to register_write are valid */
static bool ipa_cmd_register_write_valid(struct ipa *ipa)
{
const struct ipa_reg *reg;
const struct reg *reg;
const char *name;
u32 offset;

Expand All @@ -300,7 +300,7 @@ static bool ipa_cmd_register_write_valid(struct ipa *ipa)
else
reg = ipa_reg(ipa, FILT_ROUT_CACHE_FLUSH);

offset = ipa_reg_offset(reg);
offset = reg_offset(reg);
name = "filter/route hash flush";
if (!ipa_cmd_register_write_offset_valid(ipa, name, offset))
return false;
Expand All @@ -314,7 +314,7 @@ static bool ipa_cmd_register_write_valid(struct ipa *ipa)
* fits in the register write command field(s) that must hold it.
*/
reg = ipa_reg(ipa, ENDP_STATUS);
offset = ipa_reg_n_offset(reg, IPA_ENDPOINT_COUNT - 1);
offset = reg_n_offset(reg, IPA_ENDPOINT_COUNT - 1);
name = "maximal endpoint status";
if (!ipa_cmd_register_write_offset_valid(ipa, name, offset))
return false;
Expand Down
Loading

0 comments on commit 01a7ee3

Please sign in to comment.