Commit 02e57b9d authored by Giuseppe CAVALLARO's avatar Giuseppe CAVALLARO Committed by David S. Miller

drivers: net: stmmac: add port selection programming

In case of SGMII more, for example when a MAC2MAC connection
is needed, the port selection bits (inside the MAC configuration
registers) have to be programmed according to the link selected.
So the patch adds a new DT parameter to pass the port selection
and to programmed related PCS and CORE to use it.
Signed-off-by: default avatarGiuseppe Cavallaro <peppe.cavallaro@st.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 3fe5cadb
...@@ -47,6 +47,9 @@ Optional properties: ...@@ -47,6 +47,9 @@ Optional properties:
supported by this device instance supported by this device instance
- snps,perfect-filter-entries: Number of perfect filter entries supported - snps,perfect-filter-entries: Number of perfect filter entries supported
by this device instance by this device instance
- snps,ps-speed: port selection speed that can be passed to the core when
PCS is supported. For example, this is used in case of SGMII
and MAC2MAC connection.
- AXI BUS Mode parameters: below the list of all the parameters to program the - AXI BUS Mode parameters: below the list of all the parameters to program the
AXI register inside the DMA module: AXI register inside the DMA module:
- snps,lpi_en: enable Low Power Interface - snps,lpi_en: enable Low Power Interface
......
...@@ -531,6 +531,7 @@ struct mac_device_info { ...@@ -531,6 +531,7 @@ struct mac_device_info {
unsigned int rx_csum; unsigned int rx_csum;
unsigned int pcs; unsigned int pcs;
unsigned int pmt; unsigned int pmt;
unsigned int ps;
}; };
struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr, int mcbins, struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr, int mcbins,
......
...@@ -46,6 +46,21 @@ static void dwmac1000_core_init(struct mac_device_info *hw, int mtu) ...@@ -46,6 +46,21 @@ static void dwmac1000_core_init(struct mac_device_info *hw, int mtu)
if (mtu > 2000) if (mtu > 2000)
value |= GMAC_CONTROL_JE; value |= GMAC_CONTROL_JE;
if (hw->ps) {
value |= GMAC_CONTROL_TE;
if (hw->ps == SPEED_1000) {
value &= ~GMAC_CONTROL_PS;
} else {
value |= GMAC_CONTROL_PS;
if (hw->ps == SPEED_10)
value &= ~GMAC_CONTROL_FES;
else
value |= GMAC_CONTROL_FES;
}
}
writel(value, ioaddr + GMAC_CONTROL); writel(value, ioaddr + GMAC_CONTROL);
/* Mask GMAC interrupts */ /* Mask GMAC interrupts */
......
...@@ -32,6 +32,21 @@ static void dwmac4_core_init(struct mac_device_info *hw, int mtu) ...@@ -32,6 +32,21 @@ static void dwmac4_core_init(struct mac_device_info *hw, int mtu)
if (mtu > 2000) if (mtu > 2000)
value |= GMAC_CONFIG_JE; value |= GMAC_CONFIG_JE;
if (hw->ps) {
value |= GMAC_CONFIG_TE;
if (hw->ps == SPEED_1000) {
value &= ~GMAC_CONFIG_PS;
} else {
value |= GMAC_CONFIG_PS;
if (hw->ps == SPEED_10)
value &= ~GMAC_CONFIG_FES;
else
value |= GMAC_CONFIG_FES;
}
}
writel(value, ioaddr + GMAC_CONFIG); writel(value, ioaddr + GMAC_CONFIG);
/* Mask GMAC interrupts */ /* Mask GMAC interrupts */
......
...@@ -380,7 +380,8 @@ static int stmmac_ethtool_setsettings(struct net_device *dev, ...@@ -380,7 +380,8 @@ static int stmmac_ethtool_setsettings(struct net_device *dev,
spin_lock(&priv->lock); spin_lock(&priv->lock);
if (priv->hw->mac->pcs_ctrl_ane) if (priv->hw->mac->pcs_ctrl_ane)
priv->hw->mac->pcs_ctrl_ane(priv->ioaddr, 1, 0, 0); priv->hw->mac->pcs_ctrl_ane(priv->ioaddr, 1,
priv->hw->ps, 0);
spin_unlock(&priv->lock); spin_unlock(&priv->lock);
......
...@@ -1666,6 +1666,19 @@ static int stmmac_hw_setup(struct net_device *dev, bool init_ptp) ...@@ -1666,6 +1666,19 @@ static int stmmac_hw_setup(struct net_device *dev, bool init_ptp)
if (priv->plat->bus_setup) if (priv->plat->bus_setup)
priv->plat->bus_setup(priv->ioaddr); priv->plat->bus_setup(priv->ioaddr);
/* PS and related bits will be programmed according to the speed */
if (priv->hw->pcs) {
int speed = priv->plat->mac_port_sel_speed;
if ((speed == SPEED_10) || (speed == SPEED_100) ||
(speed == SPEED_1000)) {
priv->hw->ps = speed;
} else {
dev_warn(priv->device, "invalid port speed\n");
priv->hw->ps = 0;
}
}
/* Initialize the MAC Core */ /* Initialize the MAC Core */
priv->hw->mac->core_init(priv->hw, dev->mtu); priv->hw->mac->core_init(priv->hw, dev->mtu);
...@@ -1716,7 +1729,7 @@ static int stmmac_hw_setup(struct net_device *dev, bool init_ptp) ...@@ -1716,7 +1729,7 @@ static int stmmac_hw_setup(struct net_device *dev, bool init_ptp)
} }
if (priv->hw->pcs && priv->hw->mac->pcs_ctrl_ane) if (priv->hw->pcs && priv->hw->mac->pcs_ctrl_ane)
priv->hw->mac->pcs_ctrl_ane(priv->hw, 1, 0, 0); priv->hw->mac->pcs_ctrl_ane(priv->hw, 1, priv->hw->ps, 0);
/* set TX ring length */ /* set TX ring length */
if (priv->hw->dma->set_tx_ring_len) if (priv->hw->dma->set_tx_ring_len)
......
...@@ -319,6 +319,8 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac) ...@@ -319,6 +319,8 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac)
pr_warn("force_sf_dma_mode is ignored if force_thresh_dma_mode is set."); pr_warn("force_sf_dma_mode is ignored if force_thresh_dma_mode is set.");
} }
of_property_read_u32(np, "snps,ps-speed", &plat->mac_port_sel_speed);
plat->axi = stmmac_axi_setup(pdev); plat->axi = stmmac_axi_setup(pdev);
return plat; return plat;
......
...@@ -141,5 +141,6 @@ struct plat_stmmacenet_data { ...@@ -141,5 +141,6 @@ struct plat_stmmacenet_data {
struct stmmac_axi *axi; struct stmmac_axi *axi;
int has_gmac4; int has_gmac4;
bool tso_en; bool tso_en;
int mac_port_sel_speed;
}; };
#endif #endif
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