summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@armlinux.org.uk>2016-12-23 01:09:44 +0000
committerRussell King <rmk+kernel@armlinux.org.uk>2019-07-09 16:42:04 +0100
commitf57e3915150a868b9035a9ccde04da11e748c495 (patch)
treed60862edca28503296edfc7d2b57053b6ab96579
parent1ae3a79c4a842130b25de795e0615d431f129f62 (diff)
net: mvgmac: support different hw versions
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
-rw-r--r--drivers/net/ethernet/marvell/mvgmac.c109
-rw-r--r--drivers/net/ethernet/marvell/mvgmac.h9
-rw-r--r--drivers/net/ethernet/marvell/mvneta.c1
3 files changed, 106 insertions, 13 deletions
diff --git a/drivers/net/ethernet/marvell/mvgmac.c b/drivers/net/ethernet/marvell/mvgmac.c
index 8166ad931702..933c1c627b2d 100644
--- a/drivers/net/ethernet/marvell/mvgmac.c
+++ b/drivers/net/ethernet/marvell/mvgmac.c
@@ -19,6 +19,8 @@
#include "mvgmac.h"
enum {
+ /* N = Neta, 21 = PPV2.1, 22 = PPV2.2 */
+ /* N: 0-14 21: 0,2-15 22: 0-14 */
GMAC_CTRL0_REG = 0x00,
GMAC_CTRL0_PORT_ENABLE = BIT(0),
GMAC_CTRL0_PORT_1000BASE_X = BIT(1),
@@ -26,12 +28,21 @@ enum {
GMAC_CTRL0_MAX_RX_SIZE_MASK = 0x1fff << GMAC_CTRL0_MAX_RX_SIZE_SHIFT,
GMAC_CTRL0_MIB_CNTR_ENABLE = BIT(15),
+ /* N: 21: 1,5,6 22: */
+ GMAC_CTRL1_REG = 0x04,
+ GMAC_CTRL1_PERIODIC_XON_ENABLE = BIT(1),
+ GMAC_CTRL1_GMII_LB_ENABLE = BIT(5),
+ GMAC_CTRL1_PCS_LB_ENABLE = BIT(6),
+
+ /* ALL: 0,3,4,6 */
GMAC_CTRL2_REG = 0x08,
GMAC_CTRL2_INBAND_AN_SGMII = BIT(0),
GMAC_CTRL2_PCS_ENABLE = BIT(3),
GMAC_CTRL2_PORT_RGMII = BIT(4),
GMAC_CTRL2_PORT_RESET = BIT(6),
+ /* N:0-9,11-13 21:0,1,5-7,9,12,13 22:0-7,9-15 */
+ /* 22 bit 2 - EN_PCS_AN */
GMAC_ANEG_REG = 0x0c,
GMAC_ANEG_FORCE_LINK_DOWN = BIT(0),
GMAC_ANEG_FORCE_LINK_PASS = BIT(1),
@@ -43,9 +54,12 @@ enum {
GMAC_ANEG_AN_SPEED_ENABLE = BIT(7),
GMAC_ANEG_CONFIG_FLOW_CTRL = BIT(8),
GMAC_ANEG_ADVERT_SYM_FLOW_CTRL = BIT(9),
+ GMAC_ANEG_ADVERT_ASYM_FLOW_CTRL = BIT(10),
GMAC_ANEG_AN_FLOW_CTRL_ENABLE = BIT(11),
GMAC_ANEG_FULL_DUPLEX = BIT(12),
GMAC_ANEG_AN_DUPLEX_ENABLE = BIT(13),
+ /* pp22: bit 14 - phy mode */
+ /* pp22: bit 15 - choose sample tx config */
GMAC_STATUS_REG = 0x10,
MVGMAC_LINK_UP = BIT(0),
@@ -59,8 +73,21 @@ enum {
MVGMAC_AN_COMPLETE = BIT(11),
MVGMAC_SYNC_OK = BIT(14),
+ /* N: 21:6-13 22: */
+ GMAC_FIFO_CFG1_REG = 0x1c,
+ GMAC_FIFO_CFG1_TX_MIN_TH_SHIFT = 6,
+ GMAC_FIFO_CFG1_TX_MIN_TH_MASK = 0x7f <<
+ GMAC_FIFO_CFG1_TX_MIN_TH_SHIFT,
+
+ /* N:1 21: 22:0,3-7 */
GMAC_CTRL4_REG = 0x90,
+ GMAC_CTRL4_EXT_PIN_GMII_SEL = BIT(0),
GMAC_CTRL4_SHORT_PREAMBLE_ENABLE = BIT(1),
+ GMAC_CTRL4_FC_RX_ENABLE = BIT(3),
+ GMAC_CTRL4_FC_TX_ENABLE = BIT(4),
+ GMAC_CTRL4_DP_CLK_SEL = BIT(5),
+ GMAC_CTRL4_SYNC_BYPASS = BIT(6),
+ GMAC_CTRL4_QSGMII_BYPASS = BIT(7),
GMAC_LPI_CTRL0_REG = 0xc0,
GMAC_LPI_CTRL0_TS = 0xff << 8,
@@ -111,6 +138,47 @@ void mvgmac_disable(struct mvgmac *gmac)
}
EXPORT_SYMBOL_GPL(mvgmac_disable);
+int mvgmac_configure(struct mvgmac *gmac, phy_interface_t phy_mode)
+{
+ bool ext_pin_gmii;
+ u32 val;
+
+ switch (phy_mode) {
+ case PHY_INTERFACE_MODE_QSGMII:
+ case PHY_INTERFACE_MODE_SGMII:
+ ext_pin_gmii = false;
+ break;
+
+ case PHY_INTERFACE_MODE_RGMII:
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+ case PHY_INTERFACE_MODE_RGMII_TXID:
+ ext_pin_gmii = true;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ if (gmac->version == MVGMAC_PP21) {
+ /* Min. TX threshold must be less than minimum packet length */
+ val = readl_relaxed(gmac->base + GMAC_FIFO_CFG1_REG);
+ val = insert(val, GMAC_FIFO_CFG1_TX_MIN_TH_MASK, 64 - 4 - 2);
+ writel_relaxed(val, gmac->base + GMAC_FIFO_CFG1_REG);
+ } else if (gmac->version == MVGMAC_PP22) {
+ val = readl_relaxed(gmac->base + GMAC_CTRL4_REG);
+ val &= ~GMAC_CTRL4_DP_CLK_SEL;
+ val |= GMAC_CTRL4_SYNC_BYPASS;
+ val = insert(val, GMAC_CTRL4_QSGMII_BYPASS,
+ phy_mode != PHY_INTERFACE_MODE_QSGMII);
+ val = insert(val, GMAC_CTRL4_EXT_PIN_GMII_SEL, ext_pin_gmii);
+ writel_relaxed(val, gmac->base + GMAC_CTRL4_REG);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mvgmac_configure);
+
/* Configure port loopback */
void mvgmac_configure_loopback(struct mvgmac *gmac, bool gmii, bool pcs)
{
@@ -196,14 +264,13 @@ void mvgmac_config(struct mvgmac *gmac, unsigned int mode,
new_ctrl0 = gmac_ctrl0 & ~GMAC_CTRL0_PORT_1000BASE_X;
new_ctrl2 = gmac_ctrl2 & ~(GMAC_CTRL2_INBAND_AN_SGMII |
GMAC_CTRL2_PORT_RESET);
- new_ctrl4 = gmac_ctrl4 & ~GMAC_CTRL4_SHORT_PREAMBLE_ENABLE;
+ new_ctrl4 = gmac_ctrl4;
new_an = gmac_an & ~(GMAC_ANEG_INBAND_AN_ENABLE |
GMAC_ANEG_INBAND_RESTART_AN |
GMAC_ANEG_MII_SPEED |
GMAC_ANEG_GMII_SPEED |
GMAC_ANEG_AN_SPEED_ENABLE |
GMAC_ANEG_ADVERT_SYM_FLOW_CTRL |
- GMAC_ANEG_CONFIG_FLOW_CTRL |
GMAC_ANEG_AN_FLOW_CTRL_ENABLE |
GMAC_ANEG_FULL_DUPLEX |
GMAC_ANEG_AN_DUPLEX_ENABLE);
@@ -218,10 +285,8 @@ void mvgmac_config(struct mvgmac *gmac, unsigned int mode,
phy_interface_mode_is_8023z(state->interface))
new_ctrl2 |= GMAC_CTRL2_PCS_ENABLE;
- if (phylink_test(state->advertising, Pause))
- new_an |= GMAC_ANEG_ADVERT_SYM_FLOW_CTRL;
- if (state->pause & MLO_PAUSE_TXRX_MASK)
- new_an |= GMAC_ANEG_CONFIG_FLOW_CTRL;
+ new_an = insert(new_an, GMAC_ANEG_ADVERT_SYM_FLOW_CTRL,
+ !!phylink_test(state->advertising, Pause));
if (!phylink_autoneg_inband(mode)) {
/* Phy or fixed speed */
@@ -255,13 +320,6 @@ void mvgmac_config(struct mvgmac *gmac, unsigned int mode,
new_an |= GMAC_ANEG_AN_FLOW_CTRL_ENABLE;
}
- /* When at 2.5G, the link partner can send frames with shortened
- * preambles.
- */
- if (state->interface == PHY_INTERFACE_MODE_2500BASEX ||
- state->speed == SPEED_2500)
- new_ctrl4 |= GMAC_CTRL4_SHORT_PREAMBLE_ENABLE;
-
/* Armada 370 documentation says we can only change the port mode
* and in-band enable when the link is down, so force it down
* while making these changes. We also do this for GMAC_CTRL2 */
@@ -277,6 +335,31 @@ void mvgmac_config(struct mvgmac *gmac, unsigned int mode,
writel_relaxed(new_ctrl0, gmac->base + GMAC_CTRL0_REG);
if (new_ctrl2 != gmac_ctrl2)
writel_relaxed(new_ctrl2, gmac->base + GMAC_CTRL2_REG);
+
+ switch (gmac->version) {
+ case MVGMAC_NETA:
+ new_an = insert(new_an, GMAC_ANEG_CONFIG_FLOW_CTRL,
+ !!(state->pause & MLO_PAUSE_TXRX_MASK));
+ /* When at 2.5G, the link partner can send frames with
+ * shortened preambles.
+ */
+ new_ctrl4 &= ~GMAC_CTRL4_SHORT_PREAMBLE_ENABLE;
+ if (state->interface == PHY_INTERFACE_MODE_2500BASEX ||
+ state->speed == SPEED_2500)
+ new_ctrl4 |= GMAC_CTRL4_SHORT_PREAMBLE_ENABLE;
+ break;
+
+ case MVGMAC_PP22:
+ new_an = insert(new_an, GMAC_ANEG_ADVERT_ASYM_FLOW_CTRL,
+ !!phylink_test(state->advertising, Asym_Pause));
+
+ new_ctrl4 = insert(new_ctrl4, GMAC_CTRL4_FC_TX_ENABLE,
+ !!(state->pause & MLO_PAUSE_TX));
+ new_ctrl4 = insert(new_ctrl4, GMAC_CTRL4_FC_RX_ENABLE,
+ !!(state->pause & MLO_PAUSE_RX));
+ break;
+ }
+
if (new_ctrl4 != gmac_ctrl4)
writel_relaxed(new_ctrl4, gmac->base + GMAC_CTRL4_REG);
if (new_an != gmac_an)
diff --git a/drivers/net/ethernet/marvell/mvgmac.h b/drivers/net/ethernet/marvell/mvgmac.h
index b67031f50a6c..80ca338d04aa 100644
--- a/drivers/net/ethernet/marvell/mvgmac.h
+++ b/drivers/net/ethernet/marvell/mvgmac.h
@@ -14,13 +14,22 @@ struct phylink_link_state;
*/
#define MARVELL_HEADER_SIZE 2
+enum {
+ /* GMAC version */
+ MVGMAC_NETA,
+ MVGMAC_PP21,
+ MVGMAC_PP22,
+};
+
struct mvgmac {
void __iomem *base;
+ unsigned int version;
};
void mvgmac_set_max_rx_size(struct mvgmac *gmac, size_t max_rx_size);
void mvgmac_enable(struct mvgmac *gmac);
void mvgmac_disable(struct mvgmac *gmac);
+int mvgmac_configure(struct mvgmac *gmac, phy_interface_t phy_mode);
void mvgmac_configure_loopback(struct mvgmac *gmac, bool gmii, bool pcs);
void mvgmac_force_link(struct mvgmac *gmac, bool link_up);
bool mvgmac_link_is_up(struct mvgmac *gmac);
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index bbfa6cafc3e3..7533bbfea107 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -4344,6 +4344,7 @@ static int mvneta_probe(struct platform_device *pdev)
}
pp->gmac.base = pp->base + MVNETA_GMAC_BASE;
+ pp->gmac.version = MVGMAC_NETA;
pp->tx_lpi_timer = 16;
/* Alloc per-cpu port structure */