net: phy: mv88e61xx: add CPU port parameter init for 88E6071
authorAnatolij Gustschin <agust@denx.de>
Sat, 26 Oct 2019 23:14:38 +0000 (01:14 +0200)
committerJoe Hershberger <joe.hershberger@ni.com>
Mon, 9 Dec 2019 15:47:42 +0000 (09:47 -0600)
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>
drivers/net/phy/mv88e61xx.c

index 9aba04253c48eb4bd8e58f060ee37ea95d7a694b..63675e4e687607bb3aa15eba6e9f176b1070fc31 100644 (file)
 #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
 #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 @@ struct mv88e61xx_phy_priv {
        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_port_set_vlan(struct phy_device *phydev, u8 port,
 
 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 @@ static int mv88e61xx_read_port_config(struct phy_device *phydev, u8 port)
        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 @@ static int mv88e61xx_read_port_config(struct phy_device *phydev, u8 port)
                                res = -EIO;
                                goto unforce;
                        }
-                       if (val & PORT_REG_STATUS_LINK)
+                       if (val & priv->port_stat_link_mask)
                                break;
                } while (--timeout);
 
@@ -684,13 +685,13 @@ static int mv88e61xx_read_port_config(struct phy_device *phydev, u8 port)
                }
        }
 
-       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 @@ unforce:
 
 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 @@ static int mv88e61xx_fixed_port_setup(struct phy_device *phydev, u8 port)
                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 @@ static int mv88e61xx_probe(struct phy_device *phydev)
        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 @@ static int mv88e61xx_probe(struct phy_device *phydev)
        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);