summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorAnatolij Gustschin <agust@denx.de>2019-10-27 01:14:38 +0200
committerJoe Hershberger <joe.hershberger@ni.com>2019-12-09 09:47:42 -0600
commit4aa05f6cf3e893ba2394d81e586400872e3303c1 (patch)
tree45c3236d1f39db0f559c87f45f2d9ff447964a71 /drivers
parentf41a722baa9fab4eb6843eca51f0318ad104f145 (diff)
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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/phy/mv88e61xx.c42
1 files changed, 28 insertions, 14 deletions
diff --git a/drivers/net/phy/mv88e61xx.c b/drivers/net/phy/mv88e61xx.c
index 9aba04253c..63675e4e68 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 @@ 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);