Commit 3fe5cadb authored by Giuseppe CAVALLARO's avatar Giuseppe CAVALLARO Committed by David S. Miller

drivers: net: stmmac: rework core ISR to better manage PCS and PMT

By default, all gmac cores disable the PCS block and always
enable the PMT.

Note that this is done in a different way by 3.x and 4.x cores.

With this rework, PCS and PMT interrupt masks can be driven by
parameters now moved inside the mac_device_info structure
and the settings follow what the HW capability register reports.
Signed-off-by: default avatarGiuseppe Cavallaro <peppe.cavallaro@st.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 70523e63
...@@ -529,6 +529,8 @@ struct mac_device_info { ...@@ -529,6 +529,8 @@ struct mac_device_info {
int unicast_filter_entries; int unicast_filter_entries;
int mcast_bits_log2; int mcast_bits_log2;
unsigned int rx_csum; unsigned int rx_csum;
unsigned int pcs;
unsigned int pmt;
}; };
struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr, int mcbins, struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr, int mcbins,
......
...@@ -38,16 +38,26 @@ ...@@ -38,16 +38,26 @@
#define GMAC_WAKEUP_FILTER 0x00000028 /* Wake-up Frame Filter */ #define GMAC_WAKEUP_FILTER 0x00000028 /* Wake-up Frame Filter */
#define GMAC_INT_STATUS 0x00000038 /* interrupt status register */ #define GMAC_INT_STATUS 0x00000038 /* interrupt status register */
enum dwmac1000_irq_status { #define GMAC_INT_STATUS_PMT BIT(3)
lpiis_irq = 0x400, #define GMAC_INT_STATUS_MMCIS BIT(4)
time_stamp_irq = 0x0200, #define GMAC_INT_STATUS_MMCRIS BIT(5)
mmc_rx_csum_offload_irq = 0x0080, #define GMAC_INT_STATUS_MMCTIS BIT(6)
mmc_tx_irq = 0x0040, #define GMAC_INT_STATUS_MMCCSUM BIT(7)
mmc_rx_irq = 0x0020, #define GMAC_INT_STATUS_TSTAMP BIT(9)
mmc_irq = 0x0010, #define GMAC_INT_STATUS_LPIIS BIT(10)
pmt_irq = 0x0008,
}; /* interrupt mask register */
#define GMAC_INT_MASK 0x0000003c /* interrupt mask register */ #define GMAC_INT_MASK 0x0000003c
#define GMAC_INT_DISABLE_RGMII BIT(0)
#define GMAC_INT_DISABLE_PCSLINK BIT(1)
#define GMAC_INT_DISABLE_PCSAN BIT(2)
#define GMAC_INT_DISABLE_PMT BIT(3)
#define GMAC_INT_DISABLE_TIMESTAMP BIT(9)
#define GMAC_INT_DISABLE_PCS (GMAC_INT_DISABLE_RGMII | \
GMAC_INT_DISABLE_PCSLINK | \
GMAC_INT_DISABLE_PCSAN)
#define GMAC_INT_DEFAULT_MASK (GMAC_INT_DISABLE_TIMESTAMP | \
GMAC_INT_DISABLE_PCS)
/* PMT Control and Status */ /* PMT Control and Status */
#define GMAC_PMT 0x0000002c #define GMAC_PMT 0x0000002c
......
...@@ -37,7 +37,10 @@ static void dwmac1000_core_init(struct mac_device_info *hw, int mtu) ...@@ -37,7 +37,10 @@ static void dwmac1000_core_init(struct mac_device_info *hw, int mtu)
{ {
void __iomem *ioaddr = hw->pcsr; void __iomem *ioaddr = hw->pcsr;
u32 value = readl(ioaddr + GMAC_CONTROL); u32 value = readl(ioaddr + GMAC_CONTROL);
/* Configure GMAC core */
value |= GMAC_CORE_INIT; value |= GMAC_CORE_INIT;
if (mtu > 1500) if (mtu > 1500)
value |= GMAC_CONTROL_2K; value |= GMAC_CONTROL_2K;
if (mtu > 2000) if (mtu > 2000)
...@@ -46,7 +49,14 @@ static void dwmac1000_core_init(struct mac_device_info *hw, int mtu) ...@@ -46,7 +49,14 @@ static void dwmac1000_core_init(struct mac_device_info *hw, int mtu)
writel(value, ioaddr + GMAC_CONTROL); writel(value, ioaddr + GMAC_CONTROL);
/* Mask GMAC interrupts */ /* Mask GMAC interrupts */
writel(0x207, ioaddr + GMAC_INT_MASK); value = GMAC_INT_DEFAULT_MASK;
if (hw->pmt)
value &= ~GMAC_INT_DISABLE_PMT;
if (hw->pcs)
value &= ~GMAC_INT_DISABLE_PCS;
writel(value, ioaddr + GMAC_INT_MASK);
#ifdef STMMAC_VLAN_TAG_USED #ifdef STMMAC_VLAN_TAG_USED
/* Tag detection without filtering */ /* Tag detection without filtering */
...@@ -283,20 +293,20 @@ static int dwmac1000_irq_status(struct mac_device_info *hw, ...@@ -283,20 +293,20 @@ static int dwmac1000_irq_status(struct mac_device_info *hw,
int ret = 0; int ret = 0;
/* Not used events (e.g. MMC interrupts) are not handled. */ /* Not used events (e.g. MMC interrupts) are not handled. */
if ((intr_status & mmc_tx_irq)) if ((intr_status & GMAC_INT_STATUS_MMCTIS))
x->mmc_tx_irq_n++; x->mmc_tx_irq_n++;
if (unlikely(intr_status & mmc_rx_irq)) if (unlikely(intr_status & GMAC_INT_STATUS_MMCRIS))
x->mmc_rx_irq_n++; x->mmc_rx_irq_n++;
if (unlikely(intr_status & mmc_rx_csum_offload_irq)) if (unlikely(intr_status & GMAC_INT_STATUS_MMCCSUM))
x->mmc_rx_csum_offload_irq_n++; x->mmc_rx_csum_offload_irq_n++;
if (unlikely(intr_status & pmt_irq)) { if (unlikely(intr_status & GMAC_INT_DISABLE_PMT)) {
/* clear the PMT bits 5 and 6 by reading the PMT status reg */ /* clear the PMT bits 5 and 6 by reading the PMT status reg */
readl(ioaddr + GMAC_PMT); readl(ioaddr + GMAC_PMT);
x->irq_receive_pmt_irq_n++; x->irq_receive_pmt_irq_n++;
} }
/* MAC trx/rx EEE LPI entry/exit interrupts */ /* MAC tx/rx EEE LPI entry/exit interrupts */
if (intr_status & lpiis_irq) { if (intr_status & GMAC_INT_STATUS_LPIIS) {
/* Clean LPI interrupt by reading the Reg 12 */ /* Clean LPI interrupt by reading the Reg 12 */
ret = readl(ioaddr + LPI_CTRL_STATUS); ret = readl(ioaddr + LPI_CTRL_STATUS);
......
...@@ -52,9 +52,18 @@ ...@@ -52,9 +52,18 @@
#define GMAC_TX_FLOW_CTRL_PT_SHIFT 16 #define GMAC_TX_FLOW_CTRL_PT_SHIFT 16
/* MAC Interrupt bitmap*/ /* MAC Interrupt bitmap*/
#define GMAC_INT_RGSMIIS BIT(0)
#define GMAC_INT_PCS_LINK BIT(1)
#define GMAC_INT_PCS_ANE BIT(2)
#define GMAC_INT_PCS_PHYIS BIT(3)
#define GMAC_INT_PMT_EN BIT(4) #define GMAC_INT_PMT_EN BIT(4)
#define GMAC_INT_LPI_EN BIT(5) #define GMAC_INT_LPI_EN BIT(5)
#define GMAC_PCS_IRQ_DEFAULT (GMAC_INT_RGSMIIS | GMAC_INT_PCS_LINK | \
GMAC_INT_PCS_ANE)
#define GMAC_INT_DEFAULT_MASK GMAC_INT_PMT_EN
enum dwmac4_irq_status { enum dwmac4_irq_status {
time_stamp_irq = 0x00001000, time_stamp_irq = 0x00001000,
mmc_rx_csum_offload_irq = 0x00000800, mmc_rx_csum_offload_irq = 0x00000800,
......
...@@ -35,7 +35,13 @@ static void dwmac4_core_init(struct mac_device_info *hw, int mtu) ...@@ -35,7 +35,13 @@ static void dwmac4_core_init(struct mac_device_info *hw, int mtu)
writel(value, ioaddr + GMAC_CONFIG); writel(value, ioaddr + GMAC_CONFIG);
/* Mask GMAC interrupts */ /* Mask GMAC interrupts */
writel(GMAC_INT_PMT_EN, ioaddr + GMAC_INT_EN); value = GMAC_INT_DEFAULT_MASK;
if (hw->pmt)
value |= GMAC_INT_PMT_EN;
if (hw->pcs)
value |= GMAC_PCS_IRQ_DEFAULT;
writel(value, ioaddr + GMAC_INT_EN);
} }
static void dwmac4_dump_regs(struct mac_device_info *hw) static void dwmac4_dump_regs(struct mac_device_info *hw)
......
...@@ -117,7 +117,6 @@ struct stmmac_priv { ...@@ -117,7 +117,6 @@ struct stmmac_priv {
int eee_enabled; int eee_enabled;
int eee_active; int eee_active;
int tx_lpi_timer; int tx_lpi_timer;
int pcs;
unsigned int mode; unsigned int mode;
int extend_desc; int extend_desc;
struct ptp_clock *ptp_clock; struct ptp_clock *ptp_clock;
......
...@@ -276,7 +276,8 @@ static int stmmac_ethtool_getsettings(struct net_device *dev, ...@@ -276,7 +276,8 @@ static int stmmac_ethtool_getsettings(struct net_device *dev,
struct phy_device *phy = priv->phydev; struct phy_device *phy = priv->phydev;
int rc; int rc;
if ((priv->pcs & STMMAC_PCS_RGMII) || (priv->pcs & STMMAC_PCS_SGMII)) { if (priv->hw->pcs & STMMAC_PCS_RGMII ||
priv->hw->pcs & STMMAC_PCS_SGMII) {
struct rgmii_adv adv; struct rgmii_adv adv;
if (!priv->xstats.pcs_link) { if (!priv->xstats.pcs_link) {
...@@ -361,7 +362,8 @@ static int stmmac_ethtool_setsettings(struct net_device *dev, ...@@ -361,7 +362,8 @@ static int stmmac_ethtool_setsettings(struct net_device *dev,
struct phy_device *phy = priv->phydev; struct phy_device *phy = priv->phydev;
int rc; int rc;
if ((priv->pcs & STMMAC_PCS_RGMII) || (priv->pcs & STMMAC_PCS_SGMII)) { if (priv->hw->pcs & STMMAC_PCS_RGMII ||
priv->hw->pcs & STMMAC_PCS_SGMII) {
u32 mask = ADVERTISED_Autoneg | ADVERTISED_Pause; u32 mask = ADVERTISED_Autoneg | ADVERTISED_Pause;
/* Only support ANE */ /* Only support ANE */
...@@ -457,7 +459,7 @@ stmmac_get_pauseparam(struct net_device *netdev, ...@@ -457,7 +459,7 @@ stmmac_get_pauseparam(struct net_device *netdev,
pause->rx_pause = 0; pause->rx_pause = 0;
pause->tx_pause = 0; pause->tx_pause = 0;
if (priv->pcs && priv->hw->mac->pcs_get_adv_lp) { if (priv->hw->pcs && priv->hw->mac->pcs_get_adv_lp) {
struct rgmii_adv adv_lp; struct rgmii_adv adv_lp;
pause->autoneg = 1; pause->autoneg = 1;
...@@ -487,7 +489,7 @@ stmmac_set_pauseparam(struct net_device *netdev, ...@@ -487,7 +489,7 @@ stmmac_set_pauseparam(struct net_device *netdev,
struct phy_device *phy = priv->phydev; struct phy_device *phy = priv->phydev;
int new_pause = FLOW_OFF; int new_pause = FLOW_OFF;
if (priv->pcs && priv->hw->mac->pcs_get_adv_lp) { if (priv->hw->pcs && priv->hw->mac->pcs_get_adv_lp) {
struct rgmii_adv adv_lp; struct rgmii_adv adv_lp;
pause->autoneg = 1; pause->autoneg = 1;
...@@ -507,6 +509,7 @@ stmmac_set_pauseparam(struct net_device *netdev, ...@@ -507,6 +509,7 @@ stmmac_set_pauseparam(struct net_device *netdev,
priv->flow_ctrl = new_pause; priv->flow_ctrl = new_pause;
phy->autoneg = pause->autoneg; phy->autoneg = pause->autoneg;
if (phy->autoneg) { if (phy->autoneg) {
if (netif_running(netdev)) if (netif_running(netdev))
return phy_start_aneg(phy); return phy_start_aneg(phy);
......
...@@ -285,8 +285,9 @@ bool stmmac_eee_init(struct stmmac_priv *priv) ...@@ -285,8 +285,9 @@ bool stmmac_eee_init(struct stmmac_priv *priv)
/* Using PCS we cannot dial with the phy registers at this stage /* Using PCS we cannot dial with the phy registers at this stage
* so we do not support extra feature like EEE. * so we do not support extra feature like EEE.
*/ */
if ((priv->pcs == STMMAC_PCS_RGMII) || (priv->pcs == STMMAC_PCS_TBI) || if ((priv->hw->pcs == STMMAC_PCS_RGMII) ||
(priv->pcs == STMMAC_PCS_RTBI)) (priv->hw->pcs == STMMAC_PCS_TBI) ||
(priv->hw->pcs == STMMAC_PCS_RTBI))
goto out; goto out;
/* MAC core supports the EEE feature. */ /* MAC core supports the EEE feature. */
...@@ -799,10 +800,10 @@ static void stmmac_check_pcs_mode(struct stmmac_priv *priv) ...@@ -799,10 +800,10 @@ static void stmmac_check_pcs_mode(struct stmmac_priv *priv)
(interface == PHY_INTERFACE_MODE_RGMII_RXID) || (interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
(interface == PHY_INTERFACE_MODE_RGMII_TXID)) { (interface == PHY_INTERFACE_MODE_RGMII_TXID)) {
pr_debug("STMMAC: PCS RGMII support enable\n"); pr_debug("STMMAC: PCS RGMII support enable\n");
priv->pcs = STMMAC_PCS_RGMII; priv->hw->pcs = STMMAC_PCS_RGMII;
} else if (interface == PHY_INTERFACE_MODE_SGMII) { } else if (interface == PHY_INTERFACE_MODE_SGMII) {
pr_debug("STMMAC: PCS SGMII support enable\n"); pr_debug("STMMAC: PCS SGMII support enable\n");
priv->pcs = STMMAC_PCS_SGMII; priv->hw->pcs = STMMAC_PCS_SGMII;
} }
} }
} }
...@@ -1714,7 +1715,7 @@ static int stmmac_hw_setup(struct net_device *dev, bool init_ptp) ...@@ -1714,7 +1715,7 @@ static int stmmac_hw_setup(struct net_device *dev, bool init_ptp)
priv->hw->dma->rx_watchdog(priv->ioaddr, MAX_DMA_RIWT); priv->hw->dma->rx_watchdog(priv->ioaddr, MAX_DMA_RIWT);
} }
if (priv->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, 0, 0);
/* set TX ring length */ /* set TX ring length */
...@@ -1748,8 +1749,9 @@ static int stmmac_open(struct net_device *dev) ...@@ -1748,8 +1749,9 @@ static int stmmac_open(struct net_device *dev)
stmmac_check_ether_addr(priv); stmmac_check_ether_addr(priv);
if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI && if (priv->hw->pcs != STMMAC_PCS_RGMII &&
priv->pcs != STMMAC_PCS_RTBI) { priv->hw->pcs != STMMAC_PCS_TBI &&
priv->hw->pcs != STMMAC_PCS_RTBI) {
ret = stmmac_init_phy(dev); ret = stmmac_init_phy(dev);
if (ret) { if (ret) {
pr_err("%s: Cannot attach to PHY (error: %d)\n", pr_err("%s: Cannot attach to PHY (error: %d)\n",
...@@ -2811,7 +2813,7 @@ static irqreturn_t stmmac_interrupt(int irq, void *dev_id) ...@@ -2811,7 +2813,7 @@ static irqreturn_t stmmac_interrupt(int irq, void *dev_id)
} }
/* PCS link status */ /* PCS link status */
if (priv->pcs) { if (priv->hw->pcs) {
if (priv->xstats.pcs_link) if (priv->xstats.pcs_link)
netif_carrier_on(dev); netif_carrier_on(dev);
else else
...@@ -3138,6 +3140,7 @@ static int stmmac_hw_init(struct stmmac_priv *priv) ...@@ -3138,6 +3140,7 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
*/ */
priv->plat->enh_desc = priv->dma_cap.enh_desc; priv->plat->enh_desc = priv->dma_cap.enh_desc;
priv->plat->pmt = priv->dma_cap.pmt_remote_wake_up; priv->plat->pmt = priv->dma_cap.pmt_remote_wake_up;
priv->hw->pmt = priv->plat->pmt;
/* TXCOE doesn't work in thresh DMA mode */ /* TXCOE doesn't work in thresh DMA mode */
if (priv->plat->force_thresh_dma_mode) if (priv->plat->force_thresh_dma_mode)
...@@ -3333,8 +3336,9 @@ int stmmac_dvr_probe(struct device *device, ...@@ -3333,8 +3336,9 @@ int stmmac_dvr_probe(struct device *device,
stmmac_check_pcs_mode(priv); stmmac_check_pcs_mode(priv);
if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI && if (priv->hw->pcs != STMMAC_PCS_RGMII &&
priv->pcs != STMMAC_PCS_RTBI) { priv->hw->pcs != STMMAC_PCS_TBI &&
priv->hw->pcs != STMMAC_PCS_RTBI) {
/* MDIO bus Registration */ /* MDIO bus Registration */
ret = stmmac_mdio_register(ndev); ret = stmmac_mdio_register(ndev);
if (ret < 0) { if (ret < 0) {
...@@ -3384,8 +3388,9 @@ int stmmac_dvr_remove(struct device *dev) ...@@ -3384,8 +3388,9 @@ int stmmac_dvr_remove(struct device *dev)
reset_control_assert(priv->stmmac_rst); reset_control_assert(priv->stmmac_rst);
clk_disable_unprepare(priv->pclk); clk_disable_unprepare(priv->pclk);
clk_disable_unprepare(priv->stmmac_clk); clk_disable_unprepare(priv->stmmac_clk);
if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI && if (priv->hw->pcs != STMMAC_PCS_RGMII &&
priv->pcs != STMMAC_PCS_RTBI) priv->hw->pcs != STMMAC_PCS_TBI &&
priv->hw->pcs != STMMAC_PCS_RTBI)
stmmac_mdio_unregister(ndev); stmmac_mdio_unregister(ndev);
free_netdev(ndev); free_netdev(ndev);
......
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