Skip to content

Commit

Permalink
net: ipa: define IPA v3.1 GSI event ring register offsets
Browse files Browse the repository at this point in the history
Add definitions of the offsets and strides for registers whose
offset depends on an event ring ID, and use gsi_reg() and its
returned value to determine offsets for these registers.  Get
rid of the corresponding GSI_EV_CH_E_*_OFFSET() macros.

Signed-off-by: Alex Elder <elder@linaro.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Alex Elder authored and David S. Miller committed Feb 13, 2023
1 parent 76924eb commit d1ce639
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 53 deletions.
45 changes: 32 additions & 13 deletions drivers/net/ipa/gsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -392,9 +392,10 @@ static bool gsi_command(struct gsi *gsi, u32 reg, u32 val)
static enum gsi_evt_ring_state
gsi_evt_ring_state(struct gsi *gsi, u32 evt_ring_id)
{
const struct reg *reg = gsi_reg(gsi, EV_CH_E_CNTXT_0);
u32 val;

val = ioread32(gsi->virt + GSI_EV_CH_E_CNTXT_0_OFFSET(evt_ring_id));
val = ioread32(gsi->virt + reg_n_offset(reg, evt_ring_id));

return u32_get_bits(val, EV_CHSTATE_FMASK);
}
Expand Down Expand Up @@ -690,56 +691,72 @@ static void gsi_channel_de_alloc_command(struct gsi *gsi, u32 channel_id)
*/
static void gsi_evt_ring_doorbell(struct gsi *gsi, u32 evt_ring_id, u32 index)
{
const struct reg *reg = gsi_reg(gsi, EV_CH_E_DOORBELL_0);
struct gsi_ring *ring = &gsi->evt_ring[evt_ring_id].ring;
u32 val;

ring->index = index; /* Next unused entry */

/* Note: index *must* be used modulo the ring count here */
val = gsi_ring_addr(ring, (index - 1) % ring->count);
iowrite32(val, gsi->virt + GSI_EV_CH_E_DOORBELL_0_OFFSET(evt_ring_id));
iowrite32(val, gsi->virt + reg_n_offset(reg, evt_ring_id));
}

/* Program an event ring for use */
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);
/* We program all event rings as GPI type/protocol */
val = u32_encode_bits(GSI_CHANNEL_TYPE_GPI, EV_CHTYPE_FMASK);
val |= EV_INTYPE_FMASK;
val |= u32_encode_bits(GSI_RING_ELEMENT_SIZE, EV_ELEMENT_SIZE_FMASK);
iowrite32(val, gsi->virt + GSI_EV_CH_E_CNTXT_0_OFFSET(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);
iowrite32(val, gsi->virt + GSI_EV_CH_E_CNTXT_1_OFFSET(evt_ring_id));
iowrite32(val, gsi->virt + reg_n_offset(reg, evt_ring_id));

/* The context 2 and 3 registers store the low-order and
* high-order 32 bits of the address of the event ring,
* respectively.
*/
reg = gsi_reg(gsi, EV_CH_E_CNTXT_2);
val = lower_32_bits(ring->addr);
iowrite32(val, gsi->virt + GSI_EV_CH_E_CNTXT_2_OFFSET(evt_ring_id));
iowrite32(val, gsi->virt + reg_n_offset(reg, evt_ring_id));

reg = gsi_reg(gsi, EV_CH_E_CNTXT_3);
val = upper_32_bits(ring->addr);
iowrite32(val, gsi->virt + GSI_EV_CH_E_CNTXT_3_OFFSET(evt_ring_id));
iowrite32(val, gsi->virt + reg_n_offset(reg, evt_ring_id));

/* Enable interrupt moderation by setting the moderation delay */
reg = gsi_reg(gsi, EV_CH_E_CNTXT_8);
val = u32_encode_bits(GSI_EVT_RING_INT_MODT, MODT_FMASK);
val |= u32_encode_bits(1, MODC_FMASK); /* comes from channel */
iowrite32(val, gsi->virt + GSI_EV_CH_E_CNTXT_8_OFFSET(evt_ring_id));
iowrite32(val, gsi->virt + reg_n_offset(reg, evt_ring_id));

/* No MSI write data, and MSI address high and low address is 0 */
iowrite32(0, gsi->virt + GSI_EV_CH_E_CNTXT_9_OFFSET(evt_ring_id));
iowrite32(0, gsi->virt + GSI_EV_CH_E_CNTXT_10_OFFSET(evt_ring_id));
iowrite32(0, gsi->virt + GSI_EV_CH_E_CNTXT_11_OFFSET(evt_ring_id));
reg = gsi_reg(gsi, EV_CH_E_CNTXT_9);
iowrite32(0, gsi->virt + reg_n_offset(reg, evt_ring_id));

reg = gsi_reg(gsi, EV_CH_E_CNTXT_10);
iowrite32(0, gsi->virt + reg_n_offset(reg, evt_ring_id));

reg = gsi_reg(gsi, EV_CH_E_CNTXT_11);
iowrite32(0, gsi->virt + reg_n_offset(reg, evt_ring_id));

/* We don't need to get event read pointer updates */
iowrite32(0, gsi->virt + GSI_EV_CH_E_CNTXT_12_OFFSET(evt_ring_id));
iowrite32(0, gsi->virt + GSI_EV_CH_E_CNTXT_13_OFFSET(evt_ring_id));
reg = gsi_reg(gsi, EV_CH_E_CNTXT_12);
iowrite32(0, gsi->virt + reg_n_offset(reg, evt_ring_id));

reg = gsi_reg(gsi, EV_CH_E_CNTXT_13);
iowrite32(0, gsi->virt + reg_n_offset(reg, evt_ring_id));

/* Finally, tell the hardware our "last processed" event (arbitrary) */
gsi_evt_ring_doorbell(gsi, evt_ring_id, ring->index);
Expand Down Expand Up @@ -1538,6 +1555,7 @@ void gsi_channel_update(struct gsi_channel *channel)
struct gsi_evt_ring *evt_ring;
struct gsi_trans *trans;
struct gsi_ring *ring;
const struct reg *reg;
u32 offset;
u32 index;

Expand All @@ -1547,7 +1565,8 @@ void gsi_channel_update(struct gsi_channel *channel)
/* See if there's anything new to process; if not, we're done. Note
* that index always refers to an entry *within* the event ring.
*/
offset = GSI_EV_CH_E_CNTXT_4_OFFSET(evt_ring_id);
reg = gsi_reg(gsi, EV_CH_E_CNTXT_4);
offset = reg_n_offset(reg, evt_ring_id);
index = gsi_ring_index(ring, ioread32(gsi->virt + offset));
if (index == ring->index % ring->count)
return;
Expand Down
42 changes: 2 additions & 40 deletions drivers/net/ipa/gsi_reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,7 @@ enum gsi_prefetch_mode {
GSI_FREE_PREFETCH = 0x3,
};

#define GSI_EV_CH_E_CNTXT_0_OFFSET(ev) \
(0x0001d000 + 0x4000 * GSI_EE_AP + 0x80 * (ev))
/* EV_CH_E_CNTXT_0 register */
/* enum gsi_channel_type defines EV_CHTYPE field values in EV_CH_E_CNTXT_0 */
#define EV_CHTYPE_FMASK GENMASK(3, 0)
#define EV_EE_FMASK GENMASK(7, 4)
Expand All @@ -160,48 +159,11 @@ enum gsi_prefetch_mode {
#define EV_CHSTATE_FMASK GENMASK(23, 20)
#define EV_ELEMENT_SIZE_FMASK GENMASK(31, 24)

#define GSI_EV_CH_E_CNTXT_1_OFFSET(ev) \
(0x0001d004 + 0x4000 * GSI_EE_AP + 0x80 * (ev))

#define GSI_EV_CH_E_CNTXT_2_OFFSET(ev) \
(0x0001d008 + 0x4000 * GSI_EE_AP + 0x80 * (ev))

#define GSI_EV_CH_E_CNTXT_3_OFFSET(ev) \
(0x0001d00c + 0x4000 * GSI_EE_AP + 0x80 * (ev))

#define GSI_EV_CH_E_CNTXT_4_OFFSET(ev) \
(0x0001d010 + 0x4000 * GSI_EE_AP + 0x80 * (ev))

#define GSI_EV_CH_E_CNTXT_8_OFFSET(ev) \
(0x0001d020 + 0x4000 * GSI_EE_AP + 0x80 * (ev))
/* EV_CH_E_CNTXT_8 register */
#define MODT_FMASK GENMASK(15, 0)
#define MODC_FMASK GENMASK(23, 16)
#define MOD_CNT_FMASK GENMASK(31, 24)

#define GSI_EV_CH_E_CNTXT_9_OFFSET(ev) \
(0x0001d024 + 0x4000 * GSI_EE_AP + 0x80 * (ev))

#define GSI_EV_CH_E_CNTXT_10_OFFSET(ev) \
(0x0001d028 + 0x4000 * GSI_EE_AP + 0x80 * (ev))

#define GSI_EV_CH_E_CNTXT_11_OFFSET(ev) \
(0x0001d02c + 0x4000 * GSI_EE_AP + 0x80 * (ev))

#define GSI_EV_CH_E_CNTXT_12_OFFSET(ev) \
(0x0001d030 + 0x4000 * GSI_EE_AP + 0x80 * (ev))

#define GSI_EV_CH_E_CNTXT_13_OFFSET(ev) \
(0x0001d034 + 0x4000 * GSI_EE_AP + 0x80 * (ev))

#define GSI_EV_CH_E_SCRATCH_0_OFFSET(ev) \
(0x0001d048 + 0x4000 * GSI_EE_AP + 0x80 * (ev))

#define GSI_EV_CH_E_SCRATCH_1_OFFSET(ev) \
(0x0001d04c + 0x4000 * GSI_EE_AP + 0x80 * (ev))

#define GSI_EV_CH_E_DOORBELL_0_OFFSET(ev) \
(0x0001e100 + 0x4000 * GSI_EE_AP + 0x08 * (ev))

#define GSI_GSI_STATUS_OFFSET \
(0x0001f000 + 0x4000 * GSI_EE_AP)
#define ENABLED_FMASK GENMASK(0, 0)
Expand Down
56 changes: 56 additions & 0 deletions drivers/net/ipa/reg/gsi_reg-v3.1.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,51 @@ REG_STRIDE(CH_C_SCRATCH_2, ch_c_scratch_2,
REG_STRIDE(CH_C_SCRATCH_3, ch_c_scratch_3,
0x0001c06c + 0x4000 * GSI_EE_AP, 0x80);

REG_STRIDE(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);

REG_STRIDE(EV_CH_E_CNTXT_2, ev_ch_e_cntxt_2,
0x0001d008 + 0x4000 * GSI_EE_AP, 0x80);

REG_STRIDE(EV_CH_E_CNTXT_3, ev_ch_e_cntxt_3,
0x0001d00c + 0x4000 * GSI_EE_AP, 0x80);

REG_STRIDE(EV_CH_E_CNTXT_4, ev_ch_e_cntxt_4,
0x0001d010 + 0x4000 * GSI_EE_AP, 0x80);

REG_STRIDE(EV_CH_E_CNTXT_8, ev_ch_e_cntxt_8,
0x0001d020 + 0x4000 * GSI_EE_AP, 0x80);

REG_STRIDE(EV_CH_E_CNTXT_9, ev_ch_e_cntxt_9,
0x0001d024 + 0x4000 * GSI_EE_AP, 0x80);

REG_STRIDE(EV_CH_E_CNTXT_10, ev_ch_e_cntxt_10,
0x0001d028 + 0x4000 * GSI_EE_AP, 0x80);

REG_STRIDE(EV_CH_E_CNTXT_11, ev_ch_e_cntxt_11,
0x0001d02c + 0x4000 * GSI_EE_AP, 0x80);

REG_STRIDE(EV_CH_E_CNTXT_12, ev_ch_e_cntxt_12,
0x0001d030 + 0x4000 * GSI_EE_AP, 0x80);

REG_STRIDE(EV_CH_E_CNTXT_13, ev_ch_e_cntxt_13,
0x0001d034 + 0x4000 * GSI_EE_AP, 0x80);

REG_STRIDE(EV_CH_E_SCRATCH_0, ev_ch_e_scratch_0,
0x0001d048 + 0x4000 * GSI_EE_AP, 0x80);

REG_STRIDE(EV_CH_E_SCRATCH_1, ev_ch_e_scratch_1,
0x0001d04c + 0x4000 * GSI_EE_AP, 0x80);

REG_STRIDE(CH_C_DOORBELL_0, ch_c_doorbell_0,
0x0001e000 + 0x4000 * GSI_EE_AP, 0x08);

REG_STRIDE(EV_CH_E_DOORBELL_0, ev_ch_e_doorbell_0,
0x0001e100 + 0x4000 * GSI_EE_AP, 0x08);

static const struct reg *reg_array[] = {
[CH_C_CNTXT_0] = &reg_ch_c_cntxt_0,
[CH_C_CNTXT_1] = &reg_ch_c_cntxt_1,
Expand All @@ -43,7 +85,21 @@ static const struct reg *reg_array[] = {
[CH_C_SCRATCH_1] = &reg_ch_c_scratch_1,
[CH_C_SCRATCH_2] = &reg_ch_c_scratch_2,
[CH_C_SCRATCH_3] = &reg_ch_c_scratch_3,
[EV_CH_E_CNTXT_0] = &reg_ev_ch_e_cntxt_0,
[EV_CH_E_CNTXT_1] = &reg_ev_ch_e_cntxt_1,
[EV_CH_E_CNTXT_2] = &reg_ev_ch_e_cntxt_2,
[EV_CH_E_CNTXT_3] = &reg_ev_ch_e_cntxt_3,
[EV_CH_E_CNTXT_4] = &reg_ev_ch_e_cntxt_4,
[EV_CH_E_CNTXT_8] = &reg_ev_ch_e_cntxt_8,
[EV_CH_E_CNTXT_9] = &reg_ev_ch_e_cntxt_9,
[EV_CH_E_CNTXT_10] = &reg_ev_ch_e_cntxt_10,
[EV_CH_E_CNTXT_11] = &reg_ev_ch_e_cntxt_11,
[EV_CH_E_CNTXT_12] = &reg_ev_ch_e_cntxt_12,
[EV_CH_E_CNTXT_13] = &reg_ev_ch_e_cntxt_13,
[EV_CH_E_SCRATCH_0] = &reg_ev_ch_e_scratch_0,
[EV_CH_E_SCRATCH_1] = &reg_ev_ch_e_scratch_1,
[CH_C_DOORBELL_0] = &reg_ch_c_doorbell_0,
[EV_CH_E_DOORBELL_0] = &reg_ev_ch_e_doorbell_0,
};

const struct regs gsi_regs_v3_1 = {
Expand Down

0 comments on commit d1ce639

Please sign in to comment.