Commit 08a23755 authored by Marcin Wojtas's avatar Marcin Wojtas Committed by David S. Miller

net: mvpp2: Enable proper PHY polling and fix port functionality

Currently, the network interfaces that are not configured by the bootloader
(using e.g. tftp or ping) can detect the link status but are unable to
transmit data.

The network controller has a functionality that allows the hardware to
continuously poll the PHY and directly update the MAC configuration accordingly
(speed, duplex, etc.). However, this doesn't work well with phylib's
software-based polling and updating MAC configuration in the driver's callback.

This commit fixes this issue by:

  1. Setting MVPP2_PHY_AN_STOP_SMI0_MASK in MVPP2_PHY_AN_CFG0_REG in
     mvpp2_init(), which disables the harware polling feature.

  2. Disabling MVPP2_GMAC_PCS_ENABLE_MASK bit in MVPP2_GMAC_CTRL_2_REG in
     mvpp2_port_mii_set() for port types other than SGMII.
Signed-off-by: default avatarMarcin Wojtas <mw@semihalf.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b5c0a800
...@@ -248,6 +248,8 @@ ...@@ -248,6 +248,8 @@
/* LMS registers */ /* LMS registers */
#define MVPP2_SRC_ADDR_MIDDLE 0x24 #define MVPP2_SRC_ADDR_MIDDLE 0x24
#define MVPP2_SRC_ADDR_HIGH 0x28 #define MVPP2_SRC_ADDR_HIGH 0x28
#define MVPP2_PHY_AN_CFG0_REG 0x34
#define MVPP2_PHY_AN_STOP_SMI0_MASK BIT(7)
#define MVPP2_MIB_COUNTERS_BASE(port) (0x1000 + ((port) >> 1) * \ #define MVPP2_MIB_COUNTERS_BASE(port) (0x1000 + ((port) >> 1) * \
0x400 + (port) * 0x400) 0x400 + (port) * 0x400)
#define MVPP2_MIB_LATE_COLLISION 0x7c #define MVPP2_MIB_LATE_COLLISION 0x7c
...@@ -278,6 +280,7 @@ ...@@ -278,6 +280,7 @@
#define MVPP2_GMAC_CONFIG_MII_SPEED BIT(5) #define MVPP2_GMAC_CONFIG_MII_SPEED BIT(5)
#define MVPP2_GMAC_CONFIG_GMII_SPEED BIT(6) #define MVPP2_GMAC_CONFIG_GMII_SPEED BIT(6)
#define MVPP2_GMAC_AN_SPEED_EN BIT(7) #define MVPP2_GMAC_AN_SPEED_EN BIT(7)
#define MVPP2_GMAC_FC_ADV_EN BIT(9)
#define MVPP2_GMAC_CONFIG_FULL_DUPLEX BIT(12) #define MVPP2_GMAC_CONFIG_FULL_DUPLEX BIT(12)
#define MVPP2_GMAC_AN_DUPLEX_EN BIT(13) #define MVPP2_GMAC_AN_DUPLEX_EN BIT(13)
#define MVPP2_GMAC_PORT_FIFO_CFG_1_REG 0x1c #define MVPP2_GMAC_PORT_FIFO_CFG_1_REG 0x1c
...@@ -3809,16 +3812,30 @@ static void mvpp2_interrupts_unmask(void *arg) ...@@ -3809,16 +3812,30 @@ static void mvpp2_interrupts_unmask(void *arg)
static void mvpp2_port_mii_set(struct mvpp2_port *port) static void mvpp2_port_mii_set(struct mvpp2_port *port)
{ {
u32 reg, val = 0; u32 val;
if (port->phy_interface == PHY_INTERFACE_MODE_SGMII) val = readl(port->base + MVPP2_GMAC_CTRL_2_REG);
val = MVPP2_GMAC_PCS_ENABLE_MASK |
MVPP2_GMAC_INBAND_AN_MASK; switch (port->phy_interface) {
else if (port->phy_interface == PHY_INTERFACE_MODE_RGMII) case PHY_INTERFACE_MODE_SGMII:
val = MVPP2_GMAC_PORT_RGMII_MASK; val |= MVPP2_GMAC_INBAND_AN_MASK;
break;
case PHY_INTERFACE_MODE_RGMII:
val |= MVPP2_GMAC_PORT_RGMII_MASK;
default:
val &= ~MVPP2_GMAC_PCS_ENABLE_MASK;
}
writel(val, port->base + MVPP2_GMAC_CTRL_2_REG);
}
static void mvpp2_port_fc_adv_enable(struct mvpp2_port *port)
{
u32 val;
reg = readl(port->base + MVPP2_GMAC_CTRL_2_REG); val = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG);
writel(reg | val, port->base + MVPP2_GMAC_CTRL_2_REG); val |= MVPP2_GMAC_FC_ADV_EN;
writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG);
} }
static void mvpp2_port_enable(struct mvpp2_port *port) static void mvpp2_port_enable(struct mvpp2_port *port)
...@@ -5877,6 +5894,7 @@ static void mvpp2_port_power_up(struct mvpp2_port *port) ...@@ -5877,6 +5894,7 @@ static void mvpp2_port_power_up(struct mvpp2_port *port)
{ {
mvpp2_port_mii_set(port); mvpp2_port_mii_set(port);
mvpp2_port_periodic_xon_disable(port); mvpp2_port_periodic_xon_disable(port);
mvpp2_port_fc_adv_enable(port);
mvpp2_port_reset(port); mvpp2_port_reset(port);
} }
...@@ -6197,6 +6215,7 @@ static int mvpp2_init(struct platform_device *pdev, struct mvpp2 *priv) ...@@ -6197,6 +6215,7 @@ static int mvpp2_init(struct platform_device *pdev, struct mvpp2 *priv)
{ {
const struct mbus_dram_target_info *dram_target_info; const struct mbus_dram_target_info *dram_target_info;
int err, i; int err, i;
u32 val;
/* Checks for hardware constraints */ /* Checks for hardware constraints */
if (rxq_number % 4 || (rxq_number > MVPP2_MAX_RXQ) || if (rxq_number % 4 || (rxq_number > MVPP2_MAX_RXQ) ||
...@@ -6210,6 +6229,11 @@ static int mvpp2_init(struct platform_device *pdev, struct mvpp2 *priv) ...@@ -6210,6 +6229,11 @@ static int mvpp2_init(struct platform_device *pdev, struct mvpp2 *priv)
if (dram_target_info) if (dram_target_info)
mvpp2_conf_mbus_windows(dram_target_info, priv); mvpp2_conf_mbus_windows(dram_target_info, priv);
/* Disable HW PHY polling */
val = readl(priv->lms_base + MVPP2_PHY_AN_CFG0_REG);
val |= MVPP2_PHY_AN_STOP_SMI0_MASK;
writel(val, priv->lms_base + MVPP2_PHY_AN_CFG0_REG);
/* Allocate and initialize aggregated TXQs */ /* Allocate and initialize aggregated TXQs */
priv->aggr_txqs = devm_kcalloc(&pdev->dev, num_present_cpus(), priv->aggr_txqs = devm_kcalloc(&pdev->dev, num_present_cpus(),
sizeof(struct mvpp2_tx_queue), sizeof(struct mvpp2_tx_queue),
......
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