aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Lunn <andrew@lunn.ch>2018-08-09 09:38:37 -0400
committerDavid S. Miller <davem@davemloft.net>2018-08-09 14:08:19 -0400
commit54186b91bde1711080d0b23ce25f0bee5a058fc9 (patch)
treeae6b23679f30ff4f141c42b77d76e1557d9463f0
parent78b39066c425ce913af1c0353d8fdc5d8c416e32 (diff)
net: dsa: mv88e6xxx: Add support to enabling pause
The 6185 can enable/disable 802.3z pause be setting the MyPause bit in the port status register. Add an op to support this. 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>
-rw-r--r--drivers/net/dsa/mv88e6xxx/chip.c20
-rw-r--r--drivers/net/dsa/mv88e6xxx/chip.h7
-rw-r--r--drivers/net/dsa/mv88e6xxx/port.c23
-rw-r--r--drivers/net/dsa/mv88e6xxx/port.h2
4 files changed, 48 insertions, 4 deletions
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 0b5a2c31f395..f7522d001365 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -524,7 +524,7 @@ int mv88e6xxx_update(struct mv88e6xxx_chip *chip, int addr, int reg, u16 update)
524} 524}
525 525
526static int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port, 526static int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port,
527 int link, int speed, int duplex, 527 int link, int speed, int duplex, int pause,
528 phy_interface_t mode) 528 phy_interface_t mode)
529{ 529{
530 int err; 530 int err;
@@ -543,6 +543,12 @@ static int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port,
543 goto restore_link; 543 goto restore_link;
544 } 544 }
545 545
546 if (chip->info->ops->port_set_pause) {
547 err = chip->info->ops->port_set_pause(chip, port, pause);
548 if (err)
549 goto restore_link;
550 }
551
546 if (chip->info->ops->port_set_duplex) { 552 if (chip->info->ops->port_set_duplex) {
547 err = chip->info->ops->port_set_duplex(chip, port, duplex); 553 err = chip->info->ops->port_set_duplex(chip, port, duplex);
548 if (err && err != -EOPNOTSUPP) 554 if (err && err != -EOPNOTSUPP)
@@ -584,7 +590,8 @@ static void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port,
584 590
585 mutex_lock(&chip->reg_lock); 591 mutex_lock(&chip->reg_lock);
586 err = mv88e6xxx_port_setup_mac(chip, port, phydev->link, phydev->speed, 592 err = mv88e6xxx_port_setup_mac(chip, port, phydev->link, phydev->speed,
587 phydev->duplex, phydev->interface); 593 phydev->duplex, phydev->pause,
594 phydev->interface);
588 mutex_unlock(&chip->reg_lock); 595 mutex_unlock(&chip->reg_lock);
589 596
590 if (err && err != -EOPNOTSUPP) 597 if (err && err != -EOPNOTSUPP)
@@ -615,7 +622,7 @@ static void mv88e6xxx_mac_config(struct dsa_switch *ds, int port,
615 const struct phylink_link_state *state) 622 const struct phylink_link_state *state)
616{ 623{
617 struct mv88e6xxx_chip *chip = ds->priv; 624 struct mv88e6xxx_chip *chip = ds->priv;
618 int speed, duplex, link, err; 625 int speed, duplex, link, pause, err;
619 626
620 if (mode == MLO_AN_PHY) 627 if (mode == MLO_AN_PHY)
621 return; 628 return;
@@ -629,9 +636,10 @@ static void mv88e6xxx_mac_config(struct dsa_switch *ds, int port,
629 duplex = DUPLEX_UNFORCED; 636 duplex = DUPLEX_UNFORCED;
630 link = LINK_UNFORCED; 637 link = LINK_UNFORCED;
631 } 638 }
639 pause = !!phylink_test(state->advertising, Pause);
632 640
633 mutex_lock(&chip->reg_lock); 641 mutex_lock(&chip->reg_lock);
634 err = mv88e6xxx_port_setup_mac(chip, port, link, speed, duplex, 642 err = mv88e6xxx_port_setup_mac(chip, port, link, speed, duplex, pause,
635 state->interface); 643 state->interface);
636 mutex_unlock(&chip->reg_lock); 644 mutex_unlock(&chip->reg_lock);
637 645
@@ -2087,10 +2095,12 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
2087 if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) 2095 if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port))
2088 err = mv88e6xxx_port_setup_mac(chip, port, LINK_FORCED_UP, 2096 err = mv88e6xxx_port_setup_mac(chip, port, LINK_FORCED_UP,
2089 SPEED_MAX, DUPLEX_FULL, 2097 SPEED_MAX, DUPLEX_FULL,
2098 PAUSE_OFF,
2090 PHY_INTERFACE_MODE_NA); 2099 PHY_INTERFACE_MODE_NA);
2091 else 2100 else
2092 err = mv88e6xxx_port_setup_mac(chip, port, LINK_UNFORCED, 2101 err = mv88e6xxx_port_setup_mac(chip, port, LINK_UNFORCED,
2093 SPEED_UNFORCED, DUPLEX_UNFORCED, 2102 SPEED_UNFORCED, DUPLEX_UNFORCED,
2103 PAUSE_ON,
2094 PHY_INTERFACE_MODE_NA); 2104 PHY_INTERFACE_MODE_NA);
2095 if (err) 2105 if (err)
2096 return err; 2106 return err;
@@ -2729,6 +2739,7 @@ static const struct mv88e6xxx_ops mv88e6131_ops = {
2729 .port_set_jumbo_size = mv88e6165_port_set_jumbo_size, 2739 .port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
2730 .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting, 2740 .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
2731 .port_pause_limit = mv88e6097_port_pause_limit, 2741 .port_pause_limit = mv88e6097_port_pause_limit,
2742 .port_set_pause = mv88e6185_port_set_pause,
2732 .stats_snapshot = mv88e6xxx_g1_stats_snapshot, 2743 .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
2733 .stats_set_histogram = mv88e6095_g1_stats_set_histogram, 2744 .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
2734 .stats_get_sset_count = mv88e6095_stats_get_sset_count, 2745 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
@@ -3021,6 +3032,7 @@ static const struct mv88e6xxx_ops mv88e6185_ops = {
3021 .port_set_egress_floods = mv88e6185_port_set_egress_floods, 3032 .port_set_egress_floods = mv88e6185_port_set_egress_floods,
3022 .port_egress_rate_limiting = mv88e6095_port_egress_rate_limiting, 3033 .port_egress_rate_limiting = mv88e6095_port_egress_rate_limiting,
3023 .port_set_upstream_port = mv88e6095_port_set_upstream_port, 3034 .port_set_upstream_port = mv88e6095_port_set_upstream_port,
3035 .port_set_pause = mv88e6185_port_set_pause,
3024 .stats_snapshot = mv88e6xxx_g1_stats_snapshot, 3036 .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
3025 .stats_set_histogram = mv88e6095_g1_stats_set_histogram, 3037 .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
3026 .stats_get_sset_count = mv88e6095_stats_get_sset_count, 3038 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
index 6aa6197ddc10..92ebfd271168 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.h
+++ b/drivers/net/dsa/mv88e6xxx/chip.h
@@ -351,6 +351,13 @@ struct mv88e6xxx_ops {
351 */ 351 */
352 int (*port_set_duplex)(struct mv88e6xxx_chip *chip, int port, int dup); 352 int (*port_set_duplex)(struct mv88e6xxx_chip *chip, int port, int dup);
353 353
354#define PAUSE_ON 1
355#define PAUSE_OFF 0
356
357 /* Enable/disable sending Pause */
358 int (*port_set_pause)(struct mv88e6xxx_chip *chip, int port,
359 int pause);
360
354#define SPEED_MAX INT_MAX 361#define SPEED_MAX INT_MAX
355#define SPEED_UNFORCED -2 362#define SPEED_UNFORCED -2
356 363
diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c
index 429d0ebcd5b1..c0701deaca6a 100644
--- a/drivers/net/dsa/mv88e6xxx/port.c
+++ b/drivers/net/dsa/mv88e6xxx/port.c
@@ -36,6 +36,29 @@ int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg,
36 return mv88e6xxx_write(chip, addr, reg, val); 36 return mv88e6xxx_write(chip, addr, reg, val);
37} 37}
38 38
39/* Offset 0x00: MAC (or PCS or Physical) Status Register
40 *
41 * For most devices, this is read only. However the 6185 has the MyPause
42 * bit read/write.
43 */
44int mv88e6185_port_set_pause(struct mv88e6xxx_chip *chip, int port,
45 int pause)
46{
47 u16 reg;
48 int err;
49
50 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &reg);
51 if (err)
52 return err;
53
54 if (pause)
55 reg |= MV88E6XXX_PORT_STS_MY_PAUSE;
56 else
57 reg &= ~MV88E6XXX_PORT_STS_MY_PAUSE;
58
59 return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_STS, reg);
60}
61
39/* Offset 0x01: MAC (or PCS or Physical) Control Register 62/* Offset 0x01: MAC (or PCS or Physical) Control Register
40 * 63 *
41 * Link, Duplex and Flow Control have one force bit, one value bit. 64 * Link, Duplex and Flow Control have one force bit, one value bit.
diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h
index 5e1db1b221ca..44916251567b 100644
--- a/drivers/net/dsa/mv88e6xxx/port.h
+++ b/drivers/net/dsa/mv88e6xxx/port.h
@@ -242,6 +242,8 @@ int mv88e6xxx_port_read(struct mv88e6xxx_chip *chip, int port, int reg,
242int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg, 242int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg,
243 u16 val); 243 u16 val);
244 244
245int mv88e6185_port_set_pause(struct mv88e6xxx_chip *chip, int port,
246 int pause);
245int mv88e6352_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port, 247int mv88e6352_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,
246 phy_interface_t mode); 248 phy_interface_t mode);
247int mv88e6390_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port, 249int mv88e6390_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,