aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/marvell/mvneta.c
diff options
context:
space:
mode:
authorThomas Petazzoni <thomas.petazzoni@free-electrons.com>2014-04-15 09:50:20 -0400
committerDavid S. Miller <davem@davemloft.net>2014-04-16 14:36:12 -0400
commit3f1dd4bcfe2c19a336e01e32a928fcdb8cc43e5c (patch)
treeb1f0e9de7fd4199d88afbf4258564af05bd8c1ac /drivers/net/ethernet/marvell/mvneta.c
parentb9d12085f2f531fdea67f0361564e0812696227c (diff)
net: mvneta: properly configure the MAC <-> PHY connection in all situations
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, some other platforms, namely the Armada XP GP don't use SGMII, but a QSGMII connection between the MAC and the PHY, and this case was not supported by the mvneta driver, which was relying on configuration put in place by the bootloader. While this works when the mvneta driver is built-in (because clocks are not gated), it breaks when mvneta is built as a module, because the clock is gated (all configuration is lost) and then re-enabled when the mvneta driver is loaded. In order to support all of RGMII, SGMII and QSGMII, this commit reworks how the PHY interface configuration is done, and simplifies it: it removes the mvneta_port_sgmii_config() and mvneta_gmac_rgmii_set() functions, which were strange because mvneta_gmac_rgmii_set() was called in all cases, even for SGMII configurations. Also, the mvneta_gmac_rgmii_set() function was taking a boolean as argument, which was always true. Instead, all the PHY interface configuration logic is moved into the mvneta_port_power_up() function, in a much simpler 'switch' construct, with four cases: - QSGMII: the RGMIIEn bit, the PCSEn bit in GMAC_CTRL_2 are set, and the SERDES is configured in QSGMII. Technically speaking, configuring the SERDES of the first port would be sufficient, but it is simpler to do it on all ports. - SGMII: the RGMIIEn bit, the PCSEn bit in GMAC_CTRL_2 are set, and the SERDES is configured as SGMII. - RGMII: the RGMIIEn bit in GMAC_CTRL_2 is set. The PCSEn bit is kept cleared, and no SERDES configuration is done, because RGMII is not using SERDES lanes. - other: an error is returned. For this reason, the mvneta_port_power_up() now returns an int instead of nothing, and the return value is checked by mvneta_probe(). This has been successfully tested on: * Armada XP DB, which has two RGMII and two SGMII connections * Armada XP GP, which uses QSGMII for its four interfaces * Armada 370 Mirabox, which has two RGMII connections Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/marvell/mvneta.c')
-rw-r--r--drivers/net/ethernet/marvell/mvneta.c73
1 files changed, 34 insertions, 39 deletions
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index b248bcbdae63..14786c8bf99e 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -89,8 +89,9 @@
89#define MVNETA_TX_IN_PRGRS BIT(1) 89#define MVNETA_TX_IN_PRGRS BIT(1)
90#define MVNETA_TX_FIFO_EMPTY BIT(8) 90#define MVNETA_TX_FIFO_EMPTY BIT(8)
91#define MVNETA_RX_MIN_FRAME_SIZE 0x247c 91#define MVNETA_RX_MIN_FRAME_SIZE 0x247c
92#define MVNETA_SGMII_SERDES_CFG 0x24A0 92#define MVNETA_SERDES_CFG 0x24A0
93#define MVNETA_SGMII_SERDES_PROTO 0x0cc7 93#define MVNETA_SGMII_SERDES_PROTO 0x0cc7
94#define MVNETA_QSGMII_SERDES_PROTO 0x0667
94#define MVNETA_TYPE_PRIO 0x24bc 95#define MVNETA_TYPE_PRIO 0x24bc
95#define MVNETA_FORCE_UNI BIT(21) 96#define MVNETA_FORCE_UNI BIT(21)
96#define MVNETA_TXQ_CMD_1 0x24e4 97#define MVNETA_TXQ_CMD_1 0x24e4
@@ -711,35 +712,6 @@ static void mvneta_rxq_bm_disable(struct mvneta_port *pp,
711 mvreg_write(pp, MVNETA_RXQ_CONFIG_REG(rxq->id), val); 712 mvreg_write(pp, MVNETA_RXQ_CONFIG_REG(rxq->id), val);
712} 713}
713 714
714
715
716/* Sets the RGMII Enable bit (RGMIIEn) in port MAC control register */
717static void mvneta_gmac_rgmii_set(struct mvneta_port *pp, int enable)
718{
719 u32 val;
720
721 val = mvreg_read(pp, MVNETA_GMAC_CTRL_2);
722
723 if (enable)
724 val |= MVNETA_GMAC2_PORT_RGMII;
725 else
726 val &= ~MVNETA_GMAC2_PORT_RGMII;
727
728 mvreg_write(pp, MVNETA_GMAC_CTRL_2, val);
729}
730
731/* Config SGMII port */
732static void mvneta_port_sgmii_config(struct mvneta_port *pp)
733{
734 u32 val;
735
736 val = mvreg_read(pp, MVNETA_GMAC_CTRL_2);
737 val |= MVNETA_GMAC2_PCS_ENABLE;
738 mvreg_write(pp, MVNETA_GMAC_CTRL_2, val);
739
740 mvreg_write(pp, MVNETA_SGMII_SERDES_CFG, MVNETA_SGMII_SERDES_PROTO);
741}
742
743/* Start the Ethernet port RX and TX activity */ 715/* Start the Ethernet port RX and TX activity */
744static void mvneta_port_up(struct mvneta_port *pp) 716static void mvneta_port_up(struct mvneta_port *pp)
745{ 717{
@@ -2749,26 +2721,44 @@ static void mvneta_conf_mbus_windows(struct mvneta_port *pp,
2749} 2721}
2750 2722
2751/* Power up the port */ 2723/* Power up the port */
2752static void mvneta_port_power_up(struct mvneta_port *pp, int phy_mode) 2724static int mvneta_port_power_up(struct mvneta_port *pp, int phy_mode)
2753{ 2725{
2754 u32 val; 2726 u32 ctrl;
2755 2727
2756 /* MAC Cause register should be cleared */ 2728 /* MAC Cause register should be cleared */
2757 mvreg_write(pp, MVNETA_UNIT_INTR_CAUSE, 0); 2729 mvreg_write(pp, MVNETA_UNIT_INTR_CAUSE, 0);
2758 2730
2759 if (phy_mode == PHY_INTERFACE_MODE_SGMII) 2731 ctrl = mvreg_read(pp, MVNETA_GMAC_CTRL_2);
2760 mvneta_port_sgmii_config(pp);
2761 2732
2762 mvneta_gmac_rgmii_set(pp, 1); 2733 /* Even though it might look weird, when we're configured in
2734 * SGMII or QSGMII mode, the RGMII bit needs to be set.
2735 */
2736 switch(phy_mode) {
2737 case PHY_INTERFACE_MODE_QSGMII:
2738 mvreg_write(pp, MVNETA_SERDES_CFG, MVNETA_QSGMII_SERDES_PROTO);
2739 ctrl |= MVNETA_GMAC2_PCS_ENABLE | MVNETA_GMAC2_PORT_RGMII;
2740 break;
2741 case PHY_INTERFACE_MODE_SGMII:
2742 mvreg_write(pp, MVNETA_SERDES_CFG, MVNETA_SGMII_SERDES_PROTO);
2743 ctrl |= MVNETA_GMAC2_PCS_ENABLE | MVNETA_GMAC2_PORT_RGMII;
2744 break;
2745 case PHY_INTERFACE_MODE_RGMII:
2746 case PHY_INTERFACE_MODE_RGMII_ID:
2747 ctrl |= MVNETA_GMAC2_PORT_RGMII;
2748 break;
2749 default:
2750 return -EINVAL;
2751 }
2763 2752
2764 /* Cancel Port Reset */ 2753 /* Cancel Port Reset */
2765 val = mvreg_read(pp, MVNETA_GMAC_CTRL_2); 2754 ctrl &= ~MVNETA_GMAC2_PORT_RESET;
2766 val &= ~MVNETA_GMAC2_PORT_RESET; 2755 mvreg_write(pp, MVNETA_GMAC_CTRL_2, ctrl);
2767 mvreg_write(pp, MVNETA_GMAC_CTRL_2, val);
2768 2756
2769 while ((mvreg_read(pp, MVNETA_GMAC_CTRL_2) & 2757 while ((mvreg_read(pp, MVNETA_GMAC_CTRL_2) &
2770 MVNETA_GMAC2_PORT_RESET) != 0) 2758 MVNETA_GMAC2_PORT_RESET) != 0)
2771 continue; 2759 continue;
2760
2761 return 0;
2772} 2762}
2773 2763
2774/* Device initialization routine */ 2764/* Device initialization routine */
@@ -2879,7 +2869,12 @@ static int mvneta_probe(struct platform_device *pdev)
2879 dev_err(&pdev->dev, "can't init eth hal\n"); 2869 dev_err(&pdev->dev, "can't init eth hal\n");
2880 goto err_free_stats; 2870 goto err_free_stats;
2881 } 2871 }
2882 mvneta_port_power_up(pp, phy_mode); 2872
2873 err = mvneta_port_power_up(pp, phy_mode);
2874 if (err < 0) {
2875 dev_err(&pdev->dev, "can't power up port\n");
2876 goto err_deinit;
2877 }
2883 2878
2884 dram_target_info = mv_mbus_dram_info(); 2879 dram_target_info = mv_mbus_dram_info();
2885 if (dram_target_info) 2880 if (dram_target_info)