forked from Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
203 lines
5.3 KiB
203 lines
5.3 KiB
// SPDX-License-Identifier: GPL-2.0-or-later |
|
/* Applied Micro X-Gene SoC Ethernet Driver |
|
* |
|
* Copyright (c) 2015, Applied Micro Circuits Corporation |
|
* Author: Iyappan Subramanian <[email protected]> |
|
*/ |
|
|
|
#include "xgene_enet_main.h" |
|
#include "xgene_enet_hw.h" |
|
#include "xgene_enet_ring2.h" |
|
|
|
static void xgene_enet_ring_init(struct xgene_enet_desc_ring *ring) |
|
{ |
|
u32 *ring_cfg = ring->state; |
|
u64 addr = ring->dma; |
|
|
|
if (xgene_enet_ring_owner(ring->id) == RING_OWNER_CPU) { |
|
ring_cfg[0] |= SET_VAL(X2_INTLINE, ring->id & RING_BUFNUM_MASK); |
|
ring_cfg[3] |= SET_BIT(X2_DEQINTEN); |
|
} |
|
ring_cfg[0] |= SET_VAL(X2_CFGCRID, 2); |
|
|
|
addr >>= 8; |
|
ring_cfg[2] |= QCOHERENT | SET_VAL(RINGADDRL, addr); |
|
|
|
addr >>= 27; |
|
ring_cfg[3] |= SET_VAL(RINGSIZE, ring->cfgsize) |
|
| ACCEPTLERR |
|
| SET_VAL(RINGADDRH, addr); |
|
ring_cfg[4] |= SET_VAL(X2_SELTHRSH, 1); |
|
ring_cfg[5] |= SET_BIT(X2_QBASE_AM) | SET_BIT(X2_MSG_AM); |
|
} |
|
|
|
static void xgene_enet_ring_set_type(struct xgene_enet_desc_ring *ring) |
|
{ |
|
u32 *ring_cfg = ring->state; |
|
bool is_bufpool; |
|
u32 val; |
|
|
|
is_bufpool = xgene_enet_is_bufpool(ring->id); |
|
val = (is_bufpool) ? RING_BUFPOOL : RING_REGULAR; |
|
ring_cfg[4] |= SET_VAL(X2_RINGTYPE, val); |
|
if (is_bufpool) |
|
ring_cfg[3] |= SET_VAL(RINGMODE, BUFPOOL_MODE); |
|
} |
|
|
|
static void xgene_enet_ring_set_recombbuf(struct xgene_enet_desc_ring *ring) |
|
{ |
|
u32 *ring_cfg = ring->state; |
|
|
|
ring_cfg[3] |= RECOMBBUF; |
|
ring_cfg[4] |= SET_VAL(X2_RECOMTIMEOUT, 0x7); |
|
} |
|
|
|
static void xgene_enet_ring_wr32(struct xgene_enet_desc_ring *ring, |
|
u32 offset, u32 data) |
|
{ |
|
struct xgene_enet_pdata *pdata = netdev_priv(ring->ndev); |
|
|
|
iowrite32(data, pdata->ring_csr_addr + offset); |
|
} |
|
|
|
static void xgene_enet_write_ring_state(struct xgene_enet_desc_ring *ring) |
|
{ |
|
struct xgene_enet_pdata *pdata = netdev_priv(ring->ndev); |
|
int i; |
|
|
|
xgene_enet_ring_wr32(ring, CSR_RING_CONFIG, ring->num); |
|
for (i = 0; i < pdata->ring_ops->num_ring_config; i++) { |
|
xgene_enet_ring_wr32(ring, CSR_RING_WR_BASE + (i * 4), |
|
ring->state[i]); |
|
} |
|
} |
|
|
|
static void xgene_enet_clr_ring_state(struct xgene_enet_desc_ring *ring) |
|
{ |
|
memset(ring->state, 0, sizeof(ring->state)); |
|
xgene_enet_write_ring_state(ring); |
|
} |
|
|
|
static void xgene_enet_set_ring_state(struct xgene_enet_desc_ring *ring) |
|
{ |
|
enum xgene_ring_owner owner; |
|
|
|
xgene_enet_ring_set_type(ring); |
|
|
|
owner = xgene_enet_ring_owner(ring->id); |
|
if (owner == RING_OWNER_ETH0 || owner == RING_OWNER_ETH1) |
|
xgene_enet_ring_set_recombbuf(ring); |
|
|
|
xgene_enet_ring_init(ring); |
|
xgene_enet_write_ring_state(ring); |
|
} |
|
|
|
static void xgene_enet_set_ring_id(struct xgene_enet_desc_ring *ring) |
|
{ |
|
u32 ring_id_val, ring_id_buf; |
|
bool is_bufpool; |
|
|
|
if (xgene_enet_ring_owner(ring->id) == RING_OWNER_CPU) |
|
return; |
|
|
|
is_bufpool = xgene_enet_is_bufpool(ring->id); |
|
|
|
ring_id_val = ring->id & GENMASK(9, 0); |
|
ring_id_val |= OVERWRITE; |
|
|
|
ring_id_buf = (ring->num << 9) & GENMASK(18, 9); |
|
ring_id_buf |= PREFETCH_BUF_EN; |
|
|
|
if (is_bufpool) |
|
ring_id_buf |= IS_BUFFER_POOL; |
|
|
|
xgene_enet_ring_wr32(ring, CSR_RING_ID, ring_id_val); |
|
xgene_enet_ring_wr32(ring, CSR_RING_ID_BUF, ring_id_buf); |
|
} |
|
|
|
static void xgene_enet_clr_desc_ring_id(struct xgene_enet_desc_ring *ring) |
|
{ |
|
u32 ring_id; |
|
|
|
ring_id = ring->id | OVERWRITE; |
|
xgene_enet_ring_wr32(ring, CSR_RING_ID, ring_id); |
|
xgene_enet_ring_wr32(ring, CSR_RING_ID_BUF, 0); |
|
} |
|
|
|
static struct xgene_enet_desc_ring *xgene_enet_setup_ring( |
|
struct xgene_enet_desc_ring *ring) |
|
{ |
|
bool is_bufpool; |
|
u32 addr, i; |
|
|
|
xgene_enet_clr_ring_state(ring); |
|
xgene_enet_set_ring_state(ring); |
|
xgene_enet_set_ring_id(ring); |
|
|
|
ring->slots = xgene_enet_get_numslots(ring->id, ring->size); |
|
|
|
is_bufpool = xgene_enet_is_bufpool(ring->id); |
|
if (is_bufpool || xgene_enet_ring_owner(ring->id) != RING_OWNER_CPU) |
|
return ring; |
|
|
|
addr = CSR_VMID0_INTR_MBOX + (4 * (ring->id & RING_BUFNUM_MASK)); |
|
xgene_enet_ring_wr32(ring, addr, ring->irq_mbox_dma >> 10); |
|
|
|
for (i = 0; i < ring->slots; i++) |
|
xgene_enet_mark_desc_slot_empty(&ring->raw_desc[i]); |
|
|
|
return ring; |
|
} |
|
|
|
static void xgene_enet_clear_ring(struct xgene_enet_desc_ring *ring) |
|
{ |
|
xgene_enet_clr_desc_ring_id(ring); |
|
xgene_enet_clr_ring_state(ring); |
|
} |
|
|
|
static void xgene_enet_wr_cmd(struct xgene_enet_desc_ring *ring, int count) |
|
{ |
|
u32 data = 0; |
|
|
|
if (xgene_enet_ring_owner(ring->id) == RING_OWNER_CPU) { |
|
data = SET_VAL(X2_INTLINE, ring->id & RING_BUFNUM_MASK) | |
|
INTR_CLEAR; |
|
} |
|
data |= (count & GENMASK(16, 0)); |
|
|
|
iowrite32(data, ring->cmd); |
|
} |
|
|
|
static u32 xgene_enet_ring_len(struct xgene_enet_desc_ring *ring) |
|
{ |
|
u32 __iomem *cmd_base = ring->cmd_base; |
|
u32 ring_state, num_msgs; |
|
|
|
ring_state = ioread32(&cmd_base[1]); |
|
num_msgs = GET_VAL(X2_NUMMSGSINQ, ring_state); |
|
|
|
return num_msgs; |
|
} |
|
|
|
static void xgene_enet_setup_coalescing(struct xgene_enet_desc_ring *ring) |
|
{ |
|
u32 data = 0x77777777; |
|
|
|
xgene_enet_ring_wr32(ring, CSR_PBM_COAL, 0x8e); |
|
xgene_enet_ring_wr32(ring, CSR_PBM_CTICK0, data); |
|
xgene_enet_ring_wr32(ring, CSR_PBM_CTICK1, data); |
|
xgene_enet_ring_wr32(ring, CSR_PBM_CTICK2, data); |
|
xgene_enet_ring_wr32(ring, CSR_PBM_CTICK3, data); |
|
xgene_enet_ring_wr32(ring, CSR_THRESHOLD0_SET1, 0x08); |
|
xgene_enet_ring_wr32(ring, CSR_THRESHOLD1_SET1, 0x10); |
|
} |
|
|
|
struct xgene_ring_ops xgene_ring2_ops = { |
|
.num_ring_config = X2_NUM_RING_CONFIG, |
|
.num_ring_id_shift = 13, |
|
.setup = xgene_enet_setup_ring, |
|
.clear = xgene_enet_clear_ring, |
|
.wr_cmd = xgene_enet_wr_cmd, |
|
.len = xgene_enet_ring_len, |
|
.coalesce = xgene_enet_setup_coalescing, |
|
};
|
|
|