[source] mvsw61xx: enable SerDes on 6176 if required

LEDE Commits lede-commits at lists.infradead.org
Mon Sep 26 04:29:22 PDT 2016


jogo pushed a commit to source.git, branch master:
https://git.lede-project.org/167763837bc4df4d6561e3d1cda86978f0882fc7

commit 167763837bc4df4d6561e3d1cda86978f0882fc7
Author: Jonas Gorski <jonas.gorski at gmail.com>
AuthorDate: Sat Sep 24 21:00:14 2016 +0200

    mvsw61xx: enable SerDes on 6176 if required
    
    If the cpu port is connected through SGMII we need to enable SerDes for
    it to work.
    
    Signed-off-by: Jonas Gorski <jonas.gorski at gmail.com>
    Acked-by: Felix Fietkau <nbd at nbd.name>
---
 .../linux/generic/files/drivers/net/phy/mvsw61xx.c | 46 ++++++++++++++++++++++
 .../linux/generic/files/drivers/net/phy/mvsw61xx.h | 13 ++++++
 2 files changed, 59 insertions(+)

diff --git a/target/linux/generic/files/drivers/net/phy/mvsw61xx.c b/target/linux/generic/files/drivers/net/phy/mvsw61xx.c
index e6074e3..6bd112b 100644
--- a/target/linux/generic/files/drivers/net/phy/mvsw61xx.c
+++ b/target/linux/generic/files/drivers/net/phy/mvsw61xx.c
@@ -173,6 +173,27 @@ mvsw61xx_mdio_write(struct switch_dev *dev, int addr, int reg, u16 val)
 }
 
 static int
+mvsw61xx_mdio_page_read(struct switch_dev *dev, int port, int page, int reg)
+{
+	int ret;
+
+	mvsw61xx_mdio_write(dev, port, MII_MV_PAGE, page);
+	ret = mvsw61xx_mdio_read(dev, port, reg);
+	mvsw61xx_mdio_write(dev, port, MII_MV_PAGE, 0);
+
+	return ret;
+}
+
+static void
+mvsw61xx_mdio_page_write(struct switch_dev *dev, int port, int page, int reg,
+			 u16 val)
+{
+	mvsw61xx_mdio_write(dev, port, MII_MV_PAGE, page);
+	mvsw61xx_mdio_write(dev, port, reg, val);
+	mvsw61xx_mdio_write(dev, port, MII_MV_PAGE, 0);
+}
+
+static int
 mvsw61xx_get_port_mask(struct switch_dev *dev,
 		const struct switch_attr *attr, struct switch_val *val)
 {
@@ -591,6 +612,19 @@ static int mvsw61xx_apply(struct switch_dev *dev)
 	return mvsw61xx_update_state(dev);
 }
 
+static void mvsw61xx_enable_serdes(struct switch_dev *dev)
+{
+	int bmcr = mvsw61xx_mdio_page_read(dev, MV_REG_FIBER_SERDES,
+					   MV_PAGE_FIBER_SERDES, MII_BMCR);
+	if (bmcr < 0)
+		return;
+
+	if (bmcr & BMCR_PDOWN)
+		mvsw61xx_mdio_page_write(dev, MV_REG_FIBER_SERDES,
+					 MV_PAGE_FIBER_SERDES, MII_BMCR,
+					 bmcr & ~BMCR_PDOWN);
+}
+
 static int _mvsw61xx_reset(struct switch_dev *dev, bool full)
 {
 	struct mvsw61xx_state *state = get_state(dev);
@@ -635,6 +669,18 @@ static int _mvsw61xx_reset(struct switch_dev *dev, bool full)
 					    BMCR_ANENABLE | BMCR_FULLDPLX |
 					    BMCR_SPEED1000);
 		}
+
+		/* enable SerDes if necessary */
+		if (full && i >= 5 && state->model == MV_IDENT_VALUE_6176) {
+			u16 sts = sr16(dev, MV_PORTREG(STATUS, i));
+			u16 mode = sts & MV_PORT_STATUS_CMODE_MASK;
+
+			if (mode == MV_PORT_STATUS_CMODE_100BASE_X ||
+			    mode == MV_PORT_STATUS_CMODE_1000BASE_X ||
+			    mode == MV_PORT_STATUS_CMODE_SGMII) {
+				mvsw61xx_enable_serdes(dev);
+			}
+		}
 	}
 
 	for (i = 0; i < dev->vlans; i++) {
diff --git a/target/linux/generic/files/drivers/net/phy/mvsw61xx.h b/target/linux/generic/files/drivers/net/phy/mvsw61xx.h
index 64db6d3..1c45189 100644
--- a/target/linux/generic/files/drivers/net/phy/mvsw61xx.h
+++ b/target/linux/generic/files/drivers/net/phy/mvsw61xx.h
@@ -49,6 +49,14 @@ enum {
 };
 
 enum {
+	MV_PORT_STATUS_CMODE_100BASE_X	= 0x8,
+	MV_PORT_STATUS_CMODE_1000BASE_X	= 0x9,
+	MV_PORT_STATUS_CMODE_SGMII	= 0xa,
+};
+
+#define MV_PORT_STATUS_CMODE_MASK	0xf
+
+enum {
 	MV_PORT_STATUS_SPEED_10		= 0x00,
 	MV_PORT_STATUS_SPEED_100	= 0x01,
 	MV_PORT_STATUS_SPEED_1000	= 0x02,
@@ -239,6 +247,11 @@ enum {
 	MV_SPEC_DOWNSHIFT_COUNTER	= (0x3 << 12),
 };
 
+#define MII_MV_PAGE			22
+
+#define MV_REG_FIBER_SERDES		0xf
+#define MV_PAGE_FIBER_SERDES		0x1
+
 struct mvsw61xx_state {
 	struct switch_dev dev;
 	struct mii_bus *bus;



More information about the lede-commits mailing list