net: phy: mv88e61xx: add CPU port parameter init for 88E6071

On 88E6071 chip the port status register bit field offsets
for duplex and link bits differ. Extend the driver to use
88E6071 specific offset values. The width of bit fields for
speed status differ, too. Adapt for proper port speed
detection on 88E6071.

Signed-off-by: Anatolij Gustschin <agust@denx.de>
Reviewed-by: Chris Packham <judge.packham@gmail.com>
Tested-by: Chris Packham <judge.packham@gmail.com>
Acked-by: Joe Hershberger <joe.hershberger@ni.com>
diff --git a/drivers/net/phy/mv88e61xx.c b/drivers/net/phy/mv88e61xx.c
index 9aba042..63675e4 100644
--- a/drivers/net/phy/mv88e61xx.c
+++ b/drivers/net/phy/mv88e61xx.c
@@ -84,11 +84,7 @@
 #define GLOBAL1_MON_CTRL_CPUDEST_SHIFT	4
 #define GLOBAL1_MON_CTRL_CPUDEST_WIDTH	4
 
-#define PORT_REG_STATUS_LINK		BIT(11)
-#define PORT_REG_STATUS_DUPLEX		BIT(10)
-
 #define PORT_REG_STATUS_SPEED_SHIFT	8
-#define PORT_REG_STATUS_SPEED_WIDTH	2
 #define PORT_REG_STATUS_SPEED_10	0
 #define PORT_REG_STATUS_SPEED_100	1
 #define PORT_REG_STATUS_SPEED_1000	2
@@ -107,6 +103,7 @@
 #define PORT_REG_PHYS_CTRL_DUPLEX_VALUE	BIT(3)
 #define PORT_REG_PHYS_CTRL_DUPLEX_FORCE	BIT(2)
 #define PORT_REG_PHYS_CTRL_SPD1000	BIT(1)
+#define PORT_REG_PHYS_CTRL_SPD100	BIT(0)
 #define PORT_REG_PHYS_CTRL_SPD_MASK	(BIT(1) | BIT(0))
 
 #define PORT_REG_CTRL_PSTATE_SHIFT	0
@@ -196,6 +193,9 @@
 	int id;
 	int port_count;		/* Number of switch ports */
 	int port_reg_base;	/* Base of the switch port registers */
+	u16 port_stat_link_mask;/* Bitmask for port link status bits */
+	u16 port_stat_dup_mask; /* Bitmask for port duplex status bits */
+	u8 port_stat_speed_width;/* Width of speed status bitfield */
 	u8 global1;	/* Offset of Switch Global 1 registers */
 	u8 global2;	/* Offset of Switch Global 2 registers */
 };
@@ -644,6 +644,7 @@
 
 static int mv88e61xx_read_port_config(struct phy_device *phydev, u8 port)
 {
+	struct mv88e61xx_phy_priv *priv = phydev->priv;
 	int res;
 	int val;
 	bool forced = false;
@@ -651,7 +652,7 @@
 	val = mv88e61xx_port_read(phydev, port, PORT_REG_STATUS);
 	if (val < 0)
 		return val;
-	if (!(val & PORT_REG_STATUS_LINK)) {
+	if (!(val & priv->port_stat_link_mask)) {
 		/* Temporarily force link to read port configuration */
 		u32 timeout = 100;
 		forced = true;
@@ -674,7 +675,7 @@
 				res = -EIO;
 				goto unforce;
 			}
-			if (val & PORT_REG_STATUS_LINK)
+			if (val & priv->port_stat_link_mask)
 				break;
 		} while (--timeout);
 
@@ -684,13 +685,13 @@
 		}
 	}
 
-	if (val & PORT_REG_STATUS_DUPLEX)
+	if (val & priv->port_stat_dup_mask)
 		phydev->duplex = DUPLEX_FULL;
 	else
 		phydev->duplex = DUPLEX_HALF;
 
 	val = bitfield_extract(val, PORT_REG_STATUS_SPEED_SHIFT,
-			       PORT_REG_STATUS_SPEED_WIDTH);
+			       priv->port_stat_speed_width);
 	switch (val) {
 	case PORT_REG_STATUS_SPEED_1000:
 		phydev->speed = SPEED_1000;
@@ -723,6 +724,7 @@
 
 static int mv88e61xx_fixed_port_setup(struct phy_device *phydev, u8 port)
 {
+	struct mv88e61xx_phy_priv *priv = phydev->priv;
 	int val;
 
 	val = mv88e61xx_port_read(phydev, port, PORT_REG_PHYS_CTRL);
@@ -730,13 +732,19 @@
 		return val;
 
 	val &= ~(PORT_REG_PHYS_CTRL_SPD_MASK |
-		 PORT_REG_PHYS_CTRL_FC_VALUE);
-	val |= PORT_REG_PHYS_CTRL_PCS_AN_EN |
-	       PORT_REG_PHYS_CTRL_PCS_AN_RST |
-	       PORT_REG_PHYS_CTRL_FC_FORCE |
+		 PORT_REG_PHYS_CTRL_FC_VALUE |
+		 PORT_REG_PHYS_CTRL_FC_FORCE);
+	val |= PORT_REG_PHYS_CTRL_FC_FORCE |
 	       PORT_REG_PHYS_CTRL_DUPLEX_VALUE |
-	       PORT_REG_PHYS_CTRL_DUPLEX_FORCE |
-	       PORT_REG_PHYS_CTRL_SPD1000;
+	       PORT_REG_PHYS_CTRL_DUPLEX_FORCE;
+
+	if (priv->id == PORT_SWITCH_ID_6071) {
+		val |= PORT_REG_PHYS_CTRL_SPD100;
+	} else {
+		val |= PORT_REG_PHYS_CTRL_PCS_AN_EN |
+		       PORT_REG_PHYS_CTRL_PCS_AN_RST |
+		       PORT_REG_PHYS_CTRL_SPD1000;
+	}
 
 	if (port == CONFIG_MV88E61XX_CPU_PORT)
 		val |= PORT_REG_PHYS_CTRL_LINK_VALUE |
@@ -983,6 +991,9 @@
 	case PORT_SWITCH_ID_6240:
 	case PORT_SWITCH_ID_6352:
 		priv->port_count = 11;
+		priv->port_stat_link_mask = BIT(11);
+		priv->port_stat_dup_mask = BIT(10);
+		priv->port_stat_speed_width = 2;
 		break;
 	case PORT_SWITCH_ID_6020:
 	case PORT_SWITCH_ID_6070:
@@ -990,6 +1001,9 @@
 	case PORT_SWITCH_ID_6220:
 	case PORT_SWITCH_ID_6250:
 		priv->port_count = 7;
+		priv->port_stat_link_mask = BIT(12);
+		priv->port_stat_dup_mask = BIT(9);
+		priv->port_stat_speed_width = 1;
 		break;
 	default:
 		free(priv);