Commit 7025e88a authored by WingMan Kwok's avatar WingMan Kwok Committed by David S. Miller

net: netcp: Fixes SGMII reset on network interface shutdown

This patch asserts SGMII RTRESET, i.e. resetting the SGMII Tx/Rx
logic,  during network interface shutdown to avoid having the
hardware wedge when shutting down with high incoming traffic rates.
This is cleared (brought out of RTRESET) when the interface is
brought back up.
Signed-off-by: default avatarWingMan Kwok <w-kwok2@ti.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 54109da3
...@@ -223,6 +223,7 @@ void *netcp_device_find_module(struct netcp_device *netcp_device, ...@@ -223,6 +223,7 @@ void *netcp_device_find_module(struct netcp_device *netcp_device,
/* SGMII functions */ /* SGMII functions */
int netcp_sgmii_reset(void __iomem *sgmii_ofs, int port); int netcp_sgmii_reset(void __iomem *sgmii_ofs, int port);
bool netcp_sgmii_rtreset(void __iomem *sgmii_ofs, int port, bool set);
int netcp_sgmii_get_port_link(void __iomem *sgmii_ofs, int port); int netcp_sgmii_get_port_link(void __iomem *sgmii_ofs, int port);
int netcp_sgmii_config(void __iomem *sgmii_ofs, int port, u32 interface); int netcp_sgmii_config(void __iomem *sgmii_ofs, int port, u32 interface);
......
...@@ -1901,11 +1901,28 @@ static void gbe_port_config(struct gbe_priv *gbe_dev, struct gbe_slave *slave, ...@@ -1901,11 +1901,28 @@ static void gbe_port_config(struct gbe_priv *gbe_dev, struct gbe_slave *slave,
writel(slave->mac_control, GBE_REG_ADDR(slave, emac_regs, mac_control)); writel(slave->mac_control, GBE_REG_ADDR(slave, emac_regs, mac_control));
} }
static void gbe_sgmii_rtreset(struct gbe_priv *priv,
struct gbe_slave *slave, bool set)
{
void __iomem *sgmii_port_regs;
if (SLAVE_LINK_IS_XGMII(slave))
return;
if ((priv->ss_version == GBE_SS_VERSION_14) && (slave->slave_num >= 2))
sgmii_port_regs = priv->sgmii_port34_regs;
else
sgmii_port_regs = priv->sgmii_port_regs;
netcp_sgmii_rtreset(sgmii_port_regs, slave->slave_num, set);
}
static void gbe_slave_stop(struct gbe_intf *intf) static void gbe_slave_stop(struct gbe_intf *intf)
{ {
struct gbe_priv *gbe_dev = intf->gbe_dev; struct gbe_priv *gbe_dev = intf->gbe_dev;
struct gbe_slave *slave = intf->slave; struct gbe_slave *slave = intf->slave;
gbe_sgmii_rtreset(gbe_dev, slave, true);
gbe_port_reset(slave); gbe_port_reset(slave);
/* Disable forwarding */ /* Disable forwarding */
cpsw_ale_control_set(gbe_dev->ale, slave->port_num, cpsw_ale_control_set(gbe_dev->ale, slave->port_num,
...@@ -1947,6 +1964,7 @@ static int gbe_slave_open(struct gbe_intf *gbe_intf) ...@@ -1947,6 +1964,7 @@ static int gbe_slave_open(struct gbe_intf *gbe_intf)
gbe_sgmii_config(priv, slave); gbe_sgmii_config(priv, slave);
gbe_port_reset(slave); gbe_port_reset(slave);
gbe_sgmii_rtreset(priv, slave, false);
gbe_port_config(priv, slave, priv->rx_packet_max); gbe_port_config(priv, slave, priv->rx_packet_max);
gbe_set_slave_mac(slave, gbe_intf); gbe_set_slave_mac(slave, gbe_intf);
/* enable forwarding */ /* enable forwarding */
......
...@@ -18,6 +18,9 @@ ...@@ -18,6 +18,9 @@
#include "netcp.h" #include "netcp.h"
#define SGMII_SRESET_RESET BIT(0)
#define SGMII_SRESET_RTRESET BIT(1)
#define SGMII_REG_STATUS_LOCK BIT(4) #define SGMII_REG_STATUS_LOCK BIT(4)
#define SGMII_REG_STATUS_LINK BIT(0) #define SGMII_REG_STATUS_LINK BIT(0)
#define SGMII_REG_STATUS_AUTONEG BIT(2) #define SGMII_REG_STATUS_AUTONEG BIT(2)
...@@ -51,12 +54,35 @@ static void sgmii_write_reg_bit(void __iomem *base, int reg, u32 val) ...@@ -51,12 +54,35 @@ static void sgmii_write_reg_bit(void __iomem *base, int reg, u32 val)
int netcp_sgmii_reset(void __iomem *sgmii_ofs, int port) int netcp_sgmii_reset(void __iomem *sgmii_ofs, int port)
{ {
/* Soft reset */ /* Soft reset */
sgmii_write_reg_bit(sgmii_ofs, SGMII_SRESET_REG(port), 0x1); sgmii_write_reg_bit(sgmii_ofs, SGMII_SRESET_REG(port),
while (sgmii_read_reg(sgmii_ofs, SGMII_SRESET_REG(port)) != 0x0) SGMII_SRESET_RESET);
while ((sgmii_read_reg(sgmii_ofs, SGMII_SRESET_REG(port)) &
SGMII_SRESET_RESET) != 0x0)
; ;
return 0; return 0;
} }
/* port is 0 based */
bool netcp_sgmii_rtreset(void __iomem *sgmii_ofs, int port, bool set)
{
u32 reg;
bool oldval;
/* Initiate a soft reset */
reg = sgmii_read_reg(sgmii_ofs, SGMII_SRESET_REG(port));
oldval = (reg & SGMII_SRESET_RTRESET) != 0x0;
if (set)
reg |= SGMII_SRESET_RTRESET;
else
reg &= ~SGMII_SRESET_RTRESET;
sgmii_write_reg(sgmii_ofs, SGMII_SRESET_REG(port), reg);
wmb();
return oldval;
}
int netcp_sgmii_get_port_link(void __iomem *sgmii_ofs, int port) int netcp_sgmii_get_port_link(void __iomem *sgmii_ofs, int port)
{ {
u32 status = 0, link = 0; u32 status = 0, link = 0;
......
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