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>
This commit is contained in:
commit
29a720c104
@ -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;
|
||||
u32 val;
|
||||
|
||||
old_ctrl0 = ctrl0 = readl(port->base + MVPP22_XLG_CTRL0_REG);
|
||||
old_ctrl4 = ctrl4 = readl(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);
|
||||
|
||||
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;
|
||||
|
||||
if (old_ctrl0 != ctrl0)
|
||||
writel(ctrl0, port->base + MVPP22_XLG_CTRL0_REG);
|
||||
if (old_ctrl4 != ctrl4)
|
||||
writel(ctrl4, port->base + MVPP22_XLG_CTRL4_REG);
|
||||
|
||||
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);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user