aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Petazzoni <thomas.petazzoni@free-electrons.com>2014-03-25 19:25:42 -0400
committerDavid S. Miller <davem@davemloft.net>2014-03-26 16:52:41 -0400
commite3a8786c10e75903f1269474e21fe8cb49c3a670 (patch)
treeb4e84134707f4e7a64a0e0685543d8b5103901de
parenta79121d3b57e7ad61f0b5d23eae05214054f3ccd (diff)
net: mvneta: fix usage as a module on RGMII configurations
Commit 5445eaf309ff ('mvneta: Try to fix mvneta when compiled as module') fixed the mvneta driver to make it work properly when loaded as a module in SGMII configuration, which was tested successful by the author on the Armada XP OpenBlocks AX3, which uses SGMII. However, it turns out that the Armada XP GP, which uses RGMII, is affected by a similar problem: its SERDES configuration is lost when mvneta is loaded as a module, because this configuration is set by the bootloader, and then lost because the clock is gated by the clock framework until the mvneta driver is loaded again and the clock is re-enabled. However, it turns out that for the RGMII case, setting the SERDES configuration is not sufficient: the PCS enable bit in the MVNETA_GMAC_CTRL_2 register must also be set, like in the SGMII configuration. Therefore, this commit reworks the SGMII/RGMII initialization: the only difference between the two now is a different SERDES configuration, all the rest is identical. In detail, to achieve this, the commit: * Renames MVNETA_SGMII_SERDES_CFG to MVNETA_SERDES_CFG because it is not specific to SGMII, but also used on RGMII configurations. * Adds a MVNETA_RGMII_SERDES_PROTO definition, that must be used as the MVNETA_SERDES_CFG value in RGMII configurations. * Removes the mvneta_gmac_rgmii_set() and mvneta_port_sgmii_config() functions, and instead directly do the SGMII/RGMII configuration in mvneta_port_up(), from where those functions where called. It is worth mentioning that mvneta_gmac_rgmii_set() had an 'enable' parameter that was always passed as '1', so it was pretty useless. * Reworks the mvneta_port_up() function to set the MVNETA_SERDES_CFG register to the appropriate value depending on the RGMII vs. SGMII configuration. It also unconditionally set the PCS_ENABLE bit (was already done for SGMII, but is now also needed for RGMII), and sets the PORT_RGMII bit (which was already done for both SGMII and RGMII). This commit was successfully tested with mvneta compiled as a module, on both the OpenBlocks AX3 (SGMII configuration) and the Armada XP GP (RGMII configuration). Reported-by: Steve McIntyre <steve@einval.com> Cc: stable@vger.kernel.org # 3.11.x: 5445eaf309ff mvneta: Try to fix mvneta when compiled as module Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/marvell/mvneta.c41
1 files changed, 8 insertions, 33 deletions
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index d6b04d0238fa..c9c2faaf967e 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -88,8 +88,9 @@
88#define MVNETA_TX_IN_PRGRS BIT(1) 88#define MVNETA_TX_IN_PRGRS BIT(1)
89#define MVNETA_TX_FIFO_EMPTY BIT(8) 89#define MVNETA_TX_FIFO_EMPTY BIT(8)
90#define MVNETA_RX_MIN_FRAME_SIZE 0x247c 90#define MVNETA_RX_MIN_FRAME_SIZE 0x247c
91#define MVNETA_SGMII_SERDES_CFG 0x24A0 91#define MVNETA_SERDES_CFG 0x24A0
92#define MVNETA_SGMII_SERDES_PROTO 0x0cc7 92#define MVNETA_SGMII_SERDES_PROTO 0x0cc7
93#define MVNETA_RGMII_SERDES_PROTO 0x0667
93#define MVNETA_TYPE_PRIO 0x24bc 94#define MVNETA_TYPE_PRIO 0x24bc
94#define MVNETA_FORCE_UNI BIT(21) 95#define MVNETA_FORCE_UNI BIT(21)
95#define MVNETA_TXQ_CMD_1 0x24e4 96#define MVNETA_TXQ_CMD_1 0x24e4
@@ -710,35 +711,6 @@ static void mvneta_rxq_bm_disable(struct mvneta_port *pp,
710 mvreg_write(pp, MVNETA_RXQ_CONFIG_REG(rxq->id), val); 711 mvreg_write(pp, MVNETA_RXQ_CONFIG_REG(rxq->id), val);
711} 712}
712 713
713
714
715/* Sets the RGMII Enable bit (RGMIIEn) in port MAC control register */
716static void mvneta_gmac_rgmii_set(struct mvneta_port *pp, int enable)
717{
718 u32 val;
719
720 val = mvreg_read(pp, MVNETA_GMAC_CTRL_2);
721
722 if (enable)
723 val |= MVNETA_GMAC2_PORT_RGMII;
724 else
725 val &= ~MVNETA_GMAC2_PORT_RGMII;
726
727 mvreg_write(pp, MVNETA_GMAC_CTRL_2, val);
728}
729
730/* Config SGMII port */
731static void mvneta_port_sgmii_config(struct mvneta_port *pp)
732{
733 u32 val;
734
735 val = mvreg_read(pp, MVNETA_GMAC_CTRL_2);
736 val |= MVNETA_GMAC2_PCS_ENABLE;
737 mvreg_write(pp, MVNETA_GMAC_CTRL_2, val);
738
739 mvreg_write(pp, MVNETA_SGMII_SERDES_CFG, MVNETA_SGMII_SERDES_PROTO);
740}
741
742/* Start the Ethernet port RX and TX activity */ 714/* Start the Ethernet port RX and TX activity */
743static void mvneta_port_up(struct mvneta_port *pp) 715static void mvneta_port_up(struct mvneta_port *pp)
744{ 716{
@@ -2756,12 +2728,15 @@ static void mvneta_port_power_up(struct mvneta_port *pp, int phy_mode)
2756 mvreg_write(pp, MVNETA_UNIT_INTR_CAUSE, 0); 2728 mvreg_write(pp, MVNETA_UNIT_INTR_CAUSE, 0);
2757 2729
2758 if (phy_mode == PHY_INTERFACE_MODE_SGMII) 2730 if (phy_mode == PHY_INTERFACE_MODE_SGMII)
2759 mvneta_port_sgmii_config(pp); 2731 mvreg_write(pp, MVNETA_SERDES_CFG, MVNETA_SGMII_SERDES_PROTO);
2732 else
2733 mvreg_write(pp, MVNETA_SERDES_CFG, MVNETA_RGMII_SERDES_PROTO);
2760 2734
2761 mvneta_gmac_rgmii_set(pp, 1); 2735 val = mvreg_read(pp, MVNETA_GMAC_CTRL_2);
2736
2737 val |= MVNETA_GMAC2_PCS_ENABLE | MVNETA_GMAC2_PORT_RGMII;
2762 2738
2763 /* Cancel Port Reset */ 2739 /* Cancel Port Reset */
2764 val = mvreg_read(pp, MVNETA_GMAC_CTRL_2);
2765 val &= ~MVNETA_GMAC2_PORT_RESET; 2740 val &= ~MVNETA_GMAC2_PORT_RESET;
2766 mvreg_write(pp, MVNETA_GMAC_CTRL_2, val); 2741 mvreg_write(pp, MVNETA_GMAC_CTRL_2, val);
2767 2742