Commit 79c9cc3c authored by David S. Miller's avatar David S. Miller

Merge branch 'xgene-next'

Iyappan Subramanian says:

====================
drivers: net: xgene: Add ethernet with ring manager v2 support

Adding XFI based 10GbE and SGMII based 1GbE with ring manager v2 support
for APM X-Gene ethernet driver.  The ring manager v2 is used by 2nd
generation SoC.

v1:
* Initial version
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents f828ad0c 561fea6d
...@@ -3,5 +3,5 @@ ...@@ -3,5 +3,5 @@
# #
xgene-enet-objs := xgene_enet_hw.o xgene_enet_sgmac.o xgene_enet_xgmac.o \ xgene-enet-objs := xgene_enet_hw.o xgene_enet_sgmac.o xgene_enet_xgmac.o \
xgene_enet_main.o xgene_enet_ethtool.o xgene_enet_main.o xgene_enet_ring2.o xgene_enet_ethtool.o
obj-$(CONFIG_NET_XGENE) += xgene-enet.o obj-$(CONFIG_NET_XGENE) += xgene-enet.o
...@@ -87,10 +87,11 @@ static void xgene_enet_ring_rd32(struct xgene_enet_desc_ring *ring, ...@@ -87,10 +87,11 @@ static void xgene_enet_ring_rd32(struct xgene_enet_desc_ring *ring,
static void xgene_enet_write_ring_state(struct xgene_enet_desc_ring *ring) static void xgene_enet_write_ring_state(struct xgene_enet_desc_ring *ring)
{ {
struct xgene_enet_pdata *pdata = netdev_priv(ring->ndev);
int i; int i;
xgene_enet_ring_wr32(ring, CSR_RING_CONFIG, ring->num); xgene_enet_ring_wr32(ring, CSR_RING_CONFIG, ring->num);
for (i = 0; i < NUM_RING_CONFIG; i++) { for (i = 0; i < pdata->ring_ops->num_ring_config; i++) {
xgene_enet_ring_wr32(ring, CSR_RING_WR_BASE + (i * 4), xgene_enet_ring_wr32(ring, CSR_RING_WR_BASE + (i * 4),
ring->state[i]); ring->state[i]);
} }
...@@ -98,7 +99,7 @@ static void xgene_enet_write_ring_state(struct xgene_enet_desc_ring *ring) ...@@ -98,7 +99,7 @@ static void xgene_enet_write_ring_state(struct xgene_enet_desc_ring *ring)
static void xgene_enet_clr_ring_state(struct xgene_enet_desc_ring *ring) static void xgene_enet_clr_ring_state(struct xgene_enet_desc_ring *ring)
{ {
memset(ring->state, 0, sizeof(u32) * NUM_RING_CONFIG); memset(ring->state, 0, sizeof(ring->state));
xgene_enet_write_ring_state(ring); xgene_enet_write_ring_state(ring);
} }
...@@ -141,8 +142,8 @@ static void xgene_enet_clr_desc_ring_id(struct xgene_enet_desc_ring *ring) ...@@ -141,8 +142,8 @@ static void xgene_enet_clr_desc_ring_id(struct xgene_enet_desc_ring *ring)
xgene_enet_ring_wr32(ring, CSR_RING_ID_BUF, 0); xgene_enet_ring_wr32(ring, CSR_RING_ID_BUF, 0);
} }
struct xgene_enet_desc_ring *xgene_enet_setup_ring( static struct xgene_enet_desc_ring *xgene_enet_setup_ring(
struct xgene_enet_desc_ring *ring) struct xgene_enet_desc_ring *ring)
{ {
u32 size = ring->size; u32 size = ring->size;
u32 i, data; u32 i, data;
...@@ -168,7 +169,7 @@ struct xgene_enet_desc_ring *xgene_enet_setup_ring( ...@@ -168,7 +169,7 @@ struct xgene_enet_desc_ring *xgene_enet_setup_ring(
return ring; return ring;
} }
void xgene_enet_clear_ring(struct xgene_enet_desc_ring *ring) static void xgene_enet_clear_ring(struct xgene_enet_desc_ring *ring)
{ {
u32 data; u32 data;
bool is_bufpool; bool is_bufpool;
...@@ -186,6 +187,22 @@ void xgene_enet_clear_ring(struct xgene_enet_desc_ring *ring) ...@@ -186,6 +187,22 @@ void xgene_enet_clear_ring(struct xgene_enet_desc_ring *ring)
xgene_enet_clr_ring_state(ring); xgene_enet_clr_ring_state(ring);
} }
static void xgene_enet_wr_cmd(struct xgene_enet_desc_ring *ring, int count)
{
iowrite32(count, 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(NUMMSGSINQ, ring_state);
return num_msgs;
}
void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring, void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring,
struct xgene_enet_pdata *pdata, struct xgene_enet_pdata *pdata,
enum xgene_enet_err_code status) enum xgene_enet_err_code status)
...@@ -803,3 +820,12 @@ struct xgene_port_ops xgene_gport_ops = { ...@@ -803,3 +820,12 @@ struct xgene_port_ops xgene_gport_ops = {
.cle_bypass = xgene_enet_cle_bypass, .cle_bypass = xgene_enet_cle_bypass,
.shutdown = xgene_gport_shutdown, .shutdown = xgene_gport_shutdown,
}; };
struct xgene_ring_ops xgene_ring1_ops = {
.num_ring_config = NUM_RING_CONFIG,
.num_ring_id_shift = 6,
.setup = xgene_enet_setup_ring,
.clear = xgene_enet_clear_ring,
.wr_cmd = xgene_enet_wr_cmd,
.len = xgene_enet_ring_len,
};
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
struct xgene_enet_pdata; struct xgene_enet_pdata;
struct xgene_enet_stats; struct xgene_enet_stats;
struct xgene_enet_desc_ring;
/* clears and then set bits */ /* clears and then set bits */
static inline void xgene_set_bits(u32 *dst, u32 val, u32 start, u32 len) static inline void xgene_set_bits(u32 *dst, u32 val, u32 start, u32 len)
...@@ -101,8 +102,8 @@ enum xgene_enet_rm { ...@@ -101,8 +102,8 @@ enum xgene_enet_rm {
#define BLOCK_ETH_CSR_OFFSET 0x2000 #define BLOCK_ETH_CSR_OFFSET 0x2000
#define BLOCK_ETH_RING_IF_OFFSET 0x9000 #define BLOCK_ETH_RING_IF_OFFSET 0x9000
#define BLOCK_ETH_CLKRST_CSR_OFFSET 0xc000
#define BLOCK_ETH_DIAG_CSR_OFFSET 0xD000 #define BLOCK_ETH_DIAG_CSR_OFFSET 0xD000
#define BLOCK_ETH_MAC_OFFSET 0x0000 #define BLOCK_ETH_MAC_OFFSET 0x0000
#define BLOCK_ETH_MAC_CSR_OFFSET 0x2800 #define BLOCK_ETH_MAC_CSR_OFFSET 0x2800
...@@ -261,6 +262,7 @@ enum xgene_enet_ring_type { ...@@ -261,6 +262,7 @@ enum xgene_enet_ring_type {
enum xgene_ring_owner { enum xgene_ring_owner {
RING_OWNER_ETH0, RING_OWNER_ETH0,
RING_OWNER_ETH1,
RING_OWNER_CPU = 15, RING_OWNER_CPU = 15,
RING_OWNER_INVALID RING_OWNER_INVALID
}; };
...@@ -314,9 +316,6 @@ static inline u16 xgene_enet_get_numslots(u16 id, u32 size) ...@@ -314,9 +316,6 @@ static inline u16 xgene_enet_get_numslots(u16 id, u32 size)
size / WORK_DESC_SIZE; size / WORK_DESC_SIZE;
} }
struct xgene_enet_desc_ring *xgene_enet_setup_ring(
struct xgene_enet_desc_ring *ring);
void xgene_enet_clear_ring(struct xgene_enet_desc_ring *ring);
void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring, void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring,
struct xgene_enet_pdata *pdata, struct xgene_enet_pdata *pdata,
enum xgene_enet_err_code status); enum xgene_enet_err_code status);
...@@ -327,5 +326,6 @@ bool xgene_ring_mgr_init(struct xgene_enet_pdata *p); ...@@ -327,5 +326,6 @@ bool xgene_ring_mgr_init(struct xgene_enet_pdata *p);
extern struct xgene_mac_ops xgene_gmac_ops; extern struct xgene_mac_ops xgene_gmac_ops;
extern struct xgene_port_ops xgene_gport_ops; extern struct xgene_port_ops xgene_gport_ops;
extern struct xgene_ring_ops xgene_ring1_ops;
#endif /* __XGENE_ENET_HW_H__ */ #endif /* __XGENE_ENET_HW_H__ */
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include <linux/if_vlan.h> #include <linux/if_vlan.h>
#include <linux/phy.h> #include <linux/phy.h>
#include "xgene_enet_hw.h" #include "xgene_enet_hw.h"
#include "xgene_enet_ring2.h"
#define XGENE_DRV_VERSION "v1.0" #define XGENE_DRV_VERSION "v1.0"
#define XGENE_ENET_MAX_MTU 1536 #define XGENE_ENET_MAX_MTU 1536
...@@ -51,12 +52,26 @@ ...@@ -51,12 +52,26 @@
#define START_BP_BUFNUM_1 0x2A #define START_BP_BUFNUM_1 0x2A
#define START_RING_NUM_1 264 #define START_RING_NUM_1 264
#define X2_START_CPU_BUFNUM_0 0
#define X2_START_ETH_BUFNUM_0 0
#define X2_START_BP_BUFNUM_0 0x20
#define X2_START_RING_NUM_0 0
#define X2_START_CPU_BUFNUM_1 0xc
#define X2_START_ETH_BUFNUM_1 0
#define X2_START_BP_BUFNUM_1 0x20
#define X2_START_RING_NUM_1 256
#define IRQ_ID_SIZE 16 #define IRQ_ID_SIZE 16
#define XGENE_MAX_TXC_RINGS 1 #define XGENE_MAX_TXC_RINGS 1
#define PHY_POLL_LINK_ON (10 * HZ) #define PHY_POLL_LINK_ON (10 * HZ)
#define PHY_POLL_LINK_OFF (PHY_POLL_LINK_ON / 5) #define PHY_POLL_LINK_OFF (PHY_POLL_LINK_ON / 5)
enum xgene_enet_id {
XGENE_ENET1 = 1,
XGENE_ENET2
};
/* software context of a descriptor ring */ /* software context of a descriptor ring */
struct xgene_enet_desc_ring { struct xgene_enet_desc_ring {
struct net_device *ndev; struct net_device *ndev;
...@@ -72,6 +87,8 @@ struct xgene_enet_desc_ring { ...@@ -72,6 +87,8 @@ struct xgene_enet_desc_ring {
void __iomem *cmd_base; void __iomem *cmd_base;
void __iomem *cmd; void __iomem *cmd;
dma_addr_t dma; dma_addr_t dma;
dma_addr_t irq_mbox_dma;
void *irq_mbox_addr;
u16 dst_ring_num; u16 dst_ring_num;
u8 nbufpool; u8 nbufpool;
struct sk_buff *(*rx_skb); struct sk_buff *(*rx_skb);
...@@ -105,6 +122,15 @@ struct xgene_port_ops { ...@@ -105,6 +122,15 @@ struct xgene_port_ops {
void (*shutdown)(struct xgene_enet_pdata *pdata); void (*shutdown)(struct xgene_enet_pdata *pdata);
}; };
struct xgene_ring_ops {
u8 num_ring_config;
u8 num_ring_id_shift;
struct xgene_enet_desc_ring * (*setup)(struct xgene_enet_desc_ring *);
void (*clear)(struct xgene_enet_desc_ring *);
void (*wr_cmd)(struct xgene_enet_desc_ring *, int);
u32 (*len)(struct xgene_enet_desc_ring *);
};
/* ethernet private data */ /* ethernet private data */
struct xgene_enet_pdata { struct xgene_enet_pdata {
struct net_device *ndev; struct net_device *ndev;
...@@ -113,6 +139,7 @@ struct xgene_enet_pdata { ...@@ -113,6 +139,7 @@ struct xgene_enet_pdata {
int phy_speed; int phy_speed;
struct clk *clk; struct clk *clk;
struct platform_device *pdev; struct platform_device *pdev;
enum xgene_enet_id enet_id;
struct xgene_enet_desc_ring *tx_ring; struct xgene_enet_desc_ring *tx_ring;
struct xgene_enet_desc_ring *rx_ring; struct xgene_enet_desc_ring *rx_ring;
char *dev_name; char *dev_name;
...@@ -136,6 +163,7 @@ struct xgene_enet_pdata { ...@@ -136,6 +163,7 @@ struct xgene_enet_pdata {
struct rtnl_link_stats64 stats; struct rtnl_link_stats64 stats;
struct xgene_mac_ops *mac_ops; struct xgene_mac_ops *mac_ops;
struct xgene_port_ops *port_ops; struct xgene_port_ops *port_ops;
struct xgene_ring_ops *ring_ops;
struct delayed_work link_work; struct delayed_work link_work;
u32 port_id; u32 port_id;
u8 cpu_bufnum; u8 cpu_bufnum;
......
/* Applied Micro X-Gene SoC Ethernet Driver
*
* Copyright (c) 2015, Applied Micro Circuits Corporation
* Author: Iyappan Subramanian <isubramanian@apm.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#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, 1);
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;
}
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,
};
/* Applied Micro X-Gene SoC Ethernet Driver
*
* Copyright (c) 2015, Applied Micro Circuits Corporation
* Author: Iyappan Subramanian <isubramanian@apm.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __XGENE_ENET_RING2_H__
#define __XGENE_ENET_RING2_H__
#include "xgene_enet_main.h"
#define X2_NUM_RING_CONFIG 6
#define INTR_MBOX_SIZE 1024
#define CSR_VMID0_INTR_MBOX 0x0270
#define INTR_CLEAR BIT(23)
#define X2_MSG_AM_POS 10
#define X2_QBASE_AM_POS 11
#define X2_INTLINE_POS 24
#define X2_INTLINE_LEN 5
#define X2_CFGCRID_POS 29
#define X2_CFGCRID_LEN 3
#define X2_SELTHRSH_POS 7
#define X2_SELTHRSH_LEN 3
#define X2_RINGTYPE_POS 23
#define X2_RINGTYPE_LEN 2
#define X2_DEQINTEN_POS 29
#define X2_RECOMTIMEOUT_POS 0
#define X2_RECOMTIMEOUT_LEN 7
#define X2_NUMMSGSINQ_POS 0
#define X2_NUMMSGSINQ_LEN 17
extern struct xgene_ring_ops xgene_ring2_ops;
#endif /* __XGENE_ENET_RING2_H__ */
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "xgene_enet_main.h" #include "xgene_enet_main.h"
#include "xgene_enet_hw.h" #include "xgene_enet_hw.h"
#include "xgene_enet_sgmac.h" #include "xgene_enet_sgmac.h"
#include "xgene_enet_xgmac.h"
static void xgene_enet_wr_csr(struct xgene_enet_pdata *p, u32 offset, u32 val) static void xgene_enet_wr_csr(struct xgene_enet_pdata *p, u32 offset, u32 val)
{ {
...@@ -39,6 +40,14 @@ static void xgene_enet_wr_diag_csr(struct xgene_enet_pdata *p, ...@@ -39,6 +40,14 @@ static void xgene_enet_wr_diag_csr(struct xgene_enet_pdata *p,
iowrite32(val, p->eth_diag_csr_addr + offset); iowrite32(val, p->eth_diag_csr_addr + offset);
} }
static void xgene_enet_wr_mcx_csr(struct xgene_enet_pdata *pdata,
u32 offset, u32 val)
{
void __iomem *addr = pdata->mcx_mac_csr_addr + offset;
iowrite32(val, addr);
}
static bool xgene_enet_wr_indirect(struct xgene_indirect_ctl *ctl, static bool xgene_enet_wr_indirect(struct xgene_indirect_ctl *ctl,
u32 wr_addr, u32 wr_data) u32 wr_addr, u32 wr_data)
{ {
...@@ -140,8 +149,9 @@ static int xgene_enet_ecc_init(struct xgene_enet_pdata *p) ...@@ -140,8 +149,9 @@ static int xgene_enet_ecc_init(struct xgene_enet_pdata *p)
static void xgene_enet_config_ring_if_assoc(struct xgene_enet_pdata *p) static void xgene_enet_config_ring_if_assoc(struct xgene_enet_pdata *p)
{ {
u32 val = 0xffffffff; u32 val;
val = (p->enet_id == XGENE_ENET1) ? 0xffffffff : 0;
xgene_enet_wr_ring_if(p, ENET_CFGSSQMIWQASSOC_ADDR, val); xgene_enet_wr_ring_if(p, ENET_CFGSSQMIWQASSOC_ADDR, val);
xgene_enet_wr_ring_if(p, ENET_CFGSSQMIFPQASSOC_ADDR, val); xgene_enet_wr_ring_if(p, ENET_CFGSSQMIFPQASSOC_ADDR, val);
} }
...@@ -227,6 +237,8 @@ static void xgene_sgmac_init(struct xgene_enet_pdata *p) ...@@ -227,6 +237,8 @@ static void xgene_sgmac_init(struct xgene_enet_pdata *p)
{ {
u32 data, loop = 10; u32 data, loop = 10;
u32 offset = p->port_id * 4; u32 offset = p->port_id * 4;
u32 enet_spare_cfg_reg, rsif_config_reg;
u32 cfg_bypass_reg, rx_dv_gate_reg;
xgene_sgmac_reset(p); xgene_sgmac_reset(p);
...@@ -239,7 +251,7 @@ static void xgene_sgmac_init(struct xgene_enet_pdata *p) ...@@ -239,7 +251,7 @@ static void xgene_sgmac_init(struct xgene_enet_pdata *p)
SGMII_STATUS_ADDR >> 2); SGMII_STATUS_ADDR >> 2);
if ((data & AUTO_NEG_COMPLETE) && (data & LINK_STATUS)) if ((data & AUTO_NEG_COMPLETE) && (data & LINK_STATUS))
break; break;
usleep_range(10, 20); usleep_range(1000, 2000);
} }
if (!(data & AUTO_NEG_COMPLETE) || !(data & LINK_STATUS)) if (!(data & AUTO_NEG_COMPLETE) || !(data & LINK_STATUS))
netdev_err(p->ndev, "Auto-negotiation failed\n"); netdev_err(p->ndev, "Auto-negotiation failed\n");
...@@ -249,33 +261,38 @@ static void xgene_sgmac_init(struct xgene_enet_pdata *p) ...@@ -249,33 +261,38 @@ static void xgene_sgmac_init(struct xgene_enet_pdata *p)
xgene_enet_wr_mac(p, MAC_CONFIG_2_ADDR, data | FULL_DUPLEX2); xgene_enet_wr_mac(p, MAC_CONFIG_2_ADDR, data | FULL_DUPLEX2);
xgene_enet_wr_mac(p, INTERFACE_CONTROL_ADDR, ENET_GHD_MODE); xgene_enet_wr_mac(p, INTERFACE_CONTROL_ADDR, ENET_GHD_MODE);
data = xgene_enet_rd_csr(p, ENET_SPARE_CFG_REG_ADDR); if (p->enet_id == XGENE_ENET1) {
enet_spare_cfg_reg = ENET_SPARE_CFG_REG_ADDR;
rsif_config_reg = RSIF_CONFIG_REG_ADDR;
cfg_bypass_reg = CFG_BYPASS_ADDR;
rx_dv_gate_reg = SG_RX_DV_GATE_REG_0_ADDR;
} else {
enet_spare_cfg_reg = XG_ENET_SPARE_CFG_REG_ADDR;
rsif_config_reg = XG_RSIF_CONFIG_REG_ADDR;
cfg_bypass_reg = XG_CFG_BYPASS_ADDR;
rx_dv_gate_reg = XG_MCX_RX_DV_GATE_REG_0_ADDR;
}
data = xgene_enet_rd_csr(p, enet_spare_cfg_reg);
data |= MPA_IDLE_WITH_QMI_EMPTY; data |= MPA_IDLE_WITH_QMI_EMPTY;
xgene_enet_wr_csr(p, ENET_SPARE_CFG_REG_ADDR, data); xgene_enet_wr_csr(p, enet_spare_cfg_reg, data);
xgene_sgmac_set_mac_addr(p); xgene_sgmac_set_mac_addr(p);
data = xgene_enet_rd_csr(p, DEBUG_REG_ADDR);
data |= CFG_BYPASS_UNISEC_TX | CFG_BYPASS_UNISEC_RX;
xgene_enet_wr_csr(p, DEBUG_REG_ADDR, data);
/* Adjust MDC clock frequency */ /* Adjust MDC clock frequency */
data = xgene_enet_rd_mac(p, MII_MGMT_CONFIG_ADDR); data = xgene_enet_rd_mac(p, MII_MGMT_CONFIG_ADDR);
MGMT_CLOCK_SEL_SET(&data, 7); MGMT_CLOCK_SEL_SET(&data, 7);
xgene_enet_wr_mac(p, MII_MGMT_CONFIG_ADDR, data); xgene_enet_wr_mac(p, MII_MGMT_CONFIG_ADDR, data);
/* Enable drop if bufpool not available */ /* Enable drop if bufpool not available */
data = xgene_enet_rd_csr(p, RSIF_CONFIG_REG_ADDR); data = xgene_enet_rd_csr(p, rsif_config_reg);
data |= CFG_RSIF_FPBUFF_TIMEOUT_EN; data |= CFG_RSIF_FPBUFF_TIMEOUT_EN;
xgene_enet_wr_csr(p, RSIF_CONFIG_REG_ADDR, data); xgene_enet_wr_csr(p, rsif_config_reg, data);
/* Rtype should be copied from FP */
xgene_enet_wr_csr(p, RSIF_RAM_DBG_REG0_ADDR, 0);
/* Bypass traffic gating */ /* Bypass traffic gating */
xgene_enet_wr_csr(p, CFG_LINK_AGGR_RESUME_0_ADDR + offset, TX_PORT0); xgene_enet_wr_csr(p, XG_ENET_SPARE_CFG_REG_1_ADDR, 0x84);
xgene_enet_wr_csr(p, CFG_BYPASS_ADDR, RESUME_TX); xgene_enet_wr_csr(p, cfg_bypass_reg, RESUME_TX);
xgene_enet_wr_csr(p, SG_RX_DV_GATE_REG_0_ADDR + offset, RESUME_RX0); xgene_enet_wr_mcx_csr(p, rx_dv_gate_reg + offset, RESUME_RX0);
} }
static void xgene_sgmac_rxtx(struct xgene_enet_pdata *p, u32 bits, bool set) static void xgene_sgmac_rxtx(struct xgene_enet_pdata *p, u32 bits, bool set)
...@@ -331,14 +348,23 @@ static void xgene_enet_cle_bypass(struct xgene_enet_pdata *p, ...@@ -331,14 +348,23 @@ static void xgene_enet_cle_bypass(struct xgene_enet_pdata *p,
u32 dst_ring_num, u16 bufpool_id) u32 dst_ring_num, u16 bufpool_id)
{ {
u32 data, fpsel; u32 data, fpsel;
u32 cle_bypass_reg0, cle_bypass_reg1;
u32 offset = p->port_id * MAC_OFFSET; u32 offset = p->port_id * MAC_OFFSET;
if (p->enet_id == XGENE_ENET1) {
cle_bypass_reg0 = CLE_BYPASS_REG0_0_ADDR;
cle_bypass_reg1 = CLE_BYPASS_REG1_0_ADDR;
} else {
cle_bypass_reg0 = XCLE_BYPASS_REG0_ADDR;
cle_bypass_reg1 = XCLE_BYPASS_REG1_ADDR;
}
data = CFG_CLE_BYPASS_EN0; data = CFG_CLE_BYPASS_EN0;
xgene_enet_wr_csr(p, CLE_BYPASS_REG0_0_ADDR + offset, data); xgene_enet_wr_csr(p, cle_bypass_reg0 + offset, data);
fpsel = xgene_enet_ring_bufnum(bufpool_id) - 0x20; fpsel = xgene_enet_ring_bufnum(bufpool_id) - 0x20;
data = CFG_CLE_DSTQID0(dst_ring_num) | CFG_CLE_FPSEL0(fpsel); data = CFG_CLE_DSTQID0(dst_ring_num) | CFG_CLE_FPSEL0(fpsel);
xgene_enet_wr_csr(p, CLE_BYPASS_REG1_0_ADDR + offset, data); xgene_enet_wr_csr(p, cle_bypass_reg1 + offset, data);
} }
static void xgene_enet_shutdown(struct xgene_enet_pdata *p) static void xgene_enet_shutdown(struct xgene_enet_pdata *p)
......
...@@ -122,7 +122,6 @@ static bool xgene_enet_rd_indirect(void __iomem *addr, void __iomem *rd, ...@@ -122,7 +122,6 @@ static bool xgene_enet_rd_indirect(void __iomem *addr, void __iomem *rd,
return true; return true;
} }
static void xgene_enet_rd_mac(struct xgene_enet_pdata *pdata, static void xgene_enet_rd_mac(struct xgene_enet_pdata *pdata,
u32 rd_addr, u32 *rd_data) u32 rd_addr, u32 *rd_data)
{ {
......
...@@ -21,9 +21,28 @@ ...@@ -21,9 +21,28 @@
#ifndef __XGENE_ENET_XGMAC_H__ #ifndef __XGENE_ENET_XGMAC_H__
#define __XGENE_ENET_XGMAC_H__ #define __XGENE_ENET_XGMAC_H__
#define X2_BLOCK_ETH_MAC_CSR_OFFSET 0x3000
#define BLOCK_AXG_MAC_OFFSET 0x0800 #define BLOCK_AXG_MAC_OFFSET 0x0800
#define BLOCK_AXG_MAC_CSR_OFFSET 0x2000 #define BLOCK_AXG_MAC_CSR_OFFSET 0x2000
#define XGENET_CONFIG_REG_ADDR 0x20
#define XGENET_SRST_ADDR 0x00
#define XGENET_CLKEN_ADDR 0x08
#define CSR_CLK BIT(0)
#define XGENET_CLK BIT(1)
#define PCS_CLK BIT(3)
#define AN_REF_CLK BIT(4)
#define AN_CLK BIT(5)
#define AD_CLK BIT(6)
#define CSR_RST BIT(0)
#define XGENET_RST BIT(1)
#define PCS_RST BIT(3)
#define AN_REF_RST BIT(4)
#define AN_RST BIT(5)
#define AD_RST BIT(6)
#define AXGMAC_CONFIG_0 0x0000 #define AXGMAC_CONFIG_0 0x0000
#define AXGMAC_CONFIG_1 0x0004 #define AXGMAC_CONFIG_1 0x0004
#define HSTMACRST BIT(31) #define HSTMACRST BIT(31)
...@@ -38,6 +57,7 @@ ...@@ -38,6 +57,7 @@
#define HSTMACADR_MSW_ADDR 0x0014 #define HSTMACADR_MSW_ADDR 0x0014
#define HSTMAXFRAME_LENGTH_ADDR 0x0020 #define HSTMAXFRAME_LENGTH_ADDR 0x0020
#define XG_MCX_RX_DV_GATE_REG_0_ADDR 0x0004
#define XG_RSIF_CONFIG_REG_ADDR 0x00a0 #define XG_RSIF_CONFIG_REG_ADDR 0x00a0
#define XCLE_BYPASS_REG0_ADDR 0x0160 #define XCLE_BYPASS_REG0_ADDR 0x0160
#define XCLE_BYPASS_REG1_ADDR 0x0164 #define XCLE_BYPASS_REG1_ADDR 0x0164
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment