net: mv88e61xx: Add support for fixed links
On some boards these switches are wired directly into a SERDES
interface on another Ethernet MAC. Add the ability to specify
these kinds of boards using CONFIG_MV88E61XX_FIXED_PORTS which defines
a bit mask of these fixed ports.
Signed-off-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 7385848..a2fd168 100644
--- a/drivers/net/phy/mv88e61xx.c
+++ b/drivers/net/phy/mv88e61xx.c
@@ -103,8 +103,16 @@
#define PORT_REG_STATUS_CMODE_1000BASE_X 0x9
#define PORT_REG_STATUS_CMODE_SGMII 0xa
+#define PORT_REG_PHYS_CTRL_PCS_AN_EN BIT(10)
+#define PORT_REG_PHYS_CTRL_PCS_AN_RST BIT(9)
+#define PORT_REG_PHYS_CTRL_FC_VALUE BIT(7)
+#define PORT_REG_PHYS_CTRL_FC_FORCE BIT(6)
#define PORT_REG_PHYS_CTRL_LINK_VALUE BIT(5)
#define PORT_REG_PHYS_CTRL_LINK_FORCE BIT(4)
+#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_SPD_MASK (BIT(1) | BIT(0))
#define PORT_REG_CTRL_PSTATE_SHIFT 0
#define PORT_REG_CTRL_PSTATE_WIDTH 2
@@ -166,6 +174,14 @@
#error Define CONFIG_MV88E61XX_CPU_PORT to the port the CPU is attached to
#endif
+/*
+ * These are ports without PHYs that may be wired directly
+ * to other serdes interfaces
+ */
+#ifndef CONFIG_MV88E61XX_FIXED_PORTS
+#define CONFIG_MV88E61XX_FIXED_PORTS 0
+#endif
+
/* ID register values for different switch models */
#define PORT_SWITCH_ID_6096 0x0980
#define PORT_SWITCH_ID_6097 0x0990
@@ -793,6 +809,27 @@
return 0;
}
+static int mv88e61xx_fixed_port_setup(struct phy_device *phydev, u8 port)
+{
+ int val;
+
+ val = mv88e61xx_port_read(phydev, port, PORT_REG_PHYS_CTRL);
+ if (val < 0)
+ 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_DUPLEX_VALUE |
+ PORT_REG_PHYS_CTRL_DUPLEX_FORCE |
+ PORT_REG_PHYS_CTRL_SPD1000;
+
+ return mv88e61xx_port_write(phydev, port, PORT_REG_PHYS_CTRL,
+ val);
+}
+
static int mv88e61xx_phy_config_port(struct phy_device *phydev, u8 phy)
{
int val;
@@ -911,6 +948,12 @@
/* Return success if any PHY succeeds */
ret = 0;
+ } else if ((1 << i) & CONFIG_MV88E61XX_FIXED_PORTS) {
+ res = mv88e61xx_fixed_port_setup(phydev, i);
+ if (res < 0) {
+ printf("Error configuring port %i\n", i);
+ continue;
+ }
}
}