drivers: net: xgene: Add flow control initialization
This patch adds flow control/pause frame initialization and advertising capabilities. 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:
Родитель
bb64fa09ac
Коммит
56090b1228
|
@ -577,6 +577,17 @@ static void xgene_gmac_init(struct xgene_enet_pdata *pdata)
|
|||
/* Rtype should be copied from FP */
|
||||
xgene_enet_wr_csr(pdata, RSIF_RAM_DBG_REG0_ADDR, 0);
|
||||
|
||||
/* Configure HW pause frame generation */
|
||||
xgene_enet_rd_mcx_csr(pdata, CSR_MULTI_DPF0_ADDR, &value);
|
||||
value = (DEF_QUANTA << 16) | (value & 0xFFFF);
|
||||
xgene_enet_wr_mcx_csr(pdata, CSR_MULTI_DPF0_ADDR, value);
|
||||
|
||||
xgene_enet_wr_csr(pdata, RXBUF_PAUSE_THRESH, DEF_PAUSE_THRES);
|
||||
xgene_enet_wr_csr(pdata, RXBUF_PAUSE_OFF_THRESH, DEF_PAUSE_OFF_THRES);
|
||||
|
||||
xgene_gmac_flowctl_tx(pdata, pdata->tx_pause);
|
||||
xgene_gmac_flowctl_rx(pdata, pdata->rx_pause);
|
||||
|
||||
/* Rx-Tx traffic resume */
|
||||
xgene_enet_wr_csr(pdata, CFG_LINK_AGGR_RESUME_0_ADDR, TX_PORT0);
|
||||
|
||||
|
@ -749,6 +760,48 @@ static void xgene_gport_shutdown(struct xgene_enet_pdata *pdata)
|
|||
}
|
||||
}
|
||||
|
||||
static u32 xgene_enet_flowctrl_cfg(struct net_device *ndev)
|
||||
{
|
||||
struct xgene_enet_pdata *pdata = netdev_priv(ndev);
|
||||
struct phy_device *phydev = ndev->phydev;
|
||||
u16 lcladv, rmtadv = 0;
|
||||
u32 rx_pause, tx_pause;
|
||||
u8 flowctl = 0;
|
||||
|
||||
if (!phydev->duplex || !pdata->pause_autoneg)
|
||||
return 0;
|
||||
|
||||
if (pdata->tx_pause)
|
||||
flowctl |= FLOW_CTRL_TX;
|
||||
|
||||
if (pdata->rx_pause)
|
||||
flowctl |= FLOW_CTRL_RX;
|
||||
|
||||
lcladv = mii_advertise_flowctrl(flowctl);
|
||||
|
||||
if (phydev->pause)
|
||||
rmtadv = LPA_PAUSE_CAP;
|
||||
|
||||
if (phydev->asym_pause)
|
||||
rmtadv |= LPA_PAUSE_ASYM;
|
||||
|
||||
flowctl = mii_resolve_flowctrl_fdx(lcladv, rmtadv);
|
||||
tx_pause = !!(flowctl & FLOW_CTRL_TX);
|
||||
rx_pause = !!(flowctl & FLOW_CTRL_RX);
|
||||
|
||||
if (tx_pause != pdata->tx_pause) {
|
||||
pdata->tx_pause = tx_pause;
|
||||
pdata->mac_ops->flowctl_tx(pdata, pdata->tx_pause);
|
||||
}
|
||||
|
||||
if (rx_pause != pdata->rx_pause) {
|
||||
pdata->rx_pause = rx_pause;
|
||||
pdata->mac_ops->flowctl_rx(pdata, pdata->rx_pause);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void xgene_enet_adjust_link(struct net_device *ndev)
|
||||
{
|
||||
struct xgene_enet_pdata *pdata = netdev_priv(ndev);
|
||||
|
@ -763,6 +816,8 @@ static void xgene_enet_adjust_link(struct net_device *ndev)
|
|||
mac_ops->tx_enable(pdata);
|
||||
phy_print_status(phydev);
|
||||
}
|
||||
|
||||
xgene_enet_flowctrl_cfg(ndev);
|
||||
} else {
|
||||
mac_ops->rx_disable(pdata);
|
||||
mac_ops->tx_disable(pdata);
|
||||
|
@ -836,6 +891,8 @@ int xgene_enet_phy_connect(struct net_device *ndev)
|
|||
phy_dev->supported &= ~SUPPORTED_10baseT_Half &
|
||||
~SUPPORTED_100baseT_Half &
|
||||
~SUPPORTED_1000baseT_Half;
|
||||
phy_dev->supported |= SUPPORTED_Pause |
|
||||
SUPPORTED_Asym_Pause;
|
||||
phy_dev->advertising = phy_dev->supported;
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -172,6 +172,13 @@ enum xgene_enet_rm {
|
|||
#define CFG_CLE_FPSEL0(val) (((val) << 16) & GENMASK(19, 16))
|
||||
#define CSR_ECM_CFG_0_ADDR 0x0220
|
||||
#define CSR_ECM_CFG_1_ADDR 0x0224
|
||||
#define CSR_MULTI_DPF0_ADDR 0x0230
|
||||
#define RXBUF_PAUSE_THRESH 0x0534
|
||||
#define RXBUF_PAUSE_OFF_THRESH 0x0540
|
||||
#define DEF_PAUSE_THRES 0x7d
|
||||
#define DEF_PAUSE_OFF_THRES 0x6d
|
||||
#define DEF_QUANTA 0x8000
|
||||
#define NORM_PAUSE_OPCODE 0x0001
|
||||
#define PAUSE_XON_EN BIT(30)
|
||||
#define MULTI_DPF_AUTOCTRL BIT(28)
|
||||
#define CFG_CLE_NXTFPSEL0(val) (((val) << 20) & GENMASK(23, 20))
|
||||
|
|
|
@ -393,9 +393,11 @@ static void xgene_sgmac_flowctl_rx(struct xgene_enet_pdata *pdata, bool enable)
|
|||
|
||||
static void xgene_sgmac_init(struct xgene_enet_pdata *p)
|
||||
{
|
||||
u32 pause_thres_reg, pause_off_thres_reg;
|
||||
u32 enet_spare_cfg_reg, rsif_config_reg;
|
||||
u32 cfg_bypass_reg, rx_dv_gate_reg;
|
||||
u32 data, offset;
|
||||
u32 data, data1, data2, offset;
|
||||
u32 multi_dpf_reg;
|
||||
|
||||
if (!(p->enet_id == XGENE_ENET2 && p->mdio_driver))
|
||||
xgene_sgmac_reset(p);
|
||||
|
@ -431,6 +433,46 @@ static void xgene_sgmac_init(struct xgene_enet_pdata *p)
|
|||
data |= CFG_RSIF_FPBUFF_TIMEOUT_EN;
|
||||
xgene_enet_wr_csr(p, rsif_config_reg, data);
|
||||
|
||||
/* Configure HW pause frame generation */
|
||||
multi_dpf_reg = (p->enet_id == XGENE_ENET1) ? CSR_MULTI_DPF0_ADDR :
|
||||
XG_MCX_MULTI_DPF0_ADDR;
|
||||
data = xgene_enet_rd_mcx_csr(p, multi_dpf_reg);
|
||||
data = (DEF_QUANTA << 16) | (data & 0xffff);
|
||||
xgene_enet_wr_mcx_csr(p, multi_dpf_reg, data);
|
||||
|
||||
if (p->enet_id != XGENE_ENET1) {
|
||||
data = xgene_enet_rd_mcx_csr(p, XG_MCX_MULTI_DPF1_ADDR);
|
||||
data = (NORM_PAUSE_OPCODE << 16) | (data & 0xFFFF);
|
||||
xgene_enet_wr_mcx_csr(p, XG_MCX_MULTI_DPF1_ADDR, data);
|
||||
}
|
||||
|
||||
pause_thres_reg = (p->enet_id == XGENE_ENET1) ? RXBUF_PAUSE_THRESH :
|
||||
XG_RXBUF_PAUSE_THRESH;
|
||||
pause_off_thres_reg = (p->enet_id == XGENE_ENET1) ?
|
||||
RXBUF_PAUSE_OFF_THRESH : 0;
|
||||
|
||||
if (p->enet_id == XGENE_ENET1) {
|
||||
data1 = xgene_enet_rd_csr(p, pause_thres_reg);
|
||||
data2 = xgene_enet_rd_csr(p, pause_off_thres_reg);
|
||||
|
||||
if (!(p->port_id % 2)) {
|
||||
data1 = (data1 & 0xffff0000) | DEF_PAUSE_THRES;
|
||||
data2 = (data2 & 0xffff0000) | DEF_PAUSE_OFF_THRES;
|
||||
} else {
|
||||
data1 = (data1 & 0xffff) | (DEF_PAUSE_THRES << 16);
|
||||
data2 = (data2 & 0xffff) | (DEF_PAUSE_OFF_THRES << 16);
|
||||
}
|
||||
|
||||
xgene_enet_wr_csr(p, pause_thres_reg, data1);
|
||||
xgene_enet_wr_csr(p, pause_off_thres_reg, data2);
|
||||
} else {
|
||||
data = (DEF_PAUSE_OFF_THRES << 16) | DEF_PAUSE_THRES;
|
||||
xgene_enet_wr_csr(p, pause_thres_reg, data);
|
||||
}
|
||||
|
||||
xgene_sgmac_flowctl_tx(p, p->tx_pause);
|
||||
xgene_sgmac_flowctl_rx(p, p->rx_pause);
|
||||
|
||||
/* Bypass traffic gating */
|
||||
xgene_enet_wr_csr(p, XG_ENET_SPARE_CFG_REG_1_ADDR, 0x84);
|
||||
xgene_enet_wr_csr(p, cfg_bypass_reg, RESUME_TX);
|
||||
|
|
|
@ -349,6 +349,23 @@ static void xgene_xgmac_init(struct xgene_enet_pdata *pdata)
|
|||
xgene_enet_wr_csr(pdata, XG_ENET_SPARE_CFG_REG_1_ADDR, 0x82);
|
||||
xgene_enet_wr_csr(pdata, XGENET_RX_DV_GATE_REG_0_ADDR, 0);
|
||||
xgene_enet_wr_csr(pdata, XG_CFG_BYPASS_ADDR, RESUME_TX);
|
||||
|
||||
/* Configure HW pause frame generation */
|
||||
xgene_enet_rd_axg_csr(pdata, XGENET_CSR_MULTI_DPF0_ADDR, &data);
|
||||
data = (DEF_QUANTA << 16) | (data & 0xFFFF);
|
||||
xgene_enet_wr_axg_csr(pdata, XGENET_CSR_MULTI_DPF0_ADDR, data);
|
||||
|
||||
if (pdata->enet_id != XGENE_ENET1) {
|
||||
xgene_enet_rd_axg_csr(pdata, XGENET_CSR_MULTI_DPF1_ADDR, &data);
|
||||
data = (NORM_PAUSE_OPCODE << 16) | (data & 0xFFFF);
|
||||
xgene_enet_wr_axg_csr(pdata, XGENET_CSR_MULTI_DPF1_ADDR, data);
|
||||
}
|
||||
|
||||
data = (XG_DEF_PAUSE_OFF_THRES << 16) | XG_DEF_PAUSE_THRES;
|
||||
xgene_enet_wr_csr(pdata, XG_RXBUF_PAUSE_THRESH, data);
|
||||
|
||||
xgene_xgmac_flowctl_tx(pdata, pdata->tx_pause);
|
||||
xgene_xgmac_flowctl_rx(pdata, pdata->rx_pause);
|
||||
}
|
||||
|
||||
static void xgene_xgmac_rx_enable(struct xgene_enet_pdata *pdata)
|
||||
|
|
|
@ -60,6 +60,10 @@
|
|||
|
||||
#define XG_MCX_RX_DV_GATE_REG_0_ADDR 0x0004
|
||||
#define XG_MCX_ECM_CFG_0_ADDR 0x0074
|
||||
#define XG_MCX_MULTI_DPF0_ADDR 0x007c
|
||||
#define XG_MCX_MULTI_DPF1_ADDR 0x0080
|
||||
#define XG_DEF_PAUSE_THRES 0x390
|
||||
#define XG_DEF_PAUSE_OFF_THRES 0x2c0
|
||||
#define XG_RSIF_CONFIG_REG_ADDR 0x00a0
|
||||
#define XCLE_BYPASS_REG0_ADDR 0x0160
|
||||
#define XCLE_BYPASS_REG1_ADDR 0x0164
|
||||
|
@ -72,6 +76,9 @@
|
|||
#define XG_ENET_SPARE_CFG_REG_1_ADDR 0x0410
|
||||
#define XGENET_RX_DV_GATE_REG_0_ADDR 0x0804
|
||||
#define XGENET_CSR_ECM_CFG_0_ADDR 0x0880
|
||||
#define XGENET_CSR_MULTI_DPF0_ADDR 0x0888
|
||||
#define XGENET_CSR_MULTI_DPF1_ADDR 0x088c
|
||||
#define XG_RXBUF_PAUSE_THRESH 0x0020
|
||||
#define XG_MCX_ICM_CONFIG0_REG_0_ADDR 0x00e0
|
||||
#define XG_MCX_ICM_CONFIG2_REG_0_ADDR 0x00e8
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче