Merge branch 'xgene-Add-ethtool-stats-and-bug-fixes'
Iyappan Subramanian says: ==================== drivers: net: xgene: Add ethtool stats and bug fixes This patch set, - adds ethtool extended statistics support - addresses errata workarounds - fixes bugs related to statistics v2: Address review comments from v1 - Adds lock to protect mdio-xgene indirect MAC access - Refactors xgene-enet indirect MAC read/write functions - Uses mdio-xgene MAC access routines, if xgene-enet port use the same HW. v1: - Initial version Signed-off-by: Iyappan Subramanian <isubramanian@apm.com> Signed-off-by: Quan Nguyen <qnguyen@apm.com> ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Коммит
9efa27bf92
|
@ -23,9 +23,17 @@
|
|||
struct xgene_gstrings_stats {
|
||||
char name[ETH_GSTRING_LEN];
|
||||
int offset;
|
||||
u32 addr;
|
||||
u32 mask;
|
||||
};
|
||||
|
||||
#define XGENE_STAT(m) { #m, offsetof(struct xgene_enet_pdata, stats.m) }
|
||||
#define XGENE_STAT(m) { #m, offsetof(struct rtnl_link_stats64, m) }
|
||||
#define XGENE_EXTD_STAT(s, a, m) \
|
||||
{ \
|
||||
.name = #s, \
|
||||
.addr = a ## _ADDR, \
|
||||
.mask = m \
|
||||
}
|
||||
|
||||
static const struct xgene_gstrings_stats gstrings_stats[] = {
|
||||
XGENE_STAT(rx_packets),
|
||||
|
@ -40,7 +48,65 @@ static const struct xgene_gstrings_stats gstrings_stats[] = {
|
|||
XGENE_STAT(rx_fifo_errors)
|
||||
};
|
||||
|
||||
static const struct xgene_gstrings_stats gstrings_extd_stats[] = {
|
||||
XGENE_EXTD_STAT(tx_rx_64b_frame_cntr, TR64, 31),
|
||||
XGENE_EXTD_STAT(tx_rx_127b_frame_cntr, TR127, 31),
|
||||
XGENE_EXTD_STAT(tx_rx_255b_frame_cntr, TR255, 31),
|
||||
XGENE_EXTD_STAT(tx_rx_511b_frame_cntr, TR511, 31),
|
||||
XGENE_EXTD_STAT(tx_rx_1023b_frame_cntr, TR1K, 31),
|
||||
XGENE_EXTD_STAT(tx_rx_1518b_frame_cntr, TRMAX, 31),
|
||||
XGENE_EXTD_STAT(tx_rx_1522b_frame_cntr, TRMGV, 31),
|
||||
XGENE_EXTD_STAT(rx_fcs_error_cntr, RFCS, 16),
|
||||
XGENE_EXTD_STAT(rx_multicast_pkt_cntr, RMCA, 31),
|
||||
XGENE_EXTD_STAT(rx_broadcast_pkt_cntr, RBCA, 31),
|
||||
XGENE_EXTD_STAT(rx_ctrl_frame_pkt_cntr, RXCF, 16),
|
||||
XGENE_EXTD_STAT(rx_pause_frame_pkt_cntr, RXPF, 16),
|
||||
XGENE_EXTD_STAT(rx_unk_opcode_cntr, RXUO, 16),
|
||||
XGENE_EXTD_STAT(rx_align_err_cntr, RALN, 16),
|
||||
XGENE_EXTD_STAT(rx_frame_len_err_cntr, RFLR, 16),
|
||||
XGENE_EXTD_STAT(rx_frame_len_err_recov_cntr, DUMP, 0),
|
||||
XGENE_EXTD_STAT(rx_code_err_cntr, RCDE, 16),
|
||||
XGENE_EXTD_STAT(rx_carrier_sense_err_cntr, RCSE, 16),
|
||||
XGENE_EXTD_STAT(rx_undersize_pkt_cntr, RUND, 16),
|
||||
XGENE_EXTD_STAT(rx_oversize_pkt_cntr, ROVR, 16),
|
||||
XGENE_EXTD_STAT(rx_fragments_cntr, RFRG, 16),
|
||||
XGENE_EXTD_STAT(rx_jabber_cntr, RJBR, 16),
|
||||
XGENE_EXTD_STAT(rx_jabber_recov_cntr, DUMP, 0),
|
||||
XGENE_EXTD_STAT(rx_dropped_pkt_cntr, RDRP, 16),
|
||||
XGENE_EXTD_STAT(rx_overrun_cntr, DUMP, 0),
|
||||
XGENE_EXTD_STAT(tx_multicast_pkt_cntr, TMCA, 31),
|
||||
XGENE_EXTD_STAT(tx_broadcast_pkt_cntr, TBCA, 31),
|
||||
XGENE_EXTD_STAT(tx_pause_ctrl_frame_cntr, TXPF, 16),
|
||||
XGENE_EXTD_STAT(tx_defer_pkt_cntr, TDFR, 31),
|
||||
XGENE_EXTD_STAT(tx_excv_defer_pkt_cntr, TEDF, 31),
|
||||
XGENE_EXTD_STAT(tx_single_col_pkt_cntr, TSCL, 31),
|
||||
XGENE_EXTD_STAT(tx_multi_col_pkt_cntr, TMCL, 31),
|
||||
XGENE_EXTD_STAT(tx_late_col_pkt_cntr, TLCL, 31),
|
||||
XGENE_EXTD_STAT(tx_excv_col_pkt_cntr, TXCL, 31),
|
||||
XGENE_EXTD_STAT(tx_total_col_cntr, TNCL, 31),
|
||||
XGENE_EXTD_STAT(tx_pause_frames_hnrd_cntr, TPFH, 16),
|
||||
XGENE_EXTD_STAT(tx_drop_frame_cntr, TDRP, 16),
|
||||
XGENE_EXTD_STAT(tx_jabber_frame_cntr, TJBR, 12),
|
||||
XGENE_EXTD_STAT(tx_fcs_error_cntr, TFCS, 12),
|
||||
XGENE_EXTD_STAT(tx_ctrl_frame_cntr, TXCF, 12),
|
||||
XGENE_EXTD_STAT(tx_oversize_frame_cntr, TOVR, 12),
|
||||
XGENE_EXTD_STAT(tx_undersize_frame_cntr, TUND, 12),
|
||||
XGENE_EXTD_STAT(tx_fragments_cntr, TFRG, 12),
|
||||
XGENE_EXTD_STAT(tx_underrun_cntr, DUMP, 0)
|
||||
};
|
||||
|
||||
#define XGENE_STATS_LEN ARRAY_SIZE(gstrings_stats)
|
||||
#define XGENE_EXTD_STATS_LEN ARRAY_SIZE(gstrings_extd_stats)
|
||||
#define RFCS_IDX 7
|
||||
#define RALN_IDX 13
|
||||
#define RFLR_IDX 14
|
||||
#define FALSE_RFLR_IDX 15
|
||||
#define RUND_IDX 18
|
||||
#define FALSE_RJBR_IDX 22
|
||||
#define RX_OVERRUN_IDX 24
|
||||
#define TFCS_IDX 38
|
||||
#define TFRG_IDX 42
|
||||
#define TX_UNDERRUN_IDX 43
|
||||
|
||||
static void xgene_get_drvinfo(struct net_device *ndev,
|
||||
struct ethtool_drvinfo *info)
|
||||
|
@ -142,6 +208,11 @@ static void xgene_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
|
|||
memcpy(p, gstrings_stats[i].name, ETH_GSTRING_LEN);
|
||||
p += ETH_GSTRING_LEN;
|
||||
}
|
||||
|
||||
for (i = 0; i < XGENE_EXTD_STATS_LEN; i++) {
|
||||
memcpy(p, gstrings_extd_stats[i].name, ETH_GSTRING_LEN);
|
||||
p += ETH_GSTRING_LEN;
|
||||
}
|
||||
}
|
||||
|
||||
static int xgene_get_sset_count(struct net_device *ndev, int sset)
|
||||
|
@ -149,18 +220,71 @@ static int xgene_get_sset_count(struct net_device *ndev, int sset)
|
|||
if (sset != ETH_SS_STATS)
|
||||
return -EINVAL;
|
||||
|
||||
return XGENE_STATS_LEN;
|
||||
return XGENE_STATS_LEN + XGENE_EXTD_STATS_LEN;
|
||||
}
|
||||
|
||||
static void xgene_get_extd_stats(struct xgene_enet_pdata *pdata)
|
||||
{
|
||||
u32 rx_drop, tx_drop;
|
||||
u32 mask, tmp;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < XGENE_EXTD_STATS_LEN; i++) {
|
||||
tmp = xgene_enet_rd_stat(pdata, gstrings_extd_stats[i].addr);
|
||||
if (gstrings_extd_stats[i].mask) {
|
||||
mask = GENMASK(gstrings_extd_stats[i].mask - 1, 0);
|
||||
pdata->extd_stats[i] += (tmp & mask);
|
||||
}
|
||||
}
|
||||
|
||||
if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) {
|
||||
/* Errata 10GE_10 - SW should intepret RALN as 0 */
|
||||
pdata->extd_stats[RALN_IDX] = 0;
|
||||
} else {
|
||||
/* Errata ENET_15 - Fixes RFCS, RFLR, TFCS counter */
|
||||
pdata->extd_stats[RFCS_IDX] -= pdata->extd_stats[RALN_IDX];
|
||||
pdata->extd_stats[RFLR_IDX] -= pdata->extd_stats[RUND_IDX];
|
||||
pdata->extd_stats[TFCS_IDX] -= pdata->extd_stats[TFRG_IDX];
|
||||
}
|
||||
|
||||
pdata->mac_ops->get_drop_cnt(pdata, &rx_drop, &tx_drop);
|
||||
pdata->extd_stats[RX_OVERRUN_IDX] += rx_drop;
|
||||
pdata->extd_stats[TX_UNDERRUN_IDX] += tx_drop;
|
||||
|
||||
/* Errata 10GE_8 - Update Frame recovered from Errata 10GE_8/ENET_11 */
|
||||
pdata->extd_stats[FALSE_RFLR_IDX] = pdata->false_rflr;
|
||||
/* Errata ENET_15 - Jabber Frame recov'ed from Errata 10GE_10/ENET_15 */
|
||||
pdata->extd_stats[FALSE_RJBR_IDX] = pdata->vlan_rjbr;
|
||||
}
|
||||
|
||||
int xgene_extd_stats_init(struct xgene_enet_pdata *pdata)
|
||||
{
|
||||
pdata->extd_stats = devm_kmalloc_array(&pdata->pdev->dev,
|
||||
XGENE_EXTD_STATS_LEN, sizeof(u64), GFP_KERNEL);
|
||||
if (!pdata->extd_stats)
|
||||
return -ENOMEM;
|
||||
|
||||
xgene_get_extd_stats(pdata);
|
||||
memset(pdata->extd_stats, 0, XGENE_EXTD_STATS_LEN * sizeof(u64));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void xgene_get_ethtool_stats(struct net_device *ndev,
|
||||
struct ethtool_stats *dummy,
|
||||
u64 *data)
|
||||
{
|
||||
void *pdata = netdev_priv(ndev);
|
||||
struct xgene_enet_pdata *pdata = netdev_priv(ndev);
|
||||
struct rtnl_link_stats64 stats;
|
||||
int i;
|
||||
|
||||
dev_get_stats(ndev, &stats);
|
||||
for (i = 0; i < XGENE_STATS_LEN; i++)
|
||||
*data++ = *(u64 *)(pdata + gstrings_stats[i].offset);
|
||||
data[i] = *(u64 *)((char *)&stats + gstrings_stats[i].offset);
|
||||
|
||||
xgene_get_extd_stats(pdata);
|
||||
for (i = 0; i < XGENE_EXTD_STATS_LEN; i++)
|
||||
data[i + XGENE_STATS_LEN] = pdata->extd_stats[i];
|
||||
}
|
||||
|
||||
static void xgene_get_pauseparam(struct net_device *ndev,
|
||||
|
|
|
@ -205,30 +205,24 @@ static u32 xgene_enet_ring_len(struct xgene_enet_desc_ring *ring)
|
|||
}
|
||||
|
||||
void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring,
|
||||
struct xgene_enet_pdata *pdata,
|
||||
enum xgene_enet_err_code status)
|
||||
{
|
||||
switch (status) {
|
||||
case INGRESS_CRC:
|
||||
ring->rx_crc_errors++;
|
||||
ring->rx_dropped++;
|
||||
break;
|
||||
case INGRESS_CHECKSUM:
|
||||
case INGRESS_CHECKSUM_COMPUTE:
|
||||
ring->rx_errors++;
|
||||
ring->rx_dropped++;
|
||||
break;
|
||||
case INGRESS_TRUNC_FRAME:
|
||||
ring->rx_frame_errors++;
|
||||
ring->rx_dropped++;
|
||||
break;
|
||||
case INGRESS_PKT_LEN:
|
||||
ring->rx_length_errors++;
|
||||
ring->rx_dropped++;
|
||||
break;
|
||||
case INGRESS_PKT_UNDER:
|
||||
ring->rx_frame_errors++;
|
||||
ring->rx_dropped++;
|
||||
break;
|
||||
case INGRESS_FIFO_OVERRUN:
|
||||
ring->rx_fifo_errors++;
|
||||
|
@ -270,42 +264,39 @@ static void xgene_enet_wr_mcx_csr(struct xgene_enet_pdata *pdata,
|
|||
iowrite32(val, addr);
|
||||
}
|
||||
|
||||
static bool xgene_enet_wr_indirect(void __iomem *addr, void __iomem *wr,
|
||||
void __iomem *cmd, void __iomem *cmd_done,
|
||||
u32 wr_addr, u32 wr_data)
|
||||
{
|
||||
u32 done;
|
||||
u8 wait = 10;
|
||||
|
||||
iowrite32(wr_addr, addr);
|
||||
iowrite32(wr_data, wr);
|
||||
iowrite32(XGENE_ENET_WR_CMD, cmd);
|
||||
|
||||
/* wait for write command to complete */
|
||||
while (!(done = ioread32(cmd_done)) && wait--)
|
||||
udelay(1);
|
||||
|
||||
if (!done)
|
||||
return false;
|
||||
|
||||
iowrite32(0, cmd);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void xgene_enet_wr_mcx_mac(struct xgene_enet_pdata *pdata,
|
||||
u32 wr_addr, u32 wr_data)
|
||||
void xgene_enet_wr_mac(struct xgene_enet_pdata *pdata, u32 wr_addr, u32 wr_data)
|
||||
{
|
||||
void __iomem *addr, *wr, *cmd, *cmd_done;
|
||||
struct net_device *ndev = pdata->ndev;
|
||||
u8 wait = 10;
|
||||
u32 done;
|
||||
|
||||
if (pdata->mdio_driver && ndev->phydev &&
|
||||
pdata->phy_mode == PHY_INTERFACE_MODE_RGMII) {
|
||||
struct mii_bus *bus = ndev->phydev->mdio.bus;
|
||||
|
||||
return xgene_mdio_wr_mac(bus->priv, wr_addr, wr_data);
|
||||
}
|
||||
|
||||
addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET;
|
||||
wr = pdata->mcx_mac_addr + MAC_WRITE_REG_OFFSET;
|
||||
cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET;
|
||||
cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET;
|
||||
|
||||
if (!xgene_enet_wr_indirect(addr, wr, cmd, cmd_done, wr_addr, wr_data))
|
||||
netdev_err(pdata->ndev, "MCX mac write failed, addr: %04x\n",
|
||||
wr_addr);
|
||||
spin_lock(&pdata->mac_lock);
|
||||
iowrite32(wr_addr, addr);
|
||||
iowrite32(wr_data, wr);
|
||||
iowrite32(XGENE_ENET_WR_CMD, cmd);
|
||||
|
||||
while (!(done = ioread32(cmd_done)) && wait--)
|
||||
udelay(1);
|
||||
|
||||
if (!done)
|
||||
netdev_err(ndev, "mac write failed, addr: %04x data: %08x\n",
|
||||
wr_addr, wr_data);
|
||||
|
||||
iowrite32(0, cmd);
|
||||
spin_unlock(&pdata->mac_lock);
|
||||
}
|
||||
|
||||
static void xgene_enet_rd_csr(struct xgene_enet_pdata *pdata,
|
||||
|
@ -332,42 +323,69 @@ static void xgene_enet_rd_mcx_csr(struct xgene_enet_pdata *pdata,
|
|||
*val = ioread32(addr);
|
||||
}
|
||||
|
||||
static bool xgene_enet_rd_indirect(void __iomem *addr, void __iomem *rd,
|
||||
void __iomem *cmd, void __iomem *cmd_done,
|
||||
u32 rd_addr, u32 *rd_data)
|
||||
{
|
||||
u32 done;
|
||||
u8 wait = 10;
|
||||
|
||||
iowrite32(rd_addr, addr);
|
||||
iowrite32(XGENE_ENET_RD_CMD, cmd);
|
||||
|
||||
/* wait for read command to complete */
|
||||
while (!(done = ioread32(cmd_done)) && wait--)
|
||||
udelay(1);
|
||||
|
||||
if (!done)
|
||||
return false;
|
||||
|
||||
*rd_data = ioread32(rd);
|
||||
iowrite32(0, cmd);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void xgene_enet_rd_mcx_mac(struct xgene_enet_pdata *pdata,
|
||||
u32 rd_addr, u32 *rd_data)
|
||||
u32 xgene_enet_rd_mac(struct xgene_enet_pdata *pdata, u32 rd_addr)
|
||||
{
|
||||
void __iomem *addr, *rd, *cmd, *cmd_done;
|
||||
u32 done, rd_data;
|
||||
u8 wait = 10;
|
||||
|
||||
if (pdata->mdio_driver && pdata->ndev->phydev &&
|
||||
pdata->phy_mode == PHY_INTERFACE_MODE_RGMII) {
|
||||
struct mii_bus *bus = pdata->ndev->phydev->mdio.bus;
|
||||
|
||||
return xgene_mdio_rd_mac(bus->priv, rd_addr);
|
||||
}
|
||||
|
||||
addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET;
|
||||
rd = pdata->mcx_mac_addr + MAC_READ_REG_OFFSET;
|
||||
cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET;
|
||||
cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET;
|
||||
|
||||
if (!xgene_enet_rd_indirect(addr, rd, cmd, cmd_done, rd_addr, rd_data))
|
||||
netdev_err(pdata->ndev, "MCX mac read failed, addr: %04x\n",
|
||||
spin_lock(&pdata->mac_lock);
|
||||
iowrite32(rd_addr, addr);
|
||||
iowrite32(XGENE_ENET_RD_CMD, cmd);
|
||||
|
||||
while (!(done = ioread32(cmd_done)) && wait--)
|
||||
udelay(1);
|
||||
|
||||
if (!done)
|
||||
netdev_err(pdata->ndev, "mac read failed, addr: %04x\n",
|
||||
rd_addr);
|
||||
|
||||
rd_data = ioread32(rd);
|
||||
iowrite32(0, cmd);
|
||||
spin_unlock(&pdata->mac_lock);
|
||||
|
||||
return rd_data;
|
||||
}
|
||||
|
||||
u32 xgene_enet_rd_stat(struct xgene_enet_pdata *pdata, u32 rd_addr)
|
||||
{
|
||||
void __iomem *addr, *rd, *cmd, *cmd_done;
|
||||
u32 done, rd_data;
|
||||
u8 wait = 10;
|
||||
|
||||
addr = pdata->mcx_stats_addr + STAT_ADDR_REG_OFFSET;
|
||||
rd = pdata->mcx_stats_addr + STAT_READ_REG_OFFSET;
|
||||
cmd = pdata->mcx_stats_addr + STAT_COMMAND_REG_OFFSET;
|
||||
cmd_done = pdata->mcx_stats_addr + STAT_COMMAND_DONE_REG_OFFSET;
|
||||
|
||||
spin_lock(&pdata->stats_lock);
|
||||
iowrite32(rd_addr, addr);
|
||||
iowrite32(XGENE_ENET_RD_CMD, cmd);
|
||||
|
||||
while (!(done = ioread32(cmd_done)) && wait--)
|
||||
udelay(1);
|
||||
|
||||
if (!done)
|
||||
netdev_err(pdata->ndev, "mac stats read failed, addr: %04x\n",
|
||||
rd_addr);
|
||||
|
||||
rd_data = ioread32(rd);
|
||||
iowrite32(0, cmd);
|
||||
spin_unlock(&pdata->stats_lock);
|
||||
|
||||
return rd_data;
|
||||
}
|
||||
|
||||
static void xgene_gmac_set_mac_addr(struct xgene_enet_pdata *pdata)
|
||||
|
@ -379,8 +397,8 @@ static void xgene_gmac_set_mac_addr(struct xgene_enet_pdata *pdata)
|
|||
(dev_addr[1] << 8) | dev_addr[0];
|
||||
addr1 = (dev_addr[5] << 24) | (dev_addr[4] << 16);
|
||||
|
||||
xgene_enet_wr_mcx_mac(pdata, STATION_ADDR0_ADDR, addr0);
|
||||
xgene_enet_wr_mcx_mac(pdata, STATION_ADDR1_ADDR, addr1);
|
||||
xgene_enet_wr_mac(pdata, STATION_ADDR0_ADDR, addr0);
|
||||
xgene_enet_wr_mac(pdata, STATION_ADDR1_ADDR, addr1);
|
||||
}
|
||||
|
||||
static int xgene_enet_ecc_init(struct xgene_enet_pdata *pdata)
|
||||
|
@ -405,8 +423,8 @@ static int xgene_enet_ecc_init(struct xgene_enet_pdata *pdata)
|
|||
|
||||
static void xgene_gmac_reset(struct xgene_enet_pdata *pdata)
|
||||
{
|
||||
xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, SOFT_RESET1);
|
||||
xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, 0);
|
||||
xgene_enet_wr_mac(pdata, MAC_CONFIG_1_ADDR, SOFT_RESET1);
|
||||
xgene_enet_wr_mac(pdata, MAC_CONFIG_1_ADDR, 0);
|
||||
}
|
||||
|
||||
static void xgene_enet_configure_clock(struct xgene_enet_pdata *pdata)
|
||||
|
@ -456,8 +474,8 @@ static void xgene_gmac_set_speed(struct xgene_enet_pdata *pdata)
|
|||
|
||||
xgene_enet_rd_mcx_csr(pdata, ICM_CONFIG0_REG_0_ADDR, &icm0);
|
||||
xgene_enet_rd_mcx_csr(pdata, ICM_CONFIG2_REG_0_ADDR, &icm2);
|
||||
xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_2_ADDR, &mc2);
|
||||
xgene_enet_rd_mcx_mac(pdata, INTERFACE_CONTROL_ADDR, &intf_ctl);
|
||||
mc2 = xgene_enet_rd_mac(pdata, MAC_CONFIG_2_ADDR);
|
||||
intf_ctl = xgene_enet_rd_mac(pdata, INTERFACE_CONTROL_ADDR);
|
||||
xgene_enet_rd_csr(pdata, RGMII_REG_0_ADDR, &rgmii);
|
||||
|
||||
switch (pdata->phy_speed) {
|
||||
|
@ -495,8 +513,8 @@ static void xgene_gmac_set_speed(struct xgene_enet_pdata *pdata)
|
|||
}
|
||||
|
||||
mc2 |= FULL_DUPLEX2 | PAD_CRC | LENGTH_CHK;
|
||||
xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_2_ADDR, mc2);
|
||||
xgene_enet_wr_mcx_mac(pdata, INTERFACE_CONTROL_ADDR, intf_ctl);
|
||||
xgene_enet_wr_mac(pdata, MAC_CONFIG_2_ADDR, mc2);
|
||||
xgene_enet_wr_mac(pdata, INTERFACE_CONTROL_ADDR, intf_ctl);
|
||||
xgene_enet_wr_csr(pdata, RGMII_REG_0_ADDR, rgmii);
|
||||
xgene_enet_configure_clock(pdata);
|
||||
|
||||
|
@ -506,7 +524,7 @@ static void xgene_gmac_set_speed(struct xgene_enet_pdata *pdata)
|
|||
|
||||
static void xgene_enet_set_frame_size(struct xgene_enet_pdata *pdata, int size)
|
||||
{
|
||||
xgene_enet_wr_mcx_mac(pdata, MAX_FRAME_LEN_ADDR, size);
|
||||
xgene_enet_wr_mac(pdata, MAX_FRAME_LEN_ADDR, size);
|
||||
}
|
||||
|
||||
static void xgene_gmac_enable_tx_pause(struct xgene_enet_pdata *pdata,
|
||||
|
@ -528,14 +546,14 @@ static void xgene_gmac_flowctl_tx(struct xgene_enet_pdata *pdata, bool enable)
|
|||
{
|
||||
u32 data;
|
||||
|
||||
xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data);
|
||||
data = xgene_enet_rd_mac(pdata, MAC_CONFIG_1_ADDR);
|
||||
|
||||
if (enable)
|
||||
data |= TX_FLOW_EN;
|
||||
else
|
||||
data &= ~TX_FLOW_EN;
|
||||
|
||||
xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data);
|
||||
xgene_enet_wr_mac(pdata, MAC_CONFIG_1_ADDR, data);
|
||||
|
||||
pdata->mac_ops->enable_tx_pause(pdata, enable);
|
||||
}
|
||||
|
@ -544,14 +562,14 @@ static void xgene_gmac_flowctl_rx(struct xgene_enet_pdata *pdata, bool enable)
|
|||
{
|
||||
u32 data;
|
||||
|
||||
xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data);
|
||||
data = xgene_enet_rd_mac(pdata, MAC_CONFIG_1_ADDR);
|
||||
|
||||
if (enable)
|
||||
data |= RX_FLOW_EN;
|
||||
else
|
||||
data &= ~RX_FLOW_EN;
|
||||
|
||||
xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data);
|
||||
xgene_enet_wr_mac(pdata, MAC_CONFIG_1_ADDR, data);
|
||||
}
|
||||
|
||||
static void xgene_gmac_init(struct xgene_enet_pdata *pdata)
|
||||
|
@ -565,9 +583,9 @@ static void xgene_gmac_init(struct xgene_enet_pdata *pdata)
|
|||
xgene_gmac_set_mac_addr(pdata);
|
||||
|
||||
/* Adjust MDC clock frequency */
|
||||
xgene_enet_rd_mcx_mac(pdata, MII_MGMT_CONFIG_ADDR, &value);
|
||||
value = xgene_enet_rd_mac(pdata, MII_MGMT_CONFIG_ADDR);
|
||||
MGMT_CLOCK_SEL_SET(&value, 7);
|
||||
xgene_enet_wr_mcx_mac(pdata, MII_MGMT_CONFIG_ADDR, value);
|
||||
xgene_enet_wr_mac(pdata, MII_MGMT_CONFIG_ADDR, value);
|
||||
|
||||
/* Enable drop if bufpool not available */
|
||||
xgene_enet_rd_csr(pdata, RSIF_CONFIG_REG_ADDR, &value);
|
||||
|
@ -600,6 +618,18 @@ static void xgene_gmac_init(struct xgene_enet_pdata *pdata)
|
|||
xgene_enet_wr_csr(pdata, CFG_BYPASS_ADDR, RESUME_TX);
|
||||
}
|
||||
|
||||
static void xgene_gmac_get_drop_cnt(struct xgene_enet_pdata *pdata,
|
||||
u32 *rx, u32 *tx)
|
||||
{
|
||||
u32 count;
|
||||
|
||||
xgene_enet_rd_mcx_csr(pdata, ICM_ECM_DROP_COUNT_REG0_ADDR, &count);
|
||||
*rx = ICM_DROP_COUNT(count);
|
||||
*tx = ECM_DROP_COUNT(count);
|
||||
/* Errata: 10GE_4 - Fix ICM_ECM_DROP_COUNT not clear-on-read */
|
||||
xgene_enet_rd_mcx_csr(pdata, ECM_CONFIG0_REG_0_ADDR, &count);
|
||||
}
|
||||
|
||||
static void xgene_enet_config_ring_if_assoc(struct xgene_enet_pdata *pdata)
|
||||
{
|
||||
u32 val = 0xffffffff;
|
||||
|
@ -637,32 +667,32 @@ static void xgene_gmac_rx_enable(struct xgene_enet_pdata *pdata)
|
|||
{
|
||||
u32 data;
|
||||
|
||||
xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data);
|
||||
xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data | RX_EN);
|
||||
data = xgene_enet_rd_mac(pdata, MAC_CONFIG_1_ADDR);
|
||||
xgene_enet_wr_mac(pdata, MAC_CONFIG_1_ADDR, data | RX_EN);
|
||||
}
|
||||
|
||||
static void xgene_gmac_tx_enable(struct xgene_enet_pdata *pdata)
|
||||
{
|
||||
u32 data;
|
||||
|
||||
xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data);
|
||||
xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data | TX_EN);
|
||||
data = xgene_enet_rd_mac(pdata, MAC_CONFIG_1_ADDR);
|
||||
xgene_enet_wr_mac(pdata, MAC_CONFIG_1_ADDR, data | TX_EN);
|
||||
}
|
||||
|
||||
static void xgene_gmac_rx_disable(struct xgene_enet_pdata *pdata)
|
||||
{
|
||||
u32 data;
|
||||
|
||||
xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data);
|
||||
xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data & ~RX_EN);
|
||||
data = xgene_enet_rd_mac(pdata, MAC_CONFIG_1_ADDR);
|
||||
xgene_enet_wr_mac(pdata, MAC_CONFIG_1_ADDR, data & ~RX_EN);
|
||||
}
|
||||
|
||||
static void xgene_gmac_tx_disable(struct xgene_enet_pdata *pdata)
|
||||
{
|
||||
u32 data;
|
||||
|
||||
xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data);
|
||||
xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data & ~TX_EN);
|
||||
data = xgene_enet_rd_mac(pdata, MAC_CONFIG_1_ADDR);
|
||||
xgene_enet_wr_mac(pdata, MAC_CONFIG_1_ADDR, data & ~TX_EN);
|
||||
}
|
||||
|
||||
bool xgene_ring_mgr_init(struct xgene_enet_pdata *p)
|
||||
|
@ -733,27 +763,6 @@ static void xgene_enet_clear(struct xgene_enet_pdata *pdata,
|
|||
static void xgene_gport_shutdown(struct xgene_enet_pdata *pdata)
|
||||
{
|
||||
struct device *dev = &pdata->pdev->dev;
|
||||
struct xgene_enet_desc_ring *ring;
|
||||
u32 pb;
|
||||
int i;
|
||||
|
||||
pb = 0;
|
||||
for (i = 0; i < pdata->rxq_cnt; i++) {
|
||||
ring = pdata->rx_ring[i]->buf_pool;
|
||||
pb |= BIT(xgene_enet_get_fpsel(ring->id));
|
||||
ring = pdata->rx_ring[i]->page_pool;
|
||||
if (ring)
|
||||
pb |= BIT(xgene_enet_get_fpsel(ring->id));
|
||||
|
||||
}
|
||||
xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIFPRESET_ADDR, pb);
|
||||
|
||||
pb = 0;
|
||||
for (i = 0; i < pdata->txq_cnt; i++) {
|
||||
ring = pdata->tx_ring[i];
|
||||
pb |= BIT(xgene_enet_ring_bufnum(ring->id));
|
||||
}
|
||||
xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIWQRESET_ADDR, pb);
|
||||
|
||||
if (dev->of_node) {
|
||||
if (!IS_ERR(pdata->clk))
|
||||
|
@ -1009,6 +1018,7 @@ const struct xgene_mac_ops xgene_gmac_ops = {
|
|||
.tx_enable = xgene_gmac_tx_enable,
|
||||
.rx_disable = xgene_gmac_rx_disable,
|
||||
.tx_disable = xgene_gmac_tx_disable,
|
||||
.get_drop_cnt = xgene_gmac_get_drop_cnt,
|
||||
.set_speed = xgene_gmac_set_speed,
|
||||
.set_mac_addr = xgene_gmac_set_mac_addr,
|
||||
.set_framesize = xgene_enet_set_frame_size,
|
||||
|
|
|
@ -115,6 +115,7 @@ enum xgene_enet_rm {
|
|||
#define BLOCK_ETH_CLKRST_CSR_OFFSET 0xc000
|
||||
#define BLOCK_ETH_DIAG_CSR_OFFSET 0xD000
|
||||
#define BLOCK_ETH_MAC_OFFSET 0x0000
|
||||
#define BLOCK_ETH_STATS_OFFSET 0x0000
|
||||
#define BLOCK_ETH_MAC_CSR_OFFSET 0x2800
|
||||
|
||||
#define CLKEN_ADDR 0xc208
|
||||
|
@ -126,6 +127,12 @@ enum xgene_enet_rm {
|
|||
#define MAC_READ_REG_OFFSET 0x0c
|
||||
#define MAC_COMMAND_DONE_REG_OFFSET 0x10
|
||||
|
||||
#define STAT_ADDR_REG_OFFSET 0x14
|
||||
#define STAT_COMMAND_REG_OFFSET 0x18
|
||||
#define STAT_WRITE_REG_OFFSET 0x1c
|
||||
#define STAT_READ_REG_OFFSET 0x20
|
||||
#define STAT_COMMAND_DONE_REG_OFFSET 0x24
|
||||
|
||||
#define PCS_ADDR_REG_OFFSET 0x00
|
||||
#define PCS_COMMAND_REG_OFFSET 0x04
|
||||
#define PCS_WRITE_REG_OFFSET 0x08
|
||||
|
@ -185,6 +192,10 @@ enum xgene_enet_rm {
|
|||
#define CFG_CLE_NXTFPSEL0(val) (((val) << 20) & GENMASK(23, 20))
|
||||
#define ICM_CONFIG0_REG_0_ADDR 0x0400
|
||||
#define ICM_CONFIG2_REG_0_ADDR 0x0410
|
||||
#define ECM_CONFIG0_REG_0_ADDR 0x0500
|
||||
#define ECM_CONFIG0_REG_1_ADDR 0x0504
|
||||
#define ICM_ECM_DROP_COUNT_REG0_ADDR 0x0508
|
||||
#define ICM_ECM_DROP_COUNT_REG1_ADDR 0x050c
|
||||
#define RX_DV_GATE_REG_0_ADDR 0x05fc
|
||||
#define TX_DV_GATE_EN0 BIT(2)
|
||||
#define RX_DV_GATE_EN0 BIT(1)
|
||||
|
@ -217,12 +228,53 @@ enum xgene_enet_rm {
|
|||
#define FULL_DUPLEX2 BIT(0)
|
||||
#define PAD_CRC BIT(2)
|
||||
#define LENGTH_CHK BIT(4)
|
||||
#define SCAN_AUTO_INCR BIT(5)
|
||||
#define TBYT_ADDR 0x38
|
||||
#define TPKT_ADDR 0x39
|
||||
#define TDRP_ADDR 0x45
|
||||
#define TFCS_ADDR 0x47
|
||||
#define TUND_ADDR 0x4a
|
||||
|
||||
#define TR64_ADDR 0x20
|
||||
#define TR127_ADDR 0x21
|
||||
#define TR255_ADDR 0x22
|
||||
#define TR511_ADDR 0x23
|
||||
#define TR1K_ADDR 0x24
|
||||
#define TRMAX_ADDR 0x25
|
||||
#define TRMGV_ADDR 0x26
|
||||
|
||||
#define RFCS_ADDR 0x29
|
||||
#define RMCA_ADDR 0x2a
|
||||
#define RBCA_ADDR 0x2b
|
||||
#define RXCF_ADDR 0x2c
|
||||
#define RXPF_ADDR 0x2d
|
||||
#define RXUO_ADDR 0x2e
|
||||
#define RALN_ADDR 0x2f
|
||||
#define RFLR_ADDR 0x30
|
||||
#define RCDE_ADDR 0x31
|
||||
#define RCSE_ADDR 0x32
|
||||
#define RUND_ADDR 0x33
|
||||
#define ROVR_ADDR 0x34
|
||||
#define RFRG_ADDR 0x35
|
||||
#define RJBR_ADDR 0x36
|
||||
#define RDRP_ADDR 0x37
|
||||
|
||||
#define TMCA_ADDR 0x3a
|
||||
#define TBCA_ADDR 0x3b
|
||||
#define TXPF_ADDR 0x3c
|
||||
#define TDFR_ADDR 0x3d
|
||||
#define TEDF_ADDR 0x3e
|
||||
#define TSCL_ADDR 0x3f
|
||||
#define TMCL_ADDR 0x40
|
||||
#define TLCL_ADDR 0x41
|
||||
#define TXCL_ADDR 0x42
|
||||
#define TNCL_ADDR 0x43
|
||||
#define TPFH_ADDR 0x44
|
||||
#define TDRP_ADDR 0x45
|
||||
#define TJBR_ADDR 0x46
|
||||
#define TFCS_ADDR 0x47
|
||||
#define TXCF_ADDR 0x48
|
||||
#define TOVR_ADDR 0x49
|
||||
#define TUND_ADDR 0x4a
|
||||
#define TFRG_ADDR 0x4b
|
||||
#define DUMP_ADDR 0x27
|
||||
|
||||
#define ECM_DROP_COUNT(src) xgene_get_bits(src, 0, 15)
|
||||
#define ICM_DROP_COUNT(src) xgene_get_bits(src, 16, 31)
|
||||
|
||||
#define TSO_IPPROTO_TCP 1
|
||||
|
||||
|
@ -380,14 +432,16 @@ static inline u16 xgene_enet_get_numslots(u16 id, u32 size)
|
|||
}
|
||||
|
||||
void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring,
|
||||
struct xgene_enet_pdata *pdata,
|
||||
enum xgene_enet_err_code status);
|
||||
|
||||
int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata);
|
||||
void xgene_enet_mdio_remove(struct xgene_enet_pdata *pdata);
|
||||
bool xgene_ring_mgr_init(struct xgene_enet_pdata *p);
|
||||
int xgene_enet_phy_connect(struct net_device *ndev);
|
||||
void xgene_enet_phy_disconnect(struct xgene_enet_pdata *pdata);
|
||||
u32 xgene_enet_rd_mac(struct xgene_enet_pdata *pdata, u32 rd_addr);
|
||||
void xgene_enet_wr_mac(struct xgene_enet_pdata *pdata, u32 wr_addr,
|
||||
u32 wr_data);
|
||||
u32 xgene_enet_rd_stat(struct xgene_enet_pdata *pdata, u32 rd_addr);
|
||||
|
||||
extern const struct xgene_mac_ops xgene_gmac_ops;
|
||||
extern const struct xgene_port_ops xgene_gport_ops;
|
||||
|
|
|
@ -246,9 +246,9 @@ static int xgene_enet_tx_completion(struct xgene_enet_desc_ring *cp_ring,
|
|||
skb_frag_t *frag;
|
||||
dma_addr_t *frag_dma_addr;
|
||||
u16 skb_index;
|
||||
u8 status;
|
||||
int i, ret = 0;
|
||||
u8 mss_index;
|
||||
u8 status;
|
||||
int i;
|
||||
|
||||
skb_index = GET_VAL(USERINFO, le64_to_cpu(raw_desc->m0));
|
||||
skb = cp_ring->cp_skb[skb_index];
|
||||
|
@ -275,19 +275,17 @@ static int xgene_enet_tx_completion(struct xgene_enet_desc_ring *cp_ring,
|
|||
/* Checking for error */
|
||||
status = GET_VAL(LERR, le64_to_cpu(raw_desc->m0));
|
||||
if (unlikely(status > 2)) {
|
||||
xgene_enet_parse_error(cp_ring, netdev_priv(cp_ring->ndev),
|
||||
status);
|
||||
ret = -EIO;
|
||||
cp_ring->tx_dropped++;
|
||||
cp_ring->tx_errors++;
|
||||
}
|
||||
|
||||
if (likely(skb)) {
|
||||
dev_kfree_skb_any(skb);
|
||||
} else {
|
||||
netdev_err(cp_ring->ndev, "completion skb is NULL\n");
|
||||
ret = -EIO;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xgene_enet_setup_mss(struct net_device *ndev, u32 mss)
|
||||
|
@ -658,6 +656,18 @@ static void xgene_enet_free_pagepool(struct xgene_enet_desc_ring *buf_pool,
|
|||
buf_pool->head = head;
|
||||
}
|
||||
|
||||
/* Errata 10GE_10 and ENET_15 - Fix duplicated HW statistic counters */
|
||||
static bool xgene_enet_errata_10GE_10(struct sk_buff *skb, u32 len, u8 status)
|
||||
{
|
||||
if (status == INGRESS_CRC &&
|
||||
len >= (ETHER_STD_PACKET + 1) &&
|
||||
len <= (ETHER_STD_PACKET + 4) &&
|
||||
skb->protocol == htons(ETH_P_8021Q))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Errata 10GE_8 and ENET_11 - allow packet with length <=64B */
|
||||
static bool xgene_enet_errata_10GE_8(struct sk_buff *skb, u32 len, u8 status)
|
||||
{
|
||||
|
@ -708,10 +718,15 @@ static int xgene_enet_rx_frame(struct xgene_enet_desc_ring *rx_ring,
|
|||
status = (GET_VAL(ELERR, le64_to_cpu(raw_desc->m0)) << LERR_LEN) |
|
||||
GET_VAL(LERR, le64_to_cpu(raw_desc->m0));
|
||||
if (unlikely(status)) {
|
||||
if (!xgene_enet_errata_10GE_8(skb, datalen, status)) {
|
||||
if (xgene_enet_errata_10GE_8(skb, datalen, status)) {
|
||||
pdata->false_rflr++;
|
||||
} else if (xgene_enet_errata_10GE_10(skb, datalen, status)) {
|
||||
pdata->vlan_rjbr++;
|
||||
} else {
|
||||
dev_kfree_skb_any(skb);
|
||||
xgene_enet_free_pagepool(page_pool, raw_desc, exp_desc);
|
||||
xgene_enet_parse_error(rx_ring, pdata, status);
|
||||
xgene_enet_parse_error(rx_ring, status);
|
||||
rx_ring->rx_dropped++;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
@ -1466,10 +1481,9 @@ err:
|
|||
|
||||
static void xgene_enet_get_stats64(
|
||||
struct net_device *ndev,
|
||||
struct rtnl_link_stats64 *storage)
|
||||
struct rtnl_link_stats64 *stats)
|
||||
{
|
||||
struct xgene_enet_pdata *pdata = netdev_priv(ndev);
|
||||
struct rtnl_link_stats64 *stats = &pdata->stats;
|
||||
struct xgene_enet_desc_ring *ring;
|
||||
int i;
|
||||
|
||||
|
@ -1478,6 +1492,8 @@ static void xgene_enet_get_stats64(
|
|||
if (ring) {
|
||||
stats->tx_packets += ring->tx_packets;
|
||||
stats->tx_bytes += ring->tx_bytes;
|
||||
stats->tx_dropped += ring->tx_dropped;
|
||||
stats->tx_errors += ring->tx_errors;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1486,14 +1502,18 @@ static void xgene_enet_get_stats64(
|
|||
if (ring) {
|
||||
stats->rx_packets += ring->rx_packets;
|
||||
stats->rx_bytes += ring->rx_bytes;
|
||||
stats->rx_errors += ring->rx_length_errors +
|
||||
stats->rx_dropped += ring->rx_dropped;
|
||||
stats->rx_errors += ring->rx_errors +
|
||||
ring->rx_length_errors +
|
||||
ring->rx_crc_errors +
|
||||
ring->rx_frame_errors +
|
||||
ring->rx_fifo_errors;
|
||||
stats->rx_dropped += ring->rx_dropped;
|
||||
stats->rx_length_errors += ring->rx_length_errors;
|
||||
stats->rx_crc_errors += ring->rx_crc_errors;
|
||||
stats->rx_frame_errors += ring->rx_frame_errors;
|
||||
stats->rx_fifo_errors += ring->rx_fifo_errors;
|
||||
}
|
||||
}
|
||||
memcpy(storage, stats, sizeof(struct rtnl_link_stats64));
|
||||
}
|
||||
|
||||
static int xgene_enet_set_mac_address(struct net_device *ndev, void *addr)
|
||||
|
@ -1788,12 +1808,15 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
|
|||
if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII ||
|
||||
pdata->phy_mode == PHY_INTERFACE_MODE_SGMII) {
|
||||
pdata->mcx_mac_addr = pdata->base_addr + BLOCK_ETH_MAC_OFFSET;
|
||||
pdata->mcx_stats_addr =
|
||||
pdata->base_addr + BLOCK_ETH_STATS_OFFSET;
|
||||
offset = (pdata->enet_id == XGENE_ENET1) ?
|
||||
BLOCK_ETH_MAC_CSR_OFFSET :
|
||||
X2_BLOCK_ETH_MAC_CSR_OFFSET;
|
||||
pdata->mcx_mac_csr_addr = base_addr + offset;
|
||||
} else {
|
||||
pdata->mcx_mac_addr = base_addr + BLOCK_AXG_MAC_OFFSET;
|
||||
pdata->mcx_stats_addr = base_addr + BLOCK_AXG_STATS_OFFSET;
|
||||
pdata->mcx_mac_csr_addr = base_addr + BLOCK_AXG_MAC_CSR_OFFSET;
|
||||
pdata->pcs_addr = base_addr + BLOCK_PCS_OFFSET;
|
||||
}
|
||||
|
@ -2055,6 +2078,7 @@ static int xgene_enet_probe(struct platform_device *pdev)
|
|||
goto err;
|
||||
|
||||
xgene_enet_setup_ops(pdata);
|
||||
spin_lock_init(&pdata->mac_lock);
|
||||
|
||||
if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) {
|
||||
ndev->features |= NETIF_F_TSO | NETIF_F_RXCSUM;
|
||||
|
@ -2085,6 +2109,11 @@ static int xgene_enet_probe(struct platform_device *pdev)
|
|||
goto err1;
|
||||
}
|
||||
|
||||
spin_lock_init(&pdata->stats_lock);
|
||||
ret = xgene_extd_stats_init(pdata);
|
||||
if (ret)
|
||||
goto err2;
|
||||
|
||||
xgene_enet_napi_add(pdata);
|
||||
ret = register_netdev(ndev);
|
||||
if (ret) {
|
||||
|
@ -2130,8 +2159,8 @@ static int xgene_enet_remove(struct platform_device *pdev)
|
|||
xgene_enet_mdio_remove(pdata);
|
||||
|
||||
unregister_netdev(ndev);
|
||||
pdata->port_ops->shutdown(pdata);
|
||||
xgene_enet_delete_desc_rings(pdata);
|
||||
pdata->port_ops->shutdown(pdata);
|
||||
free_netdev(ndev);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
|
||||
#define XGENE_DRV_VERSION "v1.0"
|
||||
#define ETHER_MIN_PACKET 64
|
||||
#define ETHER_STD_PACKET 1518
|
||||
#define XGENE_ENET_STD_MTU 1536
|
||||
#define XGENE_ENET_MAX_MTU 9600
|
||||
#define SKB_BUFFER_SIZE (XGENE_ENET_STD_MTU - NET_IP_ALIGN)
|
||||
|
@ -138,6 +139,8 @@ struct xgene_enet_desc_ring {
|
|||
__le64 *exp_bufs;
|
||||
u64 tx_packets;
|
||||
u64 tx_bytes;
|
||||
u64 tx_dropped;
|
||||
u64 tx_errors;
|
||||
u64 rx_packets;
|
||||
u64 rx_bytes;
|
||||
u64 rx_dropped;
|
||||
|
@ -155,6 +158,7 @@ struct xgene_mac_ops {
|
|||
void (*rx_enable)(struct xgene_enet_pdata *pdata);
|
||||
void (*tx_disable)(struct xgene_enet_pdata *pdata);
|
||||
void (*rx_disable)(struct xgene_enet_pdata *pdata);
|
||||
void (*get_drop_cnt)(struct xgene_enet_pdata *pdata, u32 *rx, u32 *tx);
|
||||
void (*set_speed)(struct xgene_enet_pdata *pdata);
|
||||
void (*set_mac_addr)(struct xgene_enet_pdata *pdata);
|
||||
void (*set_framesize)(struct xgene_enet_pdata *pdata, int framesize);
|
||||
|
@ -212,6 +216,7 @@ struct xgene_enet_pdata {
|
|||
void __iomem *eth_diag_csr_addr;
|
||||
void __iomem *mcx_mac_addr;
|
||||
void __iomem *mcx_mac_csr_addr;
|
||||
void __iomem *mcx_stats_addr;
|
||||
void __iomem *base_addr;
|
||||
void __iomem *pcs_addr;
|
||||
void __iomem *ring_csr_addr;
|
||||
|
@ -219,8 +224,12 @@ struct xgene_enet_pdata {
|
|||
int phy_mode;
|
||||
enum xgene_enet_rm rm;
|
||||
struct xgene_enet_cle cle;
|
||||
struct rtnl_link_stats64 stats;
|
||||
u64 *extd_stats;
|
||||
u64 false_rflr;
|
||||
u64 vlan_rjbr;
|
||||
spinlock_t stats_lock; /* statistics lock */
|
||||
const struct xgene_mac_ops *mac_ops;
|
||||
spinlock_t mac_lock; /* mac lock */
|
||||
const struct xgene_port_ops *port_ops;
|
||||
struct xgene_ring_ops *ring_ops;
|
||||
const struct xgene_cle_ops *cle_ops;
|
||||
|
@ -263,5 +272,6 @@ static inline u16 xgene_enet_dst_ring_num(struct xgene_enet_desc_ring *ring)
|
|||
}
|
||||
|
||||
void xgene_enet_set_ethtool_ops(struct net_device *netdev);
|
||||
int xgene_extd_stats_init(struct xgene_enet_pdata *pdata);
|
||||
|
||||
#endif /* __XGENE_ENET_MAIN_H__ */
|
||||
|
|
|
@ -54,41 +54,6 @@ static void xgene_enet_wr_mcx_csr(struct xgene_enet_pdata *pdata,
|
|||
iowrite32(val, addr);
|
||||
}
|
||||
|
||||
static bool xgene_enet_wr_indirect(struct xgene_indirect_ctl *ctl,
|
||||
u32 wr_addr, u32 wr_data)
|
||||
{
|
||||
int i;
|
||||
|
||||
iowrite32(wr_addr, ctl->addr);
|
||||
iowrite32(wr_data, ctl->ctl);
|
||||
iowrite32(XGENE_ENET_WR_CMD, ctl->cmd);
|
||||
|
||||
/* wait for write command to complete */
|
||||
for (i = 0; i < 10; i++) {
|
||||
if (ioread32(ctl->cmd_done)) {
|
||||
iowrite32(0, ctl->cmd);
|
||||
return true;
|
||||
}
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void xgene_enet_wr_mac(struct xgene_enet_pdata *p,
|
||||
u32 wr_addr, u32 wr_data)
|
||||
{
|
||||
struct xgene_indirect_ctl ctl = {
|
||||
.addr = p->mcx_mac_addr + MAC_ADDR_REG_OFFSET,
|
||||
.ctl = p->mcx_mac_addr + MAC_WRITE_REG_OFFSET,
|
||||
.cmd = p->mcx_mac_addr + MAC_COMMAND_REG_OFFSET,
|
||||
.cmd_done = p->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET
|
||||
};
|
||||
|
||||
if (!xgene_enet_wr_indirect(&ctl, wr_addr, wr_data))
|
||||
netdev_err(p->ndev, "mac write failed, addr: %04x\n", wr_addr);
|
||||
}
|
||||
|
||||
static u32 xgene_enet_rd_csr(struct xgene_enet_pdata *p, u32 offset)
|
||||
{
|
||||
return ioread32(p->eth_csr_addr + offset);
|
||||
|
@ -104,42 +69,6 @@ static u32 xgene_enet_rd_mcx_csr(struct xgene_enet_pdata *p, u32 offset)
|
|||
return ioread32(p->mcx_mac_csr_addr + offset);
|
||||
}
|
||||
|
||||
static u32 xgene_enet_rd_indirect(struct xgene_indirect_ctl *ctl, u32 rd_addr)
|
||||
{
|
||||
u32 rd_data;
|
||||
int i;
|
||||
|
||||
iowrite32(rd_addr, ctl->addr);
|
||||
iowrite32(XGENE_ENET_RD_CMD, ctl->cmd);
|
||||
|
||||
/* wait for read command to complete */
|
||||
for (i = 0; i < 10; i++) {
|
||||
if (ioread32(ctl->cmd_done)) {
|
||||
rd_data = ioread32(ctl->ctl);
|
||||
iowrite32(0, ctl->cmd);
|
||||
|
||||
return rd_data;
|
||||
}
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
pr_err("%s: mac read failed, addr: %04x\n", __func__, rd_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 xgene_enet_rd_mac(struct xgene_enet_pdata *p, u32 rd_addr)
|
||||
{
|
||||
struct xgene_indirect_ctl ctl = {
|
||||
.addr = p->mcx_mac_addr + MAC_ADDR_REG_OFFSET,
|
||||
.ctl = p->mcx_mac_addr + MAC_READ_REG_OFFSET,
|
||||
.cmd = p->mcx_mac_addr + MAC_COMMAND_REG_OFFSET,
|
||||
.cmd_done = p->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET
|
||||
};
|
||||
|
||||
return xgene_enet_rd_indirect(&ctl, rd_addr);
|
||||
}
|
||||
|
||||
static int xgene_enet_ecc_init(struct xgene_enet_pdata *p)
|
||||
{
|
||||
struct net_device *ndev = p->ndev;
|
||||
|
@ -166,6 +95,24 @@ static int xgene_enet_ecc_init(struct xgene_enet_pdata *p)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
static void xgene_sgmac_get_drop_cnt(struct xgene_enet_pdata *pdata,
|
||||
u32 *rx, u32 *tx)
|
||||
{
|
||||
u32 addr, count;
|
||||
|
||||
addr = (pdata->enet_id != XGENE_ENET1) ?
|
||||
XG_MCX_ICM_ECM_DROP_COUNT_REG0_ADDR :
|
||||
ICM_ECM_DROP_COUNT_REG0_ADDR + pdata->port_id * OFFSET_4;
|
||||
count = xgene_enet_rd_mcx_csr(pdata, addr);
|
||||
*rx = ICM_DROP_COUNT(count);
|
||||
*tx = ECM_DROP_COUNT(count);
|
||||
/* Errata: 10GE_4 - ICM_ECM_DROP_COUNT not clear-on-read */
|
||||
addr = (pdata->enet_id != XGENE_ENET1) ?
|
||||
XG_MCX_ECM_CONFIG0_REG_0_ADDR :
|
||||
ECM_CONFIG0_REG_0_ADDR + pdata->port_id * OFFSET_4;
|
||||
xgene_enet_rd_mcx_csr(pdata, addr);
|
||||
}
|
||||
|
||||
static void xgene_enet_config_ring_if_assoc(struct xgene_enet_pdata *p)
|
||||
{
|
||||
u32 val;
|
||||
|
@ -587,26 +534,6 @@ static void xgene_enet_clear(struct xgene_enet_pdata *pdata,
|
|||
static void xgene_enet_shutdown(struct xgene_enet_pdata *p)
|
||||
{
|
||||
struct device *dev = &p->pdev->dev;
|
||||
struct xgene_enet_desc_ring *ring;
|
||||
u32 pb;
|
||||
int i;
|
||||
|
||||
pb = 0;
|
||||
for (i = 0; i < p->rxq_cnt; i++) {
|
||||
ring = p->rx_ring[i]->buf_pool;
|
||||
pb |= BIT(xgene_enet_get_fpsel(ring->id));
|
||||
ring = p->rx_ring[i]->page_pool;
|
||||
if (ring)
|
||||
pb |= BIT(xgene_enet_get_fpsel(ring->id));
|
||||
}
|
||||
xgene_enet_wr_ring_if(p, ENET_CFGSSQMIFPRESET_ADDR, pb);
|
||||
|
||||
pb = 0;
|
||||
for (i = 0; i < p->txq_cnt; i++) {
|
||||
ring = p->tx_ring[i];
|
||||
pb |= BIT(xgene_enet_ring_bufnum(ring->id));
|
||||
}
|
||||
xgene_enet_wr_ring_if(p, ENET_CFGSSQMIWQRESET_ADDR, pb);
|
||||
|
||||
if (dev->of_node) {
|
||||
if (!IS_ERR(p->clk))
|
||||
|
@ -671,6 +598,7 @@ const struct xgene_mac_ops xgene_sgmac_ops = {
|
|||
.tx_enable = xgene_sgmac_tx_enable,
|
||||
.rx_disable = xgene_sgmac_rx_disable,
|
||||
.tx_disable = xgene_sgmac_tx_disable,
|
||||
.get_drop_cnt = xgene_sgmac_get_drop_cnt,
|
||||
.set_speed = xgene_sgmac_set_speed,
|
||||
.set_mac_addr = xgene_sgmac_set_mac_addr,
|
||||
.set_framesize = xgene_sgmac_set_frame_size,
|
||||
|
|
|
@ -71,21 +71,6 @@ static bool xgene_enet_wr_indirect(void __iomem *addr, void __iomem *wr,
|
|||
return true;
|
||||
}
|
||||
|
||||
static void xgene_enet_wr_mac(struct xgene_enet_pdata *pdata,
|
||||
u32 wr_addr, u32 wr_data)
|
||||
{
|
||||
void __iomem *addr, *wr, *cmd, *cmd_done;
|
||||
|
||||
addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET;
|
||||
wr = pdata->mcx_mac_addr + MAC_WRITE_REG_OFFSET;
|
||||
cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET;
|
||||
cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET;
|
||||
|
||||
if (!xgene_enet_wr_indirect(addr, wr, cmd, cmd_done, wr_addr, wr_data))
|
||||
netdev_err(pdata->ndev, "MCX mac write failed, addr: %04x\n",
|
||||
wr_addr);
|
||||
}
|
||||
|
||||
static void xgene_enet_wr_pcs(struct xgene_enet_pdata *pdata,
|
||||
u32 wr_addr, u32 wr_data)
|
||||
{
|
||||
|
@ -148,21 +133,6 @@ static bool xgene_enet_rd_indirect(void __iomem *addr, void __iomem *rd,
|
|||
return true;
|
||||
}
|
||||
|
||||
static void xgene_enet_rd_mac(struct xgene_enet_pdata *pdata,
|
||||
u32 rd_addr, u32 *rd_data)
|
||||
{
|
||||
void __iomem *addr, *rd, *cmd, *cmd_done;
|
||||
|
||||
addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET;
|
||||
rd = pdata->mcx_mac_addr + MAC_READ_REG_OFFSET;
|
||||
cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET;
|
||||
cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET;
|
||||
|
||||
if (!xgene_enet_rd_indirect(addr, rd, cmd, cmd_done, rd_addr, rd_data))
|
||||
netdev_err(pdata->ndev, "MCX mac read failed, addr: %04x\n",
|
||||
rd_addr);
|
||||
}
|
||||
|
||||
static bool xgene_enet_rd_pcs(struct xgene_enet_pdata *pdata,
|
||||
u32 rd_addr, u32 *rd_data)
|
||||
{
|
||||
|
@ -210,6 +180,18 @@ static int xgene_enet_ecc_init(struct xgene_enet_pdata *pdata)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void xgene_xgmac_get_drop_cnt(struct xgene_enet_pdata *pdata,
|
||||
u32 *rx, u32 *tx)
|
||||
{
|
||||
u32 count;
|
||||
|
||||
xgene_enet_rd_axg_csr(pdata, XGENET_ICM_ECM_DROP_COUNT_REG0, &count);
|
||||
*rx = ICM_DROP_COUNT(count);
|
||||
*tx = ECM_DROP_COUNT(count);
|
||||
/* Errata: 10GE_4 - ICM_ECM_DROP_COUNT not clear-on-read */
|
||||
xgene_enet_rd_axg_csr(pdata, XGENET_ECM_CONFIG0_REG_0, &count);
|
||||
}
|
||||
|
||||
static void xgene_enet_config_ring_if_assoc(struct xgene_enet_pdata *pdata)
|
||||
{
|
||||
xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIWQASSOC_ADDR, 0);
|
||||
|
@ -300,7 +282,7 @@ static void xgene_xgmac_flowctl_tx(struct xgene_enet_pdata *pdata, bool enable)
|
|||
{
|
||||
u32 data;
|
||||
|
||||
xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data);
|
||||
data = xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1);
|
||||
|
||||
if (enable)
|
||||
data |= HSTTCTLEN;
|
||||
|
@ -316,7 +298,7 @@ static void xgene_xgmac_flowctl_rx(struct xgene_enet_pdata *pdata, bool enable)
|
|||
{
|
||||
u32 data;
|
||||
|
||||
xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data);
|
||||
data = xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1);
|
||||
|
||||
if (enable)
|
||||
data |= HSTRCTLEN;
|
||||
|
@ -332,7 +314,7 @@ static void xgene_xgmac_init(struct xgene_enet_pdata *pdata)
|
|||
|
||||
xgene_xgmac_reset(pdata);
|
||||
|
||||
xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data);
|
||||
data = xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1);
|
||||
data |= HSTPPEN;
|
||||
data &= ~HSTLENCHK;
|
||||
xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data);
|
||||
|
@ -379,7 +361,7 @@ static void xgene_xgmac_rx_enable(struct xgene_enet_pdata *pdata)
|
|||
{
|
||||
u32 data;
|
||||
|
||||
xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data);
|
||||
data = xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1);
|
||||
xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data | HSTRFEN);
|
||||
}
|
||||
|
||||
|
@ -387,7 +369,7 @@ static void xgene_xgmac_tx_enable(struct xgene_enet_pdata *pdata)
|
|||
{
|
||||
u32 data;
|
||||
|
||||
xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data);
|
||||
data = xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1);
|
||||
xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data | HSTTFEN);
|
||||
}
|
||||
|
||||
|
@ -395,7 +377,7 @@ static void xgene_xgmac_rx_disable(struct xgene_enet_pdata *pdata)
|
|||
{
|
||||
u32 data;
|
||||
|
||||
xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data);
|
||||
data = xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1);
|
||||
xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data & ~HSTRFEN);
|
||||
}
|
||||
|
||||
|
@ -403,7 +385,7 @@ static void xgene_xgmac_tx_disable(struct xgene_enet_pdata *pdata)
|
|||
{
|
||||
u32 data;
|
||||
|
||||
xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data);
|
||||
data = xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1);
|
||||
xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data & ~HSTTFEN);
|
||||
}
|
||||
|
||||
|
@ -464,26 +446,6 @@ static void xgene_enet_xgcle_bypass(struct xgene_enet_pdata *pdata,
|
|||
static void xgene_enet_shutdown(struct xgene_enet_pdata *pdata)
|
||||
{
|
||||
struct device *dev = &pdata->pdev->dev;
|
||||
struct xgene_enet_desc_ring *ring;
|
||||
u32 pb;
|
||||
int i;
|
||||
|
||||
pb = 0;
|
||||
for (i = 0; i < pdata->rxq_cnt; i++) {
|
||||
ring = pdata->rx_ring[i]->buf_pool;
|
||||
pb |= BIT(xgene_enet_get_fpsel(ring->id));
|
||||
ring = pdata->rx_ring[i]->page_pool;
|
||||
if (ring)
|
||||
pb |= BIT(xgene_enet_get_fpsel(ring->id));
|
||||
}
|
||||
xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIFPRESET_ADDR, pb);
|
||||
|
||||
pb = 0;
|
||||
for (i = 0; i < pdata->txq_cnt; i++) {
|
||||
ring = pdata->tx_ring[i];
|
||||
pb |= BIT(xgene_enet_ring_bufnum(ring->id));
|
||||
}
|
||||
xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIWQRESET_ADDR, pb);
|
||||
|
||||
if (dev->of_node) {
|
||||
if (!IS_ERR(pdata->clk))
|
||||
|
@ -567,6 +529,7 @@ const struct xgene_mac_ops xgene_xgmac_ops = {
|
|||
.set_mac_addr = xgene_xgmac_set_mac_addr,
|
||||
.set_framesize = xgene_xgmac_set_frame_size,
|
||||
.set_mss = xgene_xgmac_set_mss,
|
||||
.get_drop_cnt = xgene_xgmac_get_drop_cnt,
|
||||
.link_state = xgene_enet_link_state,
|
||||
.enable_tx_pause = xgene_xgmac_enable_tx_pause,
|
||||
.flowctl_rx = xgene_xgmac_flowctl_rx,
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#define X2_BLOCK_ETH_MAC_CSR_OFFSET 0x3000
|
||||
#define BLOCK_AXG_MAC_OFFSET 0x0800
|
||||
#define BLOCK_AXG_STATS_OFFSET 0x0800
|
||||
#define BLOCK_AXG_MAC_CSR_OFFSET 0x2000
|
||||
#define BLOCK_PCS_OFFSET 0x3800
|
||||
|
||||
|
@ -70,6 +71,8 @@
|
|||
#define XG_RSIF_CONFIG1_REG_ADDR 0x00b8
|
||||
#define XG_RSIF_PLC_CLE_BUFF_THRESH 0x1
|
||||
#define RSIF_PLC_CLE_BUFF_THRESH_SET(dst, val) xgene_set_bits(dst, val, 0, 2)
|
||||
#define XG_MCX_ECM_CONFIG0_REG_0_ADDR 0x0070
|
||||
#define XG_MCX_ICM_ECM_DROP_COUNT_REG0_ADDR 0x0124
|
||||
#define XCLE_BYPASS_REG0_ADDR 0x0160
|
||||
#define XCLE_BYPASS_REG1_ADDR 0x0164
|
||||
#define XG_CFG_BYPASS_ADDR 0x0204
|
||||
|
@ -80,6 +83,8 @@
|
|||
#define XG_ENET_SPARE_CFG_REG_ADDR 0x040c
|
||||
#define XG_ENET_SPARE_CFG_REG_1_ADDR 0x0410
|
||||
#define XGENET_RX_DV_GATE_REG_0_ADDR 0x0804
|
||||
#define XGENET_ECM_CONFIG0_REG_0 0x0870
|
||||
#define XGENET_ICM_ECM_DROP_COUNT_REG0 0x0924
|
||||
#define XGENET_CSR_ECM_CFG_0_ADDR 0x0880
|
||||
#define XGENET_CSR_MULTI_DPF0_ADDR 0x0888
|
||||
#define XGENET_CSR_MULTI_DPF1_ADDR 0x088c
|
||||
|
|
|
@ -34,76 +34,73 @@
|
|||
|
||||
static bool xgene_mdio_status;
|
||||
|
||||
static u32 xgene_enet_rd_mac(void __iomem *base_addr, u32 rd_addr)
|
||||
u32 xgene_mdio_rd_mac(struct xgene_mdio_pdata *pdata, u32 rd_addr)
|
||||
{
|
||||
void __iomem *addr, *rd, *cmd, *cmd_done;
|
||||
u32 done, rd_data = BUSY_MASK;
|
||||
u8 wait = 10;
|
||||
|
||||
addr = base_addr + MAC_ADDR_REG_OFFSET;
|
||||
rd = base_addr + MAC_READ_REG_OFFSET;
|
||||
cmd = base_addr + MAC_COMMAND_REG_OFFSET;
|
||||
cmd_done = base_addr + MAC_COMMAND_DONE_REG_OFFSET;
|
||||
addr = pdata->mac_csr_addr + MAC_ADDR_REG_OFFSET;
|
||||
rd = pdata->mac_csr_addr + MAC_READ_REG_OFFSET;
|
||||
cmd = pdata->mac_csr_addr + MAC_COMMAND_REG_OFFSET;
|
||||
cmd_done = pdata->mac_csr_addr + MAC_COMMAND_DONE_REG_OFFSET;
|
||||
|
||||
spin_lock(&pdata->mac_lock);
|
||||
iowrite32(rd_addr, addr);
|
||||
iowrite32(XGENE_ENET_RD_CMD, cmd);
|
||||
|
||||
while (wait--) {
|
||||
done = ioread32(cmd_done);
|
||||
if (done)
|
||||
break;
|
||||
while (!(done = ioread32(cmd_done)) && wait--)
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
if (!done)
|
||||
return rd_data;
|
||||
if (done)
|
||||
rd_data = ioread32(rd);
|
||||
|
||||
rd_data = ioread32(rd);
|
||||
iowrite32(0, cmd);
|
||||
spin_unlock(&pdata->mac_lock);
|
||||
|
||||
return rd_data;
|
||||
}
|
||||
EXPORT_SYMBOL(xgene_mdio_rd_mac);
|
||||
|
||||
static void xgene_enet_wr_mac(void __iomem *base_addr, u32 wr_addr, u32 wr_data)
|
||||
void xgene_mdio_wr_mac(struct xgene_mdio_pdata *pdata, u32 wr_addr, u32 data)
|
||||
{
|
||||
void __iomem *addr, *wr, *cmd, *cmd_done;
|
||||
u8 wait = 10;
|
||||
u32 done;
|
||||
|
||||
addr = base_addr + MAC_ADDR_REG_OFFSET;
|
||||
wr = base_addr + MAC_WRITE_REG_OFFSET;
|
||||
cmd = base_addr + MAC_COMMAND_REG_OFFSET;
|
||||
cmd_done = base_addr + MAC_COMMAND_DONE_REG_OFFSET;
|
||||
addr = pdata->mac_csr_addr + MAC_ADDR_REG_OFFSET;
|
||||
wr = pdata->mac_csr_addr + MAC_WRITE_REG_OFFSET;
|
||||
cmd = pdata->mac_csr_addr + MAC_COMMAND_REG_OFFSET;
|
||||
cmd_done = pdata->mac_csr_addr + MAC_COMMAND_DONE_REG_OFFSET;
|
||||
|
||||
spin_lock(&pdata->mac_lock);
|
||||
iowrite32(wr_addr, addr);
|
||||
iowrite32(wr_data, wr);
|
||||
iowrite32(data, wr);
|
||||
iowrite32(XGENE_ENET_WR_CMD, cmd);
|
||||
|
||||
while (wait--) {
|
||||
done = ioread32(cmd_done);
|
||||
if (done)
|
||||
break;
|
||||
while (!(done = ioread32(cmd_done)) && wait--)
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
if (!done)
|
||||
pr_err("MCX mac write failed, addr: 0x%04x\n", wr_addr);
|
||||
|
||||
iowrite32(0, cmd);
|
||||
spin_unlock(&pdata->mac_lock);
|
||||
}
|
||||
EXPORT_SYMBOL(xgene_mdio_wr_mac);
|
||||
|
||||
int xgene_mdio_rgmii_read(struct mii_bus *bus, int phy_id, int reg)
|
||||
{
|
||||
void __iomem *addr = (void __iomem *)bus->priv;
|
||||
struct xgene_mdio_pdata *pdata = (struct xgene_mdio_pdata *)bus->priv;
|
||||
u32 data, done;
|
||||
u8 wait = 10;
|
||||
|
||||
data = SET_VAL(PHY_ADDR, phy_id) | SET_VAL(REG_ADDR, reg);
|
||||
xgene_enet_wr_mac(addr, MII_MGMT_ADDRESS_ADDR, data);
|
||||
xgene_enet_wr_mac(addr, MII_MGMT_COMMAND_ADDR, READ_CYCLE_MASK);
|
||||
xgene_mdio_wr_mac(pdata, MII_MGMT_ADDRESS_ADDR, data);
|
||||
xgene_mdio_wr_mac(pdata, MII_MGMT_COMMAND_ADDR, READ_CYCLE_MASK);
|
||||
do {
|
||||
usleep_range(5, 10);
|
||||
done = xgene_enet_rd_mac(addr, MII_MGMT_INDICATORS_ADDR);
|
||||
done = xgene_mdio_rd_mac(pdata, MII_MGMT_INDICATORS_ADDR);
|
||||
} while ((done & BUSY_MASK) && wait--);
|
||||
|
||||
if (done & BUSY_MASK) {
|
||||
|
@ -111,8 +108,8 @@ int xgene_mdio_rgmii_read(struct mii_bus *bus, int phy_id, int reg)
|
|||
return -EBUSY;
|
||||
}
|
||||
|
||||
data = xgene_enet_rd_mac(addr, MII_MGMT_STATUS_ADDR);
|
||||
xgene_enet_wr_mac(addr, MII_MGMT_COMMAND_ADDR, 0);
|
||||
data = xgene_mdio_rd_mac(pdata, MII_MGMT_STATUS_ADDR);
|
||||
xgene_mdio_wr_mac(pdata, MII_MGMT_COMMAND_ADDR, 0);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
@ -120,17 +117,17 @@ EXPORT_SYMBOL(xgene_mdio_rgmii_read);
|
|||
|
||||
int xgene_mdio_rgmii_write(struct mii_bus *bus, int phy_id, int reg, u16 data)
|
||||
{
|
||||
void __iomem *addr = (void __iomem *)bus->priv;
|
||||
struct xgene_mdio_pdata *pdata = (struct xgene_mdio_pdata *)bus->priv;
|
||||
u32 val, done;
|
||||
u8 wait = 10;
|
||||
|
||||
val = SET_VAL(PHY_ADDR, phy_id) | SET_VAL(REG_ADDR, reg);
|
||||
xgene_enet_wr_mac(addr, MII_MGMT_ADDRESS_ADDR, val);
|
||||
xgene_mdio_wr_mac(pdata, MII_MGMT_ADDRESS_ADDR, val);
|
||||
|
||||
xgene_enet_wr_mac(addr, MII_MGMT_CONTROL_ADDR, data);
|
||||
xgene_mdio_wr_mac(pdata, MII_MGMT_CONTROL_ADDR, data);
|
||||
do {
|
||||
usleep_range(5, 10);
|
||||
done = xgene_enet_rd_mac(addr, MII_MGMT_INDICATORS_ADDR);
|
||||
done = xgene_mdio_rd_mac(pdata, MII_MGMT_INDICATORS_ADDR);
|
||||
} while ((done & BUSY_MASK) && wait--);
|
||||
|
||||
if (done & BUSY_MASK) {
|
||||
|
@ -174,8 +171,8 @@ static int xgene_enet_ecc_init(struct xgene_mdio_pdata *pdata)
|
|||
|
||||
static void xgene_gmac_reset(struct xgene_mdio_pdata *pdata)
|
||||
{
|
||||
xgene_enet_wr_mac(pdata->mac_csr_addr, MAC_CONFIG_1_ADDR, SOFT_RESET);
|
||||
xgene_enet_wr_mac(pdata->mac_csr_addr, MAC_CONFIG_1_ADDR, 0);
|
||||
xgene_mdio_wr_mac(pdata, MAC_CONFIG_1_ADDR, SOFT_RESET);
|
||||
xgene_mdio_wr_mac(pdata, MAC_CONFIG_1_ADDR, 0);
|
||||
}
|
||||
|
||||
static int xgene_mdio_reset(struct xgene_mdio_pdata *pdata)
|
||||
|
@ -375,6 +372,9 @@ static int xgene_mdio_probe(struct platform_device *pdev)
|
|||
pdata->mdio_csr_addr = csr_base + BLOCK_XG_MDIO_CSR_OFFSET;
|
||||
pdata->diag_csr_addr = csr_base + BLOCK_DIAG_CSR_OFFSET;
|
||||
|
||||
if (mdio_id == XGENE_MDIO_RGMII)
|
||||
spin_lock_init(&pdata->mac_lock);
|
||||
|
||||
if (dev->of_node) {
|
||||
pdata->clk = devm_clk_get(dev, NULL);
|
||||
if (IS_ERR(pdata->clk)) {
|
||||
|
@ -396,7 +396,7 @@ static int xgene_mdio_probe(struct platform_device *pdev)
|
|||
if (mdio_id == XGENE_MDIO_RGMII) {
|
||||
mdio_bus->read = xgene_mdio_rgmii_read;
|
||||
mdio_bus->write = xgene_mdio_rgmii_write;
|
||||
mdio_bus->priv = (void __force *)pdata->mac_csr_addr;
|
||||
mdio_bus->priv = (void __force *)pdata;
|
||||
snprintf(mdio_bus->id, MII_BUS_ID_SIZE, "%s",
|
||||
"xgene-mii-rgmii");
|
||||
} else {
|
||||
|
|
|
@ -102,6 +102,7 @@ struct xgene_mdio_pdata {
|
|||
void __iomem *mdio_csr_addr;
|
||||
struct mii_bus *mdio_bus;
|
||||
int mdio_id;
|
||||
spinlock_t mac_lock; /* mac lock */
|
||||
};
|
||||
|
||||
/* Set the specified value into a bit-field defined by its starting position
|
||||
|
@ -132,6 +133,8 @@ static inline u64 xgene_enet_get_field_value(int pos, int len, u64 src)
|
|||
#define GET_BIT(field, src) \
|
||||
xgene_enet_get_field_value(field ## _POS, 1, src)
|
||||
|
||||
u32 xgene_mdio_rd_mac(struct xgene_mdio_pdata *pdata, u32 rd_addr);
|
||||
void xgene_mdio_wr_mac(struct xgene_mdio_pdata *pdata, u32 wr_addr, u32 data);
|
||||
int xgene_mdio_rgmii_read(struct mii_bus *bus, int phy_id, int reg);
|
||||
int xgene_mdio_rgmii_write(struct mii_bus *bus, int phy_id, int reg, u16 data);
|
||||
struct phy_device *xgene_enet_phy_register(struct mii_bus *bus, int phy_addr);
|
||||
|
|
Загрузка…
Ссылка в новой задаче