Commit f365c6f7 authored by Russell King's avatar Russell King Committed by David S. Miller

net: dsa: mv88e6xxx: combine port_set_speed and port_set_duplex

Setting the speed independently of duplex makes little sense; the two
parameters result from negotiation or fixed setup, and may have inter-
dependencies. Moreover, they are always controlled via the same
register - having them split means we have to read-modify-write this
register twice.

Combine the two operations into a single port_set_speed_duplex()
operation. Not only is this more efficient, it reduces the size of the
code as well.
Signed-off-by: default avatarRussell King <rmk+kernel@armlinux.org.uk>
Reviewed-by: default avatarAndrew Lunn <andrew@lunn.ch>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7e0e6243
This diff is collapsed.
...@@ -399,15 +399,6 @@ struct mv88e6xxx_ops { ...@@ -399,15 +399,6 @@ struct mv88e6xxx_ops {
*/ */
int (*port_set_link)(struct mv88e6xxx_chip *chip, int port, int link); int (*port_set_link)(struct mv88e6xxx_chip *chip, int port, int link);
#define DUPLEX_UNFORCED -2
/* Port's MAC duplex mode
*
* Use DUPLEX_HALF or DUPLEX_FULL to force half or full duplex,
* or DUPLEX_UNFORCED for normal duplex detection.
*/
int (*port_set_duplex)(struct mv88e6xxx_chip *chip, int port, int dup);
#define PAUSE_ON 1 #define PAUSE_ON 1
#define PAUSE_OFF 0 #define PAUSE_OFF 0
...@@ -417,13 +408,18 @@ struct mv88e6xxx_ops { ...@@ -417,13 +408,18 @@ struct mv88e6xxx_ops {
#define SPEED_MAX INT_MAX #define SPEED_MAX INT_MAX
#define SPEED_UNFORCED -2 #define SPEED_UNFORCED -2
#define DUPLEX_UNFORCED -2
/* Port's MAC speed (in Mbps) /* Port's MAC speed (in Mbps) and MAC duplex mode
* *
* Depending on the chip, 10, 100, 200, 1000, 2500, 10000 are valid. * Depending on the chip, 10, 100, 200, 1000, 2500, 10000 are valid.
* Use SPEED_UNFORCED for normal detection, SPEED_MAX for max value. * Use SPEED_UNFORCED for normal detection, SPEED_MAX for max value.
*
* Use DUPLEX_HALF or DUPLEX_FULL to force half or full duplex,
* or DUPLEX_UNFORCED for normal duplex detection.
*/ */
int (*port_set_speed)(struct mv88e6xxx_chip *chip, int port, int speed); int (*port_set_speed_duplex)(struct mv88e6xxx_chip *chip, int port,
int speed, int duplex);
/* What interface mode should be used for maximum speed? */ /* What interface mode should be used for maximum speed? */
phy_interface_t (*port_max_speed_mode)(int port); phy_interface_t (*port_max_speed_mode)(int port);
......
...@@ -162,46 +162,9 @@ int mv88e6xxx_port_set_link(struct mv88e6xxx_chip *chip, int port, int link) ...@@ -162,46 +162,9 @@ int mv88e6xxx_port_set_link(struct mv88e6xxx_chip *chip, int port, int link)
return 0; return 0;
} }
int mv88e6xxx_port_set_duplex(struct mv88e6xxx_chip *chip, int port, int dup) static int mv88e6xxx_port_set_speed_duplex(struct mv88e6xxx_chip *chip,
{ int port, int speed, bool alt_bit,
u16 reg; bool force_bit, int duplex)
int err;
err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_MAC_CTL, &reg);
if (err)
return err;
reg &= ~(MV88E6XXX_PORT_MAC_CTL_FORCE_DUPLEX |
MV88E6XXX_PORT_MAC_CTL_DUPLEX_FULL);
switch (dup) {
case DUPLEX_HALF:
reg |= MV88E6XXX_PORT_MAC_CTL_FORCE_DUPLEX;
break;
case DUPLEX_FULL:
reg |= MV88E6XXX_PORT_MAC_CTL_FORCE_DUPLEX |
MV88E6XXX_PORT_MAC_CTL_DUPLEX_FULL;
break;
case DUPLEX_UNFORCED:
/* normal duplex detection */
break;
default:
return -EOPNOTSUPP;
}
err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_MAC_CTL, reg);
if (err)
return err;
dev_dbg(chip->dev, "p%d: %s %s duplex\n", port,
reg & MV88E6XXX_PORT_MAC_CTL_FORCE_DUPLEX ? "Force" : "Unforce",
reg & MV88E6XXX_PORT_MAC_CTL_DUPLEX_FULL ? "full" : "half");
return 0;
}
static int mv88e6xxx_port_set_speed(struct mv88e6xxx_chip *chip, int port,
int speed, bool alt_bit, bool force_bit)
{ {
u16 reg, ctrl; u16 reg, ctrl;
int err; int err;
...@@ -239,11 +202,29 @@ static int mv88e6xxx_port_set_speed(struct mv88e6xxx_chip *chip, int port, ...@@ -239,11 +202,29 @@ static int mv88e6xxx_port_set_speed(struct mv88e6xxx_chip *chip, int port,
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
switch (duplex) {
case DUPLEX_HALF:
ctrl |= MV88E6XXX_PORT_MAC_CTL_FORCE_DUPLEX;
break;
case DUPLEX_FULL:
ctrl |= MV88E6XXX_PORT_MAC_CTL_FORCE_DUPLEX |
MV88E6XXX_PORT_MAC_CTL_DUPLEX_FULL;
break;
case DUPLEX_UNFORCED:
/* normal duplex detection */
break;
default:
return -EOPNOTSUPP;
}
err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_MAC_CTL, &reg); err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_MAC_CTL, &reg);
if (err) if (err)
return err; return err;
reg &= ~MV88E6XXX_PORT_MAC_CTL_SPEED_MASK; reg &= ~(MV88E6XXX_PORT_MAC_CTL_SPEED_MASK |
MV88E6XXX_PORT_MAC_CTL_FORCE_DUPLEX |
MV88E6XXX_PORT_MAC_CTL_DUPLEX_FULL);
if (alt_bit) if (alt_bit)
reg &= ~MV88E6390_PORT_MAC_CTL_ALTSPEED; reg &= ~MV88E6390_PORT_MAC_CTL_ALTSPEED;
if (force_bit) { if (force_bit) {
...@@ -261,12 +242,16 @@ static int mv88e6xxx_port_set_speed(struct mv88e6xxx_chip *chip, int port, ...@@ -261,12 +242,16 @@ static int mv88e6xxx_port_set_speed(struct mv88e6xxx_chip *chip, int port,
dev_dbg(chip->dev, "p%d: Speed set to %d Mbps\n", port, speed); dev_dbg(chip->dev, "p%d: Speed set to %d Mbps\n", port, speed);
else else
dev_dbg(chip->dev, "p%d: Speed unforced\n", port); dev_dbg(chip->dev, "p%d: Speed unforced\n", port);
dev_dbg(chip->dev, "p%d: %s %s duplex\n", port,
reg & MV88E6XXX_PORT_MAC_CTL_FORCE_DUPLEX ? "Force" : "Unforce",
reg & MV88E6XXX_PORT_MAC_CTL_DUPLEX_FULL ? "full" : "half");
return 0; return 0;
} }
/* Support 10, 100, 200 Mbps (e.g. 88E6065 family) */ /* Support 10, 100, 200 Mbps (e.g. 88E6065 family) */
int mv88e6065_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed) int mv88e6065_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,
int speed, int duplex)
{ {
if (speed == SPEED_MAX) if (speed == SPEED_MAX)
speed = 200; speed = 200;
...@@ -275,11 +260,13 @@ int mv88e6065_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed) ...@@ -275,11 +260,13 @@ int mv88e6065_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
return -EOPNOTSUPP; return -EOPNOTSUPP;
/* Setting 200 Mbps on port 0 to 3 selects 100 Mbps */ /* Setting 200 Mbps on port 0 to 3 selects 100 Mbps */
return mv88e6xxx_port_set_speed(chip, port, speed, false, false); return mv88e6xxx_port_set_speed_duplex(chip, port, speed, false, false,
duplex);
} }
/* Support 10, 100, 1000 Mbps (e.g. 88E6185 family) */ /* Support 10, 100, 1000 Mbps (e.g. 88E6185 family) */
int mv88e6185_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed) int mv88e6185_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,
int speed, int duplex)
{ {
if (speed == SPEED_MAX) if (speed == SPEED_MAX)
speed = 1000; speed = 1000;
...@@ -287,11 +274,13 @@ int mv88e6185_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed) ...@@ -287,11 +274,13 @@ int mv88e6185_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
if (speed == 200 || speed > 1000) if (speed == 200 || speed > 1000)
return -EOPNOTSUPP; return -EOPNOTSUPP;
return mv88e6xxx_port_set_speed(chip, port, speed, false, false); return mv88e6xxx_port_set_speed_duplex(chip, port, speed, false, false,
duplex);
} }
/* Support 10, 100 Mbps (e.g. 88E6250 family) */ /* Support 10, 100 Mbps (e.g. 88E6250 family) */
int mv88e6250_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed) int mv88e6250_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,
int speed, int duplex)
{ {
if (speed == SPEED_MAX) if (speed == SPEED_MAX)
speed = 100; speed = 100;
...@@ -299,11 +288,13 @@ int mv88e6250_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed) ...@@ -299,11 +288,13 @@ int mv88e6250_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
if (speed > 100) if (speed > 100)
return -EOPNOTSUPP; return -EOPNOTSUPP;
return mv88e6xxx_port_set_speed(chip, port, speed, false, false); return mv88e6xxx_port_set_speed_duplex(chip, port, speed, false, false,
duplex);
} }
/* Support 10, 100, 200, 1000, 2500 Mbps (e.g. 88E6341) */ /* Support 10, 100, 200, 1000, 2500 Mbps (e.g. 88E6341) */
int mv88e6341_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed) int mv88e6341_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,
int speed, int duplex)
{ {
if (speed == SPEED_MAX) if (speed == SPEED_MAX)
speed = port < 5 ? 1000 : 2500; speed = port < 5 ? 1000 : 2500;
...@@ -317,7 +308,8 @@ int mv88e6341_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed) ...@@ -317,7 +308,8 @@ int mv88e6341_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
if (speed == 2500 && port < 5) if (speed == 2500 && port < 5)
return -EOPNOTSUPP; return -EOPNOTSUPP;
return mv88e6xxx_port_set_speed(chip, port, speed, !port, true); return mv88e6xxx_port_set_speed_duplex(chip, port, speed, !port, true,
duplex);
} }
phy_interface_t mv88e6341_port_max_speed_mode(int port) phy_interface_t mv88e6341_port_max_speed_mode(int port)
...@@ -329,7 +321,8 @@ phy_interface_t mv88e6341_port_max_speed_mode(int port) ...@@ -329,7 +321,8 @@ phy_interface_t mv88e6341_port_max_speed_mode(int port)
} }
/* Support 10, 100, 200, 1000 Mbps (e.g. 88E6352 family) */ /* Support 10, 100, 200, 1000 Mbps (e.g. 88E6352 family) */
int mv88e6352_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed) int mv88e6352_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,
int speed, int duplex)
{ {
if (speed == SPEED_MAX) if (speed == SPEED_MAX)
speed = 1000; speed = 1000;
...@@ -340,11 +333,13 @@ int mv88e6352_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed) ...@@ -340,11 +333,13 @@ int mv88e6352_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
if (speed == 200 && port < 5) if (speed == 200 && port < 5)
return -EOPNOTSUPP; return -EOPNOTSUPP;
return mv88e6xxx_port_set_speed(chip, port, speed, true, false); return mv88e6xxx_port_set_speed_duplex(chip, port, speed, true, false,
duplex);
} }
/* Support 10, 100, 200, 1000, 2500 Mbps (e.g. 88E6390) */ /* Support 10, 100, 200, 1000, 2500 Mbps (e.g. 88E6390) */
int mv88e6390_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed) int mv88e6390_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,
int speed, int duplex)
{ {
if (speed == SPEED_MAX) if (speed == SPEED_MAX)
speed = port < 9 ? 1000 : 2500; speed = port < 9 ? 1000 : 2500;
...@@ -358,7 +353,8 @@ int mv88e6390_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed) ...@@ -358,7 +353,8 @@ int mv88e6390_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
if (speed == 2500 && port < 9) if (speed == 2500 && port < 9)
return -EOPNOTSUPP; return -EOPNOTSUPP;
return mv88e6xxx_port_set_speed(chip, port, speed, true, true); return mv88e6xxx_port_set_speed_duplex(chip, port, speed, true, true,
duplex);
} }
phy_interface_t mv88e6390_port_max_speed_mode(int port) phy_interface_t mv88e6390_port_max_speed_mode(int port)
...@@ -370,7 +366,8 @@ phy_interface_t mv88e6390_port_max_speed_mode(int port) ...@@ -370,7 +366,8 @@ phy_interface_t mv88e6390_port_max_speed_mode(int port)
} }
/* Support 10, 100, 200, 1000, 2500, 10000 Mbps (e.g. 88E6190X) */ /* Support 10, 100, 200, 1000, 2500, 10000 Mbps (e.g. 88E6190X) */
int mv88e6390x_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed) int mv88e6390x_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,
int speed, int duplex)
{ {
if (speed == SPEED_MAX) if (speed == SPEED_MAX)
speed = port < 9 ? 1000 : 10000; speed = port < 9 ? 1000 : 10000;
...@@ -381,7 +378,8 @@ int mv88e6390x_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed) ...@@ -381,7 +378,8 @@ int mv88e6390x_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
if (speed >= 2500 && port < 9) if (speed >= 2500 && port < 9)
return -EOPNOTSUPP; return -EOPNOTSUPP;
return mv88e6xxx_port_set_speed(chip, port, speed, true, true); return mv88e6xxx_port_set_speed_duplex(chip, port, speed, true, true,
duplex);
} }
phy_interface_t mv88e6390x_port_max_speed_mode(int port) phy_interface_t mv88e6390x_port_max_speed_mode(int port)
......
...@@ -298,15 +298,20 @@ int mv88e6390_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port, ...@@ -298,15 +298,20 @@ int mv88e6390_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,
int mv88e6xxx_port_set_link(struct mv88e6xxx_chip *chip, int port, int link); int mv88e6xxx_port_set_link(struct mv88e6xxx_chip *chip, int port, int link);
int mv88e6xxx_port_set_duplex(struct mv88e6xxx_chip *chip, int port, int dup); int mv88e6065_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,
int speed, int duplex);
int mv88e6065_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed); int mv88e6185_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,
int mv88e6185_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed); int speed, int duplex);
int mv88e6250_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed); int mv88e6250_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,
int mv88e6341_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed); int speed, int duplex);
int mv88e6352_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed); int mv88e6341_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,
int mv88e6390_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed); int speed, int duplex);
int mv88e6390x_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed); int mv88e6352_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,
int speed, int duplex);
int mv88e6390_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,
int speed, int duplex);
int mv88e6390x_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,
int speed, int duplex);
phy_interface_t mv88e6341_port_max_speed_mode(int port); phy_interface_t mv88e6341_port_max_speed_mode(int port);
phy_interface_t mv88e6390_port_max_speed_mode(int port); phy_interface_t mv88e6390_port_max_speed_mode(int port);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment