diff options
author | Russell King <rmk+kernel@armlinux.org.uk> | 2020-03-14 10:15:53 +0000 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2020-03-15 17:11:12 -0700 |
commit | f365c6f7235aa9a40ed7bbca83ad086a43006b1c (patch) | |
tree | 44c6db22cf7a3028642faf4998ce637f357bdb3d /drivers/net/dsa/mv88e6xxx/port.c | |
parent | 7e0e62431259b02a9c035f6cbaec2635add30921 (diff) | |
download | linux-stable-f365c6f7235aa9a40ed7bbca83ad086a43006b1c.tar.gz linux-stable-f365c6f7235aa9a40ed7bbca83ad086a43006b1c.tar.bz2 linux-stable-f365c6f7235aa9a40ed7bbca83ad086a43006b1c.zip |
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: Russell King <rmk+kernel@armlinux.org.uk>
Reviewed-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.c | 108 |
1 files changed, 53 insertions, 55 deletions
diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c index 0b43c650e100..442abb719cdc 100644 --- a/drivers/net/dsa/mv88e6xxx/port.c +++ b/drivers/net/dsa/mv88e6xxx/port.c @@ -162,46 +162,9 @@ int mv88e6xxx_port_set_link(struct mv88e6xxx_chip *chip, int port, int link) return 0; } -int mv88e6xxx_port_set_duplex(struct mv88e6xxx_chip *chip, int port, int dup) -{ - u16 reg; - int err; - - err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_MAC_CTL, ®); - 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) +static int mv88e6xxx_port_set_speed_duplex(struct mv88e6xxx_chip *chip, + int port, int speed, bool alt_bit, + bool force_bit, int duplex) { u16 reg, ctrl; int err; @@ -239,11 +202,29 @@ static int mv88e6xxx_port_set_speed(struct mv88e6xxx_chip *chip, int port, 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, ®); if (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) reg &= ~MV88E6390_PORT_MAC_CTL_ALTSPEED; if (force_bit) { @@ -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); else 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; } /* 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) speed = 200; @@ -275,11 +260,13 @@ int mv88e6065_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed) return -EOPNOTSUPP; /* 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) */ -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) speed = 1000; @@ -287,11 +274,13 @@ int mv88e6185_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed) if (speed == 200 || speed > 1000) 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) */ -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) speed = 100; @@ -299,11 +288,13 @@ int mv88e6250_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed) if (speed > 100) 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) */ -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) speed = port < 5 ? 1000 : 2500; @@ -317,7 +308,8 @@ int mv88e6341_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed) if (speed == 2500 && port < 5) 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) @@ -329,7 +321,8 @@ phy_interface_t mv88e6341_port_max_speed_mode(int port) } /* 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) speed = 1000; @@ -340,11 +333,13 @@ int mv88e6352_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed) if (speed == 200 && port < 5) 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) */ -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) speed = port < 9 ? 1000 : 2500; @@ -358,7 +353,8 @@ int mv88e6390_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed) if (speed == 2500 && port < 9) 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) @@ -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) */ -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) speed = port < 9 ? 1000 : 10000; @@ -381,7 +378,8 @@ int mv88e6390x_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed) if (speed >= 2500 && port < 9) 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) |