summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2020-06-20 21:38:26 -0700
committerDavid S. Miller <davem@davemloft.net>2020-06-20 21:38:26 -0700
commit29a720c1042f469c8fea317cb5e7f496b116e07d (patch)
tree3a863e7cfea6291e10f6510b57c7521f59c522da
parent8bf1539515920810b86cf1783dc433b1a25d31df (diff)
parent63d78cc9766d5ee18d2e2d82c2642fa414827a77 (diff)
Merge branch 'Marvell-mvpp2-improvements'
Russell King says: ==================== Marvell mvpp2 improvements This series primarily cleans up mvpp2, but also fixes a left-over from 91a208f2185a ("net: phylink: propagate resolved link config via mac_link_up()"). Patch 1 introduces some port helpers: mvpp2_port_supports_xlg() - does the port support the XLG MAC mvpp2_port_supports_rgmii() - does the port support RGMII modes Patch 2 introduces mvpp2_phylink_to_port(), rather than having repeated open coding of container_of(). Patch 3 introduces mvpp2_modify(), which reads-modifies-writes a register - I've converted the phylink specific code to use this helper. Patch 4 moves the hardware control of the pause modes from mvpp2_xlg_config() (which is called via the phylink_config method) to mvpp2_mac_link_up() - a change that was missed in the above referenced commit. v2: remove "inline" in patch 2. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c163
1 files changed, 88 insertions, 75 deletions
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
index e9f287568026..212fc3b54310 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
@@ -1114,6 +1114,17 @@ mvpp2_shared_interrupt_mask_unmask(struct mvpp2_port *port, bool mask)
}
}
+/* Only GOP port 0 has an XLG MAC */
+static bool mvpp2_port_supports_xlg(struct mvpp2_port *port)
+{
+ return port->gop_id == 0;
+}
+
+static bool mvpp2_port_supports_rgmii(struct mvpp2_port *port)
+{
+ return !(port->priv->hw_version == MVPP22 && port->gop_id == 0);
+}
+
/* Port configuration routines */
static bool mvpp2_is_xlg(phy_interface_t interface)
{
@@ -1121,6 +1132,17 @@ static bool mvpp2_is_xlg(phy_interface_t interface)
interface == PHY_INTERFACE_MODE_XAUI;
}
+static void mvpp2_modify(void __iomem *ptr, u32 mask, u32 set)
+{
+ u32 old, val;
+
+ old = val = readl(ptr);
+ val &= ~mask;
+ val |= set;
+ if (old != val)
+ writel(val, ptr);
+}
+
static void mvpp22_gop_init_rgmii(struct mvpp2_port *port)
{
struct mvpp2 *priv = port->priv;
@@ -1194,7 +1216,7 @@ static int mvpp22_gop_init(struct mvpp2_port *port)
case PHY_INTERFACE_MODE_RGMII_ID:
case PHY_INTERFACE_MODE_RGMII_RXID:
case PHY_INTERFACE_MODE_RGMII_TXID:
- if (port->gop_id == 0)
+ if (!mvpp2_port_supports_rgmii(port))
goto invalid_conf;
mvpp22_gop_init_rgmii(port);
break;
@@ -1204,7 +1226,7 @@ static int mvpp22_gop_init(struct mvpp2_port *port)
mvpp22_gop_init_sgmii(port);
break;
case PHY_INTERFACE_MODE_10GBASER:
- if (port->gop_id != 0)
+ if (!mvpp2_port_supports_xlg(port))
goto invalid_conf;
mvpp22_gop_init_10gkr(port);
break;
@@ -1246,7 +1268,7 @@ static void mvpp22_gop_unmask_irq(struct mvpp2_port *port)
writel(val, port->base + MVPP22_GMAC_INT_SUM_MASK);
}
- if (port->gop_id == 0) {
+ if (mvpp2_port_supports_xlg(port)) {
/* Enable the XLG/GIG irqs for this port */
val = readl(port->base + MVPP22_XLG_EXT_INT_MASK);
if (mvpp2_is_xlg(port->phy_interface))
@@ -1261,7 +1283,7 @@ static void mvpp22_gop_mask_irq(struct mvpp2_port *port)
{
u32 val;
- if (port->gop_id == 0) {
+ if (mvpp2_port_supports_xlg(port)) {
val = readl(port->base + MVPP22_XLG_EXT_INT_MASK);
val &= ~(MVPP22_XLG_EXT_INT_MASK_XLG |
MVPP22_XLG_EXT_INT_MASK_GIG);
@@ -1290,7 +1312,7 @@ static void mvpp22_gop_setup_irq(struct mvpp2_port *port)
writel(val, port->base + MVPP22_GMAC_INT_MASK);
}
- if (port->gop_id == 0) {
+ if (mvpp2_port_supports_xlg(port)) {
val = readl(port->base + MVPP22_XLG_INT_MASK);
val |= MVPP22_XLG_INT_MASK_LINK;
writel(val, port->base + MVPP22_XLG_INT_MASK);
@@ -1328,8 +1350,8 @@ static void mvpp2_port_enable(struct mvpp2_port *port)
{
u32 val;
- /* Only GOP port 0 has an XLG MAC */
- if (port->gop_id == 0 && mvpp2_is_xlg(port->phy_interface)) {
+ if (mvpp2_port_supports_xlg(port) &&
+ mvpp2_is_xlg(port->phy_interface)) {
val = readl(port->base + MVPP22_XLG_CTRL0_REG);
val |= MVPP22_XLG_CTRL0_PORT_EN;
val &= ~MVPP22_XLG_CTRL0_MIB_CNT_DIS;
@@ -1346,8 +1368,8 @@ static void mvpp2_port_disable(struct mvpp2_port *port)
{
u32 val;
- /* Only GOP port 0 has an XLG MAC */
- if (port->gop_id == 0 && mvpp2_is_xlg(port->phy_interface)) {
+ if (mvpp2_port_supports_xlg(port) &&
+ mvpp2_is_xlg(port->phy_interface)) {
val = readl(port->base + MVPP22_XLG_CTRL0_REG);
val &= ~MVPP22_XLG_CTRL0_PORT_EN;
writel(val, port->base + MVPP22_XLG_CTRL0_REG);
@@ -2740,7 +2762,8 @@ static irqreturn_t mvpp2_link_status_isr(int irq, void *dev_id)
mvpp22_gop_mask_irq(port);
- if (port->gop_id == 0 && mvpp2_is_xlg(port->phy_interface)) {
+ if (mvpp2_port_supports_xlg(port) &&
+ mvpp2_is_xlg(port->phy_interface)) {
val = readl(port->base + MVPP22_XLG_INT_STAT);
if (val & MVPP22_XLG_INT_STAT_LINK) {
event = true;
@@ -3430,8 +3453,7 @@ static void mvpp22_mode_reconfigure(struct mvpp2_port *port)
mvpp22_pcs_reset_deassert(port);
- /* Only GOP port 0 has an XLG MAC */
- if (port->gop_id == 0) {
+ if (mvpp2_port_supports_xlg(port)) {
ctrl3 = readl(port->base + MVPP22_XLG_CTRL3_REG);
ctrl3 &= ~MVPP22_XLG_CTRL3_MACMODESELECT_MASK;
@@ -3443,7 +3465,7 @@ static void mvpp22_mode_reconfigure(struct mvpp2_port *port)
writel(ctrl3, port->base + MVPP22_XLG_CTRL3_REG);
}
- if (port->gop_id == 0 && mvpp2_is_xlg(port->phy_interface))
+ if (mvpp2_port_supports_xlg(port) && mvpp2_is_xlg(port->phy_interface))
mvpp2_xlg_max_rx_size_set(port);
else
mvpp2_gmac_max_rx_size_set(port);
@@ -4756,26 +4778,30 @@ static void mvpp2_port_copy_mac_addr(struct net_device *dev, struct mvpp2 *priv,
eth_hw_addr_random(dev);
}
+static struct mvpp2_port *mvpp2_phylink_to_port(struct phylink_config *config)
+{
+ return container_of(config, struct mvpp2_port, phylink_config);
+}
+
static void mvpp2_phylink_validate(struct phylink_config *config,
unsigned long *supported,
struct phylink_link_state *state)
{
- struct mvpp2_port *port = container_of(config, struct mvpp2_port,
- phylink_config);
+ struct mvpp2_port *port = mvpp2_phylink_to_port(config);
__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
/* Invalid combinations */
switch (state->interface) {
case PHY_INTERFACE_MODE_10GBASER:
case PHY_INTERFACE_MODE_XAUI:
- if (port->gop_id != 0)
+ if (!mvpp2_port_supports_xlg(port))
goto empty_set;
break;
case PHY_INTERFACE_MODE_RGMII:
case PHY_INTERFACE_MODE_RGMII_ID:
case PHY_INTERFACE_MODE_RGMII_RXID:
case PHY_INTERFACE_MODE_RGMII_TXID:
- if (port->priv->hw_version == MVPP22 && port->gop_id == 0)
+ if (!mvpp2_port_supports_rgmii(port))
goto empty_set;
break;
default:
@@ -4791,7 +4817,7 @@ static void mvpp2_phylink_validate(struct phylink_config *config,
case PHY_INTERFACE_MODE_10GBASER:
case PHY_INTERFACE_MODE_XAUI:
case PHY_INTERFACE_MODE_NA:
- if (port->gop_id == 0) {
+ if (mvpp2_port_supports_xlg(port)) {
phylink_set(mask, 10000baseT_Full);
phylink_set(mask, 10000baseCR_Full);
phylink_set(mask, 10000baseSR_Full);
@@ -4902,8 +4928,7 @@ static void mvpp2_gmac_pcs_get_state(struct mvpp2_port *port,
static void mvpp2_phylink_mac_pcs_get_state(struct phylink_config *config,
struct phylink_link_state *state)
{
- struct mvpp2_port *port = container_of(config, struct mvpp2_port,
- phylink_config);
+ struct mvpp2_port *port = mvpp2_phylink_to_port(config);
if (port->priv->hw_version == MVPP22 && port->gop_id == 0) {
u32 mode = readl(port->base + MVPP22_XLG_CTRL3_REG);
@@ -4920,8 +4945,7 @@ static void mvpp2_phylink_mac_pcs_get_state(struct phylink_config *config,
static void mvpp2_mac_an_restart(struct phylink_config *config)
{
- struct mvpp2_port *port = container_of(config, struct mvpp2_port,
- phylink_config);
+ struct mvpp2_port *port = mvpp2_phylink_to_port(config);
u32 val = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG);
writel(val | MVPP2_GMAC_IN_BAND_RESTART_AN,
@@ -4933,38 +4957,21 @@ static void mvpp2_mac_an_restart(struct phylink_config *config)
static void mvpp2_xlg_config(struct mvpp2_port *port, unsigned int mode,
const struct phylink_link_state *state)
{
- u32 old_ctrl0, ctrl0;
- u32 old_ctrl4, ctrl4;
-
- old_ctrl0 = ctrl0 = readl(port->base + MVPP22_XLG_CTRL0_REG);
- old_ctrl4 = ctrl4 = readl(port->base + MVPP22_XLG_CTRL4_REG);
-
- ctrl0 |= MVPP22_XLG_CTRL0_MAC_RESET_DIS;
-
- if (state->pause & MLO_PAUSE_TX)
- ctrl0 |= MVPP22_XLG_CTRL0_TX_FLOW_CTRL_EN;
- else
- ctrl0 &= ~MVPP22_XLG_CTRL0_TX_FLOW_CTRL_EN;
-
- if (state->pause & MLO_PAUSE_RX)
- ctrl0 |= MVPP22_XLG_CTRL0_RX_FLOW_CTRL_EN;
- else
- ctrl0 &= ~MVPP22_XLG_CTRL0_RX_FLOW_CTRL_EN;
-
- ctrl4 &= ~(MVPP22_XLG_CTRL4_MACMODSELECT_GMAC |
- MVPP22_XLG_CTRL4_EN_IDLE_CHECK);
- ctrl4 |= MVPP22_XLG_CTRL4_FWD_FC | MVPP22_XLG_CTRL4_FWD_PFC;
+ u32 val;
- if (old_ctrl0 != ctrl0)
- writel(ctrl0, port->base + MVPP22_XLG_CTRL0_REG);
- if (old_ctrl4 != ctrl4)
- writel(ctrl4, port->base + MVPP22_XLG_CTRL4_REG);
+ mvpp2_modify(port->base + MVPP22_XLG_CTRL0_REG,
+ MVPP22_XLG_CTRL0_MAC_RESET_DIS,
+ MVPP22_XLG_CTRL0_MAC_RESET_DIS);
+ mvpp2_modify(port->base + MVPP22_XLG_CTRL4_REG,
+ MVPP22_XLG_CTRL4_MACMODSELECT_GMAC |
+ MVPP22_XLG_CTRL4_EN_IDLE_CHECK |
+ MVPP22_XLG_CTRL4_FWD_FC | MVPP22_XLG_CTRL4_FWD_PFC,
+ MVPP22_XLG_CTRL4_FWD_FC | MVPP22_XLG_CTRL4_FWD_PFC);
- if (!(old_ctrl0 & MVPP22_XLG_CTRL0_MAC_RESET_DIS)) {
- while (!(readl(port->base + MVPP22_XLG_CTRL0_REG) &
- MVPP22_XLG_CTRL0_MAC_RESET_DIS))
- continue;
- }
+ /* Wait for reset to deassert */
+ do {
+ val = readl(port->base + MVPP22_XLG_CTRL0_REG);
+ } while (!(val & MVPP22_XLG_CTRL0_MAC_RESET_DIS));
}
static void mvpp2_gmac_config(struct mvpp2_port *port, unsigned int mode,
@@ -5094,13 +5101,12 @@ static void mvpp2_gmac_config(struct mvpp2_port *port, unsigned int mode,
static void mvpp2_mac_config(struct phylink_config *config, unsigned int mode,
const struct phylink_link_state *state)
{
- struct net_device *dev = to_net_dev(config->dev);
- struct mvpp2_port *port = netdev_priv(dev);
+ struct mvpp2_port *port = mvpp2_phylink_to_port(config);
bool change_interface = port->phy_interface != state->interface;
/* Check for invalid configuration */
if (mvpp2_is_xlg(state->interface) && port->gop_id != 0) {
- netdev_err(dev, "Invalid mode on %s\n", dev->name);
+ netdev_err(port->dev, "Invalid mode on %s\n", port->dev->name);
return;
}
@@ -5140,25 +5146,26 @@ static void mvpp2_mac_link_up(struct phylink_config *config,
int speed, int duplex,
bool tx_pause, bool rx_pause)
{
- struct net_device *dev = to_net_dev(config->dev);
- struct mvpp2_port *port = netdev_priv(dev);
+ struct mvpp2_port *port = mvpp2_phylink_to_port(config);
u32 val;
if (mvpp2_is_xlg(interface)) {
if (!phylink_autoneg_inband(mode)) {
- val = readl(port->base + MVPP22_XLG_CTRL0_REG);
- val &= ~MVPP22_XLG_CTRL0_FORCE_LINK_DOWN;
- val |= MVPP22_XLG_CTRL0_FORCE_LINK_PASS;
- writel(val, port->base + MVPP22_XLG_CTRL0_REG);
+ val = MVPP22_XLG_CTRL0_FORCE_LINK_PASS;
+ if (tx_pause)
+ val |= MVPP22_XLG_CTRL0_TX_FLOW_CTRL_EN;
+ if (rx_pause)
+ val |= MVPP22_XLG_CTRL0_RX_FLOW_CTRL_EN;
+
+ mvpp2_modify(port->base + MVPP22_XLG_CTRL0_REG,
+ MVPP22_XLG_CTRL0_FORCE_LINK_DOWN |
+ MVPP22_XLG_CTRL0_FORCE_LINK_PASS |
+ MVPP22_XLG_CTRL0_TX_FLOW_CTRL_EN |
+ MVPP22_XLG_CTRL0_RX_FLOW_CTRL_EN, val);
}
} else {
if (!phylink_autoneg_inband(mode)) {
- val = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG);
- val &= ~(MVPP2_GMAC_FORCE_LINK_DOWN |
- MVPP2_GMAC_CONFIG_MII_SPEED |
- MVPP2_GMAC_CONFIG_GMII_SPEED |
- MVPP2_GMAC_CONFIG_FULL_DUPLEX);
- val |= MVPP2_GMAC_FORCE_LINK_PASS;
+ val = MVPP2_GMAC_FORCE_LINK_PASS;
if (speed == SPEED_1000 || speed == SPEED_2500)
val |= MVPP2_GMAC_CONFIG_GMII_SPEED;
@@ -5168,34 +5175,40 @@ static void mvpp2_mac_link_up(struct phylink_config *config,
if (duplex == DUPLEX_FULL)
val |= MVPP2_GMAC_CONFIG_FULL_DUPLEX;
- writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG);
+ mvpp2_modify(port->base + MVPP2_GMAC_AUTONEG_CONFIG,
+ MVPP2_GMAC_FORCE_LINK_DOWN |
+ MVPP2_GMAC_FORCE_LINK_PASS |
+ MVPP2_GMAC_CONFIG_MII_SPEED |
+ MVPP2_GMAC_CONFIG_GMII_SPEED |
+ MVPP2_GMAC_CONFIG_FULL_DUPLEX, val);
}
/* We can always update the flow control enable bits;
* these will only be effective if flow control AN
* (MVPP2_GMAC_FLOW_CTRL_AUTONEG) is disabled.
*/
- val = readl(port->base + MVPP22_GMAC_CTRL_4_REG);
- val &= ~(MVPP22_CTRL4_RX_FC_EN | MVPP22_CTRL4_TX_FC_EN);
+ val = 0;
if (tx_pause)
val |= MVPP22_CTRL4_TX_FC_EN;
if (rx_pause)
val |= MVPP22_CTRL4_RX_FC_EN;
- writel(val, port->base + MVPP22_GMAC_CTRL_4_REG);
+
+ mvpp2_modify(port->base + MVPP22_GMAC_CTRL_4_REG,
+ MVPP22_CTRL4_RX_FC_EN | MVPP22_CTRL4_TX_FC_EN,
+ val);
}
mvpp2_port_enable(port);
mvpp2_egress_enable(port);
mvpp2_ingress_enable(port);
- netif_tx_wake_all_queues(dev);
+ netif_tx_wake_all_queues(port->dev);
}
static void mvpp2_mac_link_down(struct phylink_config *config,
unsigned int mode, phy_interface_t interface)
{
- struct net_device *dev = to_net_dev(config->dev);
- struct mvpp2_port *port = netdev_priv(dev);
+ struct mvpp2_port *port = mvpp2_phylink_to_port(config);
u32 val;
if (!phylink_autoneg_inband(mode)) {
@@ -5212,7 +5225,7 @@ static void mvpp2_mac_link_down(struct phylink_config *config,
}
}
- netif_tx_stop_all_queues(dev);
+ netif_tx_stop_all_queues(port->dev);
mvpp2_egress_disable(port);
mvpp2_ingress_disable(port);