summaryrefslogtreecommitdiff
path: root/drivers/net/dsa/mv88e6xxx/port.c
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@armlinux.org.uk>2018-08-09 15:38:39 +0200
committerDavid S. Miller <davem@davemloft.net>2018-08-09 11:08:19 -0700
commit6c422e34b1b6533af5730280835365d4b50786d3 (patch)
tree90e8cb7a1b096b46468221ca882dbb26dccc3de8 /drivers/net/dsa/mv88e6xxx/port.c
parent624c0f0239f04cce78c86afa95eb2841c84fbab1 (diff)
net: dsa: mv88e6xxx: add phylink support
Add rudimentary phylink support to mv88e6xxx. TODO: - needs to call phylink_mac_change() when the port link comes up/goes down. Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> Signed-off-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/dsa/mv88e6xxx/port.c')
-rw-r--r--drivers/net/dsa/mv88e6xxx/port.c56
1 files changed, 54 insertions, 2 deletions
diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c
index c0701deaca6a..2ff370cb2f3c 100644
--- a/drivers/net/dsa/mv88e6xxx/port.c
+++ b/drivers/net/dsa/mv88e6xxx/port.c
@@ -388,6 +388,19 @@ int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
return 0;
}
+/* mv88e6185 only has 3 bits for CMODE */
+static int mv88e6185_port_get_cmode(struct mv88e6xxx_chip *chip, int port)
+{
+ int err;
+ u16 reg;
+
+ err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &reg);
+ if (err)
+ return err;
+
+ return reg & MV88E6185_PORT_STS_CMODE_MASK;
+}
+
int mv88e6xxx_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode)
{
int err;
@@ -402,7 +415,7 @@ int mv88e6xxx_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode)
return 0;
}
-int mv88e6xxx_port_link_state(struct mv88e6xxx_chip *chip, int port,
+int mv88e6352_port_link_state(struct mv88e6xxx_chip *chip, int port,
struct phylink_link_state *state)
{
int err;
@@ -423,7 +436,7 @@ int mv88e6xxx_port_link_state(struct mv88e6xxx_chip *chip, int port,
state->speed = SPEED_1000;
break;
case MV88E6XXX_PORT_STS_SPEED_10000:
- if ((reg &MV88E6XXX_PORT_STS_CMODE_MASK) ==
+ if ((reg & MV88E6XXX_PORT_STS_CMODE_MASK) ==
MV88E6XXX_PORT_STS_CMODE_2500BASEX)
state->speed = SPEED_2500;
else
@@ -440,6 +453,45 @@ int mv88e6xxx_port_link_state(struct mv88e6xxx_chip *chip, int port,
return 0;
}
+int mv88e6185_port_link_state(struct mv88e6xxx_chip *chip, int port,
+ struct phylink_link_state *state)
+{
+ if (state->interface == PHY_INTERFACE_MODE_1000BASEX) {
+ int cmode = mv88e6185_port_get_cmode(chip, port);
+
+ if (cmode < 0)
+ return cmode;
+
+ /* When a port is in "Cross-chip serdes" mode, it uses
+ * 1000Base-X full duplex mode, but there is no automatic
+ * link detection. Use the sync OK status for link (as it
+ * would do for 1000Base-X mode.)
+ */
+ if (cmode == MV88E6185_PORT_STS_CMODE_SERDES) {
+ u16 mac;
+ int err;
+
+ err = mv88e6xxx_port_read(chip, port,
+ MV88E6XXX_PORT_MAC_CTL, &mac);
+ if (err)
+ return err;
+
+ state->link = !!(mac & MV88E6185_PORT_MAC_CTL_SYNC_OK);
+ state->an_enabled = 1;
+ state->an_complete =
+ !!(mac & MV88E6185_PORT_MAC_CTL_AN_DONE);
+ state->duplex =
+ state->link ? DUPLEX_FULL : DUPLEX_UNKNOWN;
+ state->speed =
+ state->link ? SPEED_1000 : SPEED_UNKNOWN;
+
+ return 0;
+ }
+ }
+
+ return mv88e6352_port_link_state(chip, port, state);
+}
+
/* Offset 0x02: Jamming Control
*
* Do not limit the period of time that this port can be paused for by