diff mbox

[2/6] net: mvpp2: Enable proper PHY polling and fix port functionality

Message ID 1405961296-5846-3-git-send-email-ezequiel.garcia@free-electrons.com (mailing list archive)
State New, archived
Headers show

Commit Message

Ezequiel Garcia July 21, 2014, 4:48 p.m. UTC
From: Marcin Wojtas <mw@semihalf.com>

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: Marcin Wojtas <mw@semihalf.com>
---
 drivers/net/ethernet/marvell/mvpp2.c | 40 ++++++++++++++++++++++++++++--------
 1 file changed, 32 insertions(+), 8 deletions(-)
diff mbox

Patch

diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
index 8eac438..aa139df 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -248,6 +248,8 @@ 
 /* LMS registers */
 #define MVPP2_SRC_ADDR_MIDDLE			0x24
 #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) * \
 						0x400 + (port) * 0x400)
 #define     MVPP2_MIB_LATE_COLLISION		0x7c
@@ -278,6 +280,7 @@ 
 #define      MVPP2_GMAC_CONFIG_MII_SPEED	BIT(5)
 #define      MVPP2_GMAC_CONFIG_GMII_SPEED	BIT(6)
 #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_AN_DUPLEX_EN		BIT(13)
 #define MVPP2_GMAC_PORT_FIFO_CFG_1_REG		0x1c
@@ -3809,16 +3812,30 @@  static void mvpp2_interrupts_unmask(void *arg)
 
 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 = MVPP2_GMAC_PCS_ENABLE_MASK |
-		      MVPP2_GMAC_INBAND_AN_MASK;
-	else if (port->phy_interface == PHY_INTERFACE_MODE_RGMII)
-		val = MVPP2_GMAC_PORT_RGMII_MASK;
+	val = readl(port->base + MVPP2_GMAC_CTRL_2_REG);
+
+	switch (port->phy_interface) {
+	case PHY_INTERFACE_MODE_SGMII:
+		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);
+}
 
-	reg = readl(port->base + MVPP2_GMAC_CTRL_2_REG);
-	writel(reg | val, port->base + MVPP2_GMAC_CTRL_2_REG);
+static void mvpp2_port_fc_adv_enable(struct mvpp2_port *port)
+{
+	u32 val;
+
+	val = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG);
+	val |= MVPP2_GMAC_FC_ADV_EN;
+	writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG);
 }
 
 static void mvpp2_port_enable(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_periodic_xon_disable(port);
+	mvpp2_port_fc_adv_enable(port);
 	mvpp2_port_reset(port);
 }
 
@@ -6198,6 +6216,7 @@  static int mvpp2_init(struct platform_device *pdev, struct mvpp2 *priv)
 {
 	const struct mbus_dram_target_info *dram_target_info;
 	int err, i;
+	u32 val;
 
 	/* Checks for hardware constraints */
 	if (rxq_number % 4 || (rxq_number > MVPP2_MAX_RXQ) ||
@@ -6211,6 +6230,11 @@  static int mvpp2_init(struct platform_device *pdev, struct mvpp2 *priv)
 	if (dram_target_info)
 		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 */
 	priv->aggr_txqs = devm_kcalloc(&pdev->dev, num_present_cpus(),
 				       sizeof(struct mvpp2_tx_queue),