Skip to content

Commit

Permalink
Merge branch 'net-final-gsi-register-updates'
Browse files Browse the repository at this point in the history
Alex Elder says:

====================
net: final GSI register updates

I believe this is the last set of changes required to allow IPA v5.0
to be supported.  There is a little cleanup work remaining, but that
can happen in the next Linux release cycle.  Otherwise we just need
config data and register definitions for IPA v5.0 (and DTS updates).
These are ready but won't be posted without further testing.

The first patch in this series fixes a minor bug in a patch just
posted, which I found too late.  The second eliminates the GSI
memory "adjustment"; this was done previously to avoid/delay the
need to implement a more general way to define GSI register offsets.
Note that this patch causes "checkpatch" warnings due to indentation
that aligns with an open parenthesis.

The third patch makes use of the newly-defined register offsets, to
eliminate the need for a function that hid a few details.  The next
modifies a different helper function to work properly for IPA v5.0+.
The fifth patch changes the way the event ring size is specified
based on how it's now done for IPA v5.0+.  And the last defines a
new register required for IPA v5.0+.
====================

Link: https://lore.kernel.org/r/20230215195352.755744-1-elder@linaro.org
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
  • Loading branch information
Paolo Abeni committed Feb 20, 2023
2 parents 1c93e48 + f651334 commit d269ac1
Show file tree
Hide file tree
Showing 10 changed files with 205 additions and 212 deletions.
36 changes: 15 additions & 21 deletions drivers/net/ipa/gsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -185,25 +185,14 @@ static u32 ch_c_cntxt_0_type_encode(enum ipa_version version,
u32 val;

val = reg_encode(reg, CHTYPE_PROTOCOL, type);
if (version < IPA_VERSION_4_5)
if (version < IPA_VERSION_4_5 || version >= IPA_VERSION_5_0)
return val;

type >>= hweight32(reg_fmask(reg, CHTYPE_PROTOCOL));

return val | reg_encode(reg, CHTYPE_PROTOCOL_MSB, type);
}

/* 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 Down Expand Up @@ -731,7 +720,6 @@ static void gsi_evt_ring_program(struct gsi *gsi, u32 evt_ring_id)
struct gsi_evt_ring *evt_ring = &gsi->evt_ring[evt_ring_id];
struct gsi_ring *ring = &evt_ring->ring;
const struct reg *reg;
size_t size;
u32 val;

reg = gsi_reg(gsi, EV_CH_E_CNTXT_0);
Expand All @@ -743,8 +731,7 @@ static void gsi_evt_ring_program(struct gsi *gsi, u32 evt_ring_id)
iowrite32(val, gsi->virt + reg_n_offset(reg, evt_ring_id));

reg = gsi_reg(gsi, EV_CH_E_CNTXT_1);
size = ring->count * GSI_RING_ELEMENT_SIZE;
val = ev_ch_e_cntxt_1_length_encode(gsi->version, size);
val = reg_encode(reg, R_LENGTH, ring->count * GSI_RING_ELEMENT_SIZE);
iowrite32(val, gsi->virt + reg_n_offset(reg, evt_ring_id));

/* The context 2 and 3 registers store the low-order and
Expand All @@ -762,7 +749,7 @@ static void gsi_evt_ring_program(struct gsi *gsi, u32 evt_ring_id)
/* Enable interrupt moderation by setting the moderation delay */
reg = gsi_reg(gsi, EV_CH_E_CNTXT_8);
val = reg_encode(reg, EV_MODT, GSI_EVT_RING_INT_MODT);
val = reg_encode(reg, EV_MODC, 1); /* comes from channel */
val |= reg_encode(reg, EV_MODC, 1); /* comes from channel */
/* EV_MOD_CNT is 0 (no counter-based interrupt coalescing) */
iowrite32(val, gsi->virt + reg_n_offset(reg, evt_ring_id));

Expand Down Expand Up @@ -853,12 +840,15 @@ static void gsi_channel_program(struct gsi_channel *channel, bool doorbell)
val = ch_c_cntxt_0_type_encode(gsi->version, reg, GSI_CHANNEL_TYPE_GPI);
if (channel->toward_ipa)
val |= reg_bit(reg, CHTYPE_DIR);
val |= reg_encode(reg, ERINDEX, channel->evt_ring_id);
if (gsi->version < IPA_VERSION_5_0)
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 = reg_encode(reg, CH_R_LENGTH, size);
if (gsi->version >= IPA_VERSION_5_0)
val |= reg_encode(reg, CH_ERINDEX, channel->evt_ring_id);
iowrite32(val, gsi->virt + reg_n_offset(reg, channel_id));

/* The context 2 and 3 registers store the low-order and
Expand Down Expand Up @@ -1999,12 +1989,11 @@ static int gsi_irq_setup(struct gsi *gsi)

/* The inter-EE interrupts are not supported for IPA v3.0-v3.1 */
if (gsi->version > IPA_VERSION_3_1) {
/* These registers are in the non-adjusted address range */
reg = gsi_reg(gsi, INTER_EE_SRC_CH_IRQ_MSK);
iowrite32(0, gsi->virt_raw + reg_offset(reg));
iowrite32(0, gsi->virt + reg_offset(reg));

reg = gsi_reg(gsi, INTER_EE_SRC_EV_CH_IRQ_MSK);
iowrite32(0, gsi->virt_raw + reg_offset(reg));
iowrite32(0, gsi->virt + reg_offset(reg));
}

reg = gsi_reg(gsi, CNTXT_GSI_IRQ_EN);
Expand Down Expand Up @@ -2053,7 +2042,12 @@ static int gsi_ring_setup(struct gsi *gsi)
}
gsi->channel_count = count;

count = reg_decode(reg, NUM_EV_PER_EE, val);
if (gsi->version < IPA_VERSION_5_0) {
count = reg_decode(reg, NUM_EV_PER_EE, val);
} else {
reg = gsi_reg(gsi, HW_PARAM_4);
count = reg_decode(reg, EV_PER_EE, val);
}
if (!count) {
dev_err(dev, "GSI reports zero event rings supported\n");
return -EINVAL;
Expand Down
3 changes: 1 addition & 2 deletions drivers/net/ipa/gsi.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,7 @@ struct gsi_evt_ring {
struct gsi {
struct device *dev; /* Same as IPA device */
enum ipa_version version;
void __iomem *virt_raw; /* I/O mapped address range */
void __iomem *virt; /* Adjusted for most registers */
void __iomem *virt; /* I/O mapped registers */
const struct regs *regs;

u32 irq;
Expand Down
35 changes: 5 additions & 30 deletions drivers/net/ipa/gsi_reg.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,6 @@
#include "reg.h"
#include "gsi_reg.h"

/* GSI EE registers as a group are shifted downward by a fixed constant amount
* for IPA versions 4.5 and beyond. This applies to all GSI registers we use
* *except* the ones that disable inter-EE interrupts for channels and event
* channels.
*
* The "raw" (not adjusted) GSI register range is mapped, and a pointer to
* the mapped range is held in gsi->virt_raw. The inter-EE interrupt
* registers are accessed using that pointer.
*
* Most registers are accessed using gsi->virt, which is a copy of the "raw"
* pointer, adjusted downward by the fixed amount.
*/
#define GSI_EE_REG_ADJUST 0x0000d000 /* IPA v4.5+ */

/* Is this register ID valid for the current GSI version? */
static bool gsi_reg_id_valid(struct gsi *gsi, enum gsi_reg_id reg_id)
{
Expand Down Expand Up @@ -121,13 +107,12 @@ static const struct regs *gsi_regs(struct gsi *gsi)
}
}

/* Sets gsi->virt_raw and gsi->virt, and I/O maps the "gsi" memory range */
/* Sets gsi->virt and I/O maps the "gsi" memory range for registers */
int gsi_reg_init(struct gsi *gsi, struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct resource *res;
resource_size_t size;
u32 adjust;

/* Get GSI memory range and map it */
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "gsi");
Expand All @@ -142,35 +127,25 @@ int gsi_reg_init(struct gsi *gsi, struct platform_device *pdev)
return -EINVAL;
}

/* Make sure we can make our pointer adjustment if necessary */
adjust = gsi->version < IPA_VERSION_4_5 ? 0 : GSI_EE_REG_ADJUST;
if (res->start < adjust) {
dev_err(dev, "DT memory resource \"gsi\" too low (< %u)\n",
adjust);
return -EINVAL;
}

gsi->regs = gsi_regs(gsi);
if (!gsi->regs) {
dev_err(dev, "unsupported IPA version %u (?)\n", gsi->version);
return -EINVAL;
}

gsi->virt_raw = ioremap(res->start, size);
if (!gsi->virt_raw) {
gsi->virt = ioremap(res->start, size);
if (!gsi->virt) {
dev_err(dev, "unable to remap \"gsi\" memory\n");
return -ENOMEM;
}
/* Most registers are accessed using an adjusted register range */
gsi->virt = gsi->virt_raw - adjust;

return 0;
}

/* Inverse of gsi_reg_init() */
void gsi_reg_exit(struct gsi *gsi)
{
iounmap(gsi->virt);
gsi->virt = NULL;
iounmap(gsi->virt_raw);
gsi->virt_raw = NULL;
gsi->regs = NULL;
}
23 changes: 18 additions & 5 deletions drivers/net/ipa/gsi_reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ enum gsi_reg_id {
EV_CH_CMD,
GENERIC_CMD,
HW_PARAM_2, /* IPA v3.5.1+ */
HW_PARAM_4, /* IPA v5.0+ */
CNTXT_TYPE_IRQ,
CNTXT_TYPE_IRQ_MSK,
CNTXT_SRC_CH_IRQ,
Expand Down Expand Up @@ -101,8 +102,8 @@ enum gsi_reg_ch_c_cntxt_0_field_id {
CHTYPE_DIR,
CH_EE,
CHID,
CHTYPE_PROTOCOL_MSB, /* IPA v4.9+ */
ERINDEX,
CHTYPE_PROTOCOL_MSB, /* IPA v4.5-4.11 */
ERINDEX, /* Not IPA v5.0+ */
CHSTATE,
ELEMENT_SIZE,
};
Expand All @@ -124,6 +125,7 @@ enum gsi_channel_type {
/* CH_C_CNTXT_1 register */
enum gsi_reg_ch_c_cntxt_1_field_id {
CH_R_LENGTH,
CH_ERINDEX, /* IPA v5.0+ */
};

/* CH_C_QOS register */
Expand All @@ -135,6 +137,7 @@ enum gsi_reg_ch_c_qos_field_id {
PREFETCH_MODE, /* IPA v4.5+ */
EMPTY_LVL_THRSHOLD, /* IPA v4.5+ */
DB_IN_BYTES, /* IPA v4.9+ */
LOW_LATENCY_EN, /* IPA v5.0+ */
};

/** enum gsi_prefetch_mode - PREFETCH_MODE field in CH_C_QOS */
Expand All @@ -155,6 +158,11 @@ enum gsi_reg_ch_c_ev_ch_e_cntxt_0_field_id {
EV_ELEMENT_SIZE,
};

/* EV_CH_E_CNTXT_1 register */
enum gsi_reg_ev_ch_c_cntxt_1_field_id {
R_LENGTH,
};

/* EV_CH_E_CNTXT_8 register */
enum gsi_reg_ch_c_ev_ch_e_cntxt_8_field_id {
EV_MODT,
Expand Down Expand Up @@ -217,7 +225,7 @@ enum gsi_generic_cmd_opcode {
enum gsi_hw_param_2_field_id {
IRAM_SIZE,
NUM_CH_PER_EE,
NUM_EV_PER_EE,
NUM_EV_PER_EE, /* Not IPA v5.0+ */
GSI_CH_PEND_TRANSLATE,
GSI_CH_FULL_LOGIC,
GSI_USE_SDMA, /* IPA v4.0+ */
Expand All @@ -240,6 +248,12 @@ enum gsi_iram_size {
IRAM_SIZE_FOUR_KB = 0x5,
};

/* HW_PARAM_4 register */ /* IPA v5.0+ */
enum gsi_hw_param_4_field_id {
EV_PER_EE,
IRAM_PROTOCOL_COUNT,
};

/**
* enum gsi_irq_type_id: GSI IRQ types
* @GSI_CH_CTRL: Channel allocation, deallocation, etc.
Expand Down Expand Up @@ -351,8 +365,7 @@ const struct reg *gsi_reg(struct gsi *gsi, enum gsi_reg_id reg_id);
* @pdev: GSI (IPA) platform device
*
* Initialize GSI registers, including looking up and I/O mapping
* the "gsi" memory space. This function sets gsi->virt_raw and
* gsi->virt.
* the "gsi" memory space.
*/
int gsi_reg_init(struct gsi *gsi, struct platform_device *pdev);

Expand Down
22 changes: 12 additions & 10 deletions drivers/net/ipa/reg/gsi_reg-v3.1.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,12 @@
#include "../reg.h"
#include "../gsi_reg.h"

/* The inter-EE IRQ registers are relative to gsi->virt_raw (IPA v3.5+) */

REG(INTER_EE_SRC_CH_IRQ_MSK, inter_ee_src_ch_irq_msk,
0x0000c020 + 0x1000 * GSI_EE_AP);

REG(INTER_EE_SRC_EV_CH_IRQ_MSK, inter_ee_src_ev_ch_irq_msk,
0x0000c024 + 0x1000 * GSI_EE_AP);

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

static const u32 reg_ch_c_cntxt_0_fmask[] = {
[CHTYPE_PROTOCOL] = GENMASK(2, 0),
[CHTYPE_DIR] = BIT(3),
Expand Down Expand Up @@ -66,10 +62,6 @@ static const u32 reg_error_log_fmask[] = {
[ERR_EE] = GENMASK(31, 28),
};

REG_FIELDS(ERROR_LOG, error_log, 0x0001f200 + 0x4000 * GSI_EE_AP);

REG(ERROR_LOG_CLR, error_log_clr, 0x0001f210 + 0x4000 * GSI_EE_AP);

REG_STRIDE(CH_C_SCRATCH_0, ch_c_scratch_0,
0x0001c060 + 0x4000 * GSI_EE_AP, 0x80);

Expand All @@ -95,8 +87,12 @@ static const u32 reg_ev_ch_e_cntxt_0_fmask[] = {
REG_STRIDE_FIELDS(EV_CH_E_CNTXT_0, ev_ch_e_cntxt_0,
0x0001d000 + 0x4000 * GSI_EE_AP, 0x80);

REG_STRIDE(EV_CH_E_CNTXT_1, ev_ch_e_cntxt_1,
0x0001d004 + 0x4000 * GSI_EE_AP, 0x80);
static const u32 reg_ev_ch_e_cntxt_1_fmask[] = {
[R_LENGTH] = GENMASK(15, 0),
};

REG_STRIDE_FIELDS(EV_CH_E_CNTXT_1, ev_ch_e_cntxt_1,
0x0001d004 + 0x4000 * GSI_EE_AP, 0x80);

REG_STRIDE(EV_CH_E_CNTXT_2, ev_ch_e_cntxt_2,
0x0001d008 + 0x4000 * GSI_EE_AP, 0x80);
Expand Down Expand Up @@ -152,13 +148,15 @@ REG_FIELDS(GSI_STATUS, gsi_status, 0x0001f000 + 0x4000 * GSI_EE_AP);

static const u32 reg_ch_cmd_fmask[] = {
[CH_CHID] = GENMASK(7, 0),
/* Bits 8-23 reserved */
[CH_OPCODE] = GENMASK(31, 24),
};

REG_FIELDS(CH_CMD, ch_cmd, 0x0001f008 + 0x4000 * GSI_EE_AP);

static const u32 reg_ev_ch_cmd_fmask[] = {
[EV_CHID] = GENMASK(7, 0),
/* Bits 8-23 reserved */
[EV_OPCODE] = GENMASK(31, 24),
};

Expand Down Expand Up @@ -220,6 +218,10 @@ static const u32 reg_cntxt_intset_fmask[] = {

REG_FIELDS(CNTXT_INTSET, cntxt_intset, 0x0001f180 + 0x4000 * GSI_EE_AP);

REG_FIELDS(ERROR_LOG, error_log, 0x0001f200 + 0x4000 * GSI_EE_AP);

REG(ERROR_LOG_CLR, error_log_clr, 0x0001f210 + 0x4000 * GSI_EE_AP);

static const u32 reg_cntxt_scratch_0_fmask[] = {
[INTER_EE_RESULT] = GENMASK(2, 0),
/* Bits 3-4 reserved */
Expand Down
Loading

0 comments on commit d269ac1

Please sign in to comment.