summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@armlinux.org.uk>2016-12-23 01:09:44 +0000
committerRussell King (Oracle) <rmk+kernel@armlinux.org.uk>2021-06-07 12:48:22 +0100
commit8098317b4fdffa8b82a7e89a8fb76b142c22497b (patch)
tree640802f79b8be2775956854a2963fa7a0621746a
parent685f6193c184ea0593beebd661527dd2d5752173 (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.c108
-rw-r--r--drivers/net/ethernet/marvell/mvgmac.h9
-rw-r--r--drivers/net/ethernet/marvell/mvneta.c1
3 files changed, 108 insertions, 10 deletions
diff --git a/drivers/net/ethernet/marvell/mvgmac.c b/drivers/net/ethernet/marvell/mvgmac.c
index 6c0b7c5c0b24..e776d4e85d3f 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);
+
void mvgmac_link_unforce(struct mvgmac *gmac)
{
u32 val;
@@ -142,7 +210,7 @@ EXPORT_SYMBOL_GPL(mvgmac_link_down);
void mvgmac_link_up(struct mvgmac *gmac, int mode, int speed, int duplex,
bool tx_pause, bool rx_pause)
{
- u32 val;
+ u32 val, ctrl4;
val = readl_relaxed(gmac->base + GMAC_ANEG_REG);
val &= ~GMAC_ANEG_CONFIG_FLOW_CTRL;
@@ -163,8 +231,19 @@ void mvgmac_link_up(struct mvgmac *gmac, int mode, int speed, int duplex,
val |= GMAC_ANEG_FULL_DUPLEX;
}
- if (tx_pause || rx_pause)
- val |= GMAC_ANEG_CONFIG_FLOW_CTRL;
+ switch (gmac->version) {
+ case MVGMAC_NETA:
+ val = insert(val, GMAC_ANEG_CONFIG_FLOW_CTRL,
+ tx_pause || rx_pause);
+ break;
+
+ case MVGMAC_PP22:
+ ctrl4 = readl_relaxed(gmac->base + GMAC_CTRL4_REG);
+ ctrl4 = insert(ctrl4, GMAC_CTRL4_FC_TX_ENABLE, tx_pause);
+ ctrl4 = insert(ctrl4, GMAC_CTRL4_FC_RX_ENABLE, rx_pause);
+ writel_relaxed(ctrl4, gmac->base + GMAC_CTRL4_REG);
+ break;
+ }
writel_relaxed(val, gmac->base + GMAC_ANEG_REG);
}
@@ -252,6 +331,11 @@ int mvgmac_pcs_config(struct mvgmac *gmac, unsigned int mode,
mask |= GMAC_ANEG_ADVERT_SYM_FLOW_CTRL;
if (phylink_test(advertising, Pause))
val |= GMAC_ANEG_ADVERT_SYM_FLOW_CTRL;
+ if (gmac->version == MVGMAC_PP22) {
+ mask |= GMAC_ANEG_ADVERT_ASYM_FLOW_CTRL;
+ if (phylink_test(advertising, Asym_Pause))
+ val |= GMAC_ANEG_ADVERT_ASYM_FLOW_CTRL;
+ }
}
} else {
/* Phy or fixed speed - disable in-band AN modes */
@@ -265,7 +349,8 @@ int mvgmac_pcs_config(struct mvgmac *gmac, unsigned int mode,
writel_relaxed(an, gmac->base + GMAC_ANEG_REG);
/* We are only interested in the advertisement bits changing */
- return !!(changed & GMAC_ANEG_ADVERT_SYM_FLOW_CTRL);
+ return !!(changed & (GMAC_ANEG_ADVERT_SYM_FLOW_CTRL |
+ GMAC_ANEG_ADVERT_ASYM_FLOW_CTRL));
}
EXPORT_SYMBOL_GPL(mvgmac_pcs_config);
@@ -279,7 +364,7 @@ void mvgmac_config_mac(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;
/* Even though it might look weird, when we're configured in
* SGMII or QSGMII mode, the RGMII bit needs to be set.
@@ -303,11 +388,14 @@ void mvgmac_config_mac(struct mvgmac *gmac, unsigned int mode,
new_ctrl0 |= GMAC_CTRL0_PORT_1000BASE_X;
}
- /* When at 2.5G, the link partner can send frames with shortened
- * preambles.
- */
- if (state->interface == PHY_INTERFACE_MODE_2500BASEX)
- new_ctrl4 |= GMAC_CTRL4_SHORT_PREAMBLE_ENABLE;
+ if (gmac->version == MVGMAC_NETA) {
+ /* 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)
+ new_ctrl4 |= GMAC_CTRL4_SHORT_PREAMBLE_ENABLE;
+ }
if (new_ctrl0 != gmac_ctrl0)
writel_relaxed(new_ctrl0, gmac->base + GMAC_CTRL0_REG);
diff --git a/drivers/net/ethernet/marvell/mvgmac.h b/drivers/net/ethernet/marvell/mvgmac.h
index ceccc6777237..f4111fba7258 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_link_unforce(struct mvgmac *gmac);
void mvgmac_link_force_down(struct mvgmac *gmac);
void mvgmac_link_down(struct mvgmac *gmac, int mode);
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index 5331f5a72ab5..b2225166f288 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -5074,6 +5074,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 */