aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcin Wojtas <mw@semihalf.com>2014-07-21 12:48:12 -0400
committerDavid S. Miller <davem@davemloft.net>2014-07-22 22:50:30 -0400
commit08a23755080f590c577ecedb5a444e55daeb258c (patch)
tree0a1eca64b56a8ce9ec59e2eda782cc2be13c0ffd
parentb5c0a8009094d37c73649867c6d7d332a0d4fb4c (diff)
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: Marcin Wojtas <mw@semihalf.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/marvell/mvpp2.c40
1 files changed, 32 insertions, 8 deletions
diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
index ed32f97496d3..ebb63d80ad51 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -248,6 +248,8 @@
248/* LMS registers */ 248/* LMS registers */
249#define MVPP2_SRC_ADDR_MIDDLE 0x24 249#define MVPP2_SRC_ADDR_MIDDLE 0x24
250#define MVPP2_SRC_ADDR_HIGH 0x28 250#define MVPP2_SRC_ADDR_HIGH 0x28
251#define MVPP2_PHY_AN_CFG0_REG 0x34
252#define MVPP2_PHY_AN_STOP_SMI0_MASK BIT(7)
251#define MVPP2_MIB_COUNTERS_BASE(port) (0x1000 + ((port) >> 1) * \ 253#define MVPP2_MIB_COUNTERS_BASE(port) (0x1000 + ((port) >> 1) * \
252 0x400 + (port) * 0x400) 254 0x400 + (port) * 0x400)
253#define MVPP2_MIB_LATE_COLLISION 0x7c 255#define MVPP2_MIB_LATE_COLLISION 0x7c
@@ -278,6 +280,7 @@
278#define MVPP2_GMAC_CONFIG_MII_SPEED BIT(5) 280#define MVPP2_GMAC_CONFIG_MII_SPEED BIT(5)
279#define MVPP2_GMAC_CONFIG_GMII_SPEED BIT(6) 281#define MVPP2_GMAC_CONFIG_GMII_SPEED BIT(6)
280#define MVPP2_GMAC_AN_SPEED_EN BIT(7) 282#define MVPP2_GMAC_AN_SPEED_EN BIT(7)
283#define MVPP2_GMAC_FC_ADV_EN BIT(9)
281#define MVPP2_GMAC_CONFIG_FULL_DUPLEX BIT(12) 284#define MVPP2_GMAC_CONFIG_FULL_DUPLEX BIT(12)
282#define MVPP2_GMAC_AN_DUPLEX_EN BIT(13) 285#define MVPP2_GMAC_AN_DUPLEX_EN BIT(13)
283#define MVPP2_GMAC_PORT_FIFO_CFG_1_REG 0x1c 286#define MVPP2_GMAC_PORT_FIFO_CFG_1_REG 0x1c
@@ -3809,16 +3812,30 @@ static void mvpp2_interrupts_unmask(void *arg)
3809 3812
3810static void mvpp2_port_mii_set(struct mvpp2_port *port) 3813static void mvpp2_port_mii_set(struct mvpp2_port *port)
3811{ 3814{
3812 u32 reg, val = 0; 3815 u32 val;
3813 3816
3814 if (port->phy_interface == PHY_INTERFACE_MODE_SGMII) 3817 val = readl(port->base + MVPP2_GMAC_CTRL_2_REG);
3815 val = MVPP2_GMAC_PCS_ENABLE_MASK | 3818
3816 MVPP2_GMAC_INBAND_AN_MASK; 3819 switch (port->phy_interface) {
3817 else if (port->phy_interface == PHY_INTERFACE_MODE_RGMII) 3820 case PHY_INTERFACE_MODE_SGMII:
3818 val = MVPP2_GMAC_PORT_RGMII_MASK; 3821 val |= MVPP2_GMAC_INBAND_AN_MASK;
3822 break;
3823 case PHY_INTERFACE_MODE_RGMII:
3824 val |= MVPP2_GMAC_PORT_RGMII_MASK;
3825 default:
3826 val &= ~MVPP2_GMAC_PCS_ENABLE_MASK;
3827 }
3828
3829 writel(val, port->base + MVPP2_GMAC_CTRL_2_REG);
3830}
3819 3831
3820 reg = readl(port->base + MVPP2_GMAC_CTRL_2_REG); 3832static void mvpp2_port_fc_adv_enable(struct mvpp2_port *port)
3821 writel(reg | val, port->base + MVPP2_GMAC_CTRL_2_REG); 3833{
3834 u32 val;
3835
3836 val = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG);
3837 val |= MVPP2_GMAC_FC_ADV_EN;
3838 writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG);
3822} 3839}
3823 3840
3824static void mvpp2_port_enable(struct mvpp2_port *port) 3841static void mvpp2_port_enable(struct mvpp2_port *port)
@@ -5877,6 +5894,7 @@ static void mvpp2_port_power_up(struct mvpp2_port *port)
5877{ 5894{
5878 mvpp2_port_mii_set(port); 5895 mvpp2_port_mii_set(port);
5879 mvpp2_port_periodic_xon_disable(port); 5896 mvpp2_port_periodic_xon_disable(port);
5897 mvpp2_port_fc_adv_enable(port);
5880 mvpp2_port_reset(port); 5898 mvpp2_port_reset(port);
5881} 5899}
5882 5900
@@ -6197,6 +6215,7 @@ static int mvpp2_init(struct platform_device *pdev, struct mvpp2 *priv)
6197{ 6215{
6198 const struct mbus_dram_target_info *dram_target_info; 6216 const struct mbus_dram_target_info *dram_target_info;
6199 int err, i; 6217 int err, i;
6218 u32 val;
6200 6219
6201 /* Checks for hardware constraints */ 6220 /* Checks for hardware constraints */
6202 if (rxq_number % 4 || (rxq_number > MVPP2_MAX_RXQ) || 6221 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 if (dram_target_info) 6229 if (dram_target_info)
6211 mvpp2_conf_mbus_windows(dram_target_info, priv); 6230 mvpp2_conf_mbus_windows(dram_target_info, priv);
6212 6231
6232 /* Disable HW PHY polling */
6233 val = readl(priv->lms_base + MVPP2_PHY_AN_CFG0_REG);
6234 val |= MVPP2_PHY_AN_STOP_SMI0_MASK;
6235 writel(val, priv->lms_base + MVPP2_PHY_AN_CFG0_REG);
6236
6213 /* Allocate and initialize aggregated TXQs */ 6237 /* Allocate and initialize aggregated TXQs */
6214 priv->aggr_txqs = devm_kcalloc(&pdev->dev, num_present_cpus(), 6238 priv->aggr_txqs = devm_kcalloc(&pdev->dev, num_present_cpus(),
6215 sizeof(struct mvpp2_tx_queue), 6239 sizeof(struct mvpp2_tx_queue),