Merge tag 'wireless-drivers-for-davem-2017-04-03' of git://git.kernel.org/pub/scm...
[linux-2.6-block.git] / drivers / net / dsa / mv88e6xxx / port.c
index 8875784c4718feee699355f91c2092622417cce1..548a956637eec56b4aac9d7e4b2890e078f51285 100644 (file)
@@ -3,7 +3,8 @@
  *
  * Copyright (c) 2008 Marvell Semiconductor
  *
- * Copyright (c) 2016 Vivien Didelot <vivien.didelot@savoirfairelinux.com>
+ * Copyright (c) 2016-2017 Savoir-faire Linux Inc.
+ *     Vivien Didelot <vivien.didelot@savoirfairelinux.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -497,8 +498,8 @@ int mv88e6351_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port,
        return mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg);
 }
 
-int mv88e6085_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port,
-                                      bool on)
+static int mv88e6185_port_set_forward_unknown(struct mv88e6xxx_chip *chip,
+                                             int port, bool unicast)
 {
        int err;
        u16 reg;
@@ -507,7 +508,7 @@ int mv88e6085_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port,
        if (err)
                return err;
 
-       if (on)
+       if (unicast)
                reg |= PORT_CONTROL_FORWARD_UNKNOWN;
        else
                reg &= ~PORT_CONTROL_FORWARD_UNKNOWN;
@@ -515,8 +516,8 @@ int mv88e6085_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port,
        return mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg);
 }
 
-int mv88e6351_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port,
-                                      bool on)
+int mv88e6352_port_set_egress_floods(struct mv88e6xxx_chip *chip, int port,
+                                    bool unicast, bool multicast)
 {
        int err;
        u16 reg;
@@ -525,21 +526,45 @@ int mv88e6351_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port,
        if (err)
                return err;
 
-       if (on)
-               reg |= PORT_CONTROL_EGRESS_ALL_UNKNOWN_DA;
+       reg &= ~PORT_CONTROL_EGRESS_FLOODS_MASK;
+
+       if (unicast && multicast)
+               reg |= PORT_CONTROL_EGRESS_FLOODS_ALL_UNKNOWN_DA;
+       else if (unicast)
+               reg |= PORT_CONTROL_EGRESS_FLOODS_NO_UNKNOWN_MC_DA;
+       else if (multicast)
+               reg |= PORT_CONTROL_EGRESS_FLOODS_NO_UNKNOWN_UC_DA;
        else
-               reg &= ~PORT_CONTROL_EGRESS_ALL_UNKNOWN_DA;
+               reg |= PORT_CONTROL_EGRESS_FLOODS_NO_UNKNOWN_DA;
 
        return mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg);
 }
 
 /* Offset 0x05: Port Control 1 */
 
+int mv88e6xxx_port_set_message_port(struct mv88e6xxx_chip *chip, int port,
+                                   bool message_port)
+{
+       u16 val;
+       int err;
+
+       err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_1, &val);
+       if (err)
+               return err;
+
+       if (message_port)
+               val |= PORT_CONTROL_1_MESSAGE_PORT;
+       else
+               val &= ~PORT_CONTROL_1_MESSAGE_PORT;
+
+       return mv88e6xxx_port_write(chip, port, PORT_CONTROL_1, val);
+}
+
 /* Offset 0x06: Port Based VLAN Map */
 
 int mv88e6xxx_port_set_vlan_map(struct mv88e6xxx_chip *chip, int port, u16 map)
 {
-       const u16 mask = GENMASK(mv88e6xxx_num_ports(chip) - 1, 0);
+       const u16 mask = mv88e6xxx_port_mask(chip);
        u16 reg;
        int err;
 
@@ -672,8 +697,8 @@ static const char * const mv88e6xxx_port_8021q_mode_names[] = {
        [PORT_CONTROL_2_8021Q_SECURE] = "Secure",
 };
 
-int mv88e6095_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port,
-                                      bool on)
+static int mv88e6185_port_set_default_forward(struct mv88e6xxx_chip *chip,
+                                             int port, bool multicast)
 {
        int err;
        u16 reg;
@@ -682,14 +707,26 @@ int mv88e6095_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port,
        if (err)
                return err;
 
-       if (on)
-               reg |= PORT_CONTROL_2_FORWARD_UNKNOWN;
+       if (multicast)
+               reg |= PORT_CONTROL_2_DEFAULT_FORWARD;
        else
-               reg &= ~PORT_CONTROL_2_FORWARD_UNKNOWN;
+               reg &= ~PORT_CONTROL_2_DEFAULT_FORWARD;
 
        return mv88e6xxx_port_write(chip, port, PORT_CONTROL_2, reg);
 }
 
+int mv88e6185_port_set_egress_floods(struct mv88e6xxx_chip *chip, int port,
+                                    bool unicast, bool multicast)
+{
+       int err;
+
+       err = mv88e6185_port_set_forward_unknown(chip, port, unicast);
+       if (err)
+               return err;
+
+       return mv88e6185_port_set_default_forward(chip, port, multicast);
+}
+
 int mv88e6095_port_set_upstream_port(struct mv88e6xxx_chip *chip, int port,
                                     int upstream_port)
 {
@@ -769,6 +806,20 @@ int mv88e6097_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port)
        return mv88e6xxx_port_write(chip, port, PORT_RATE_CONTROL, 0x0001);
 }
 
+/* Offset 0x0C: Port ATU Control */
+
+int mv88e6xxx_port_disable_learn_limit(struct mv88e6xxx_chip *chip, int port)
+{
+       return mv88e6xxx_port_write(chip, port, PORT_ATU_CONTROL, 0);
+}
+
+/* Offset 0x0D: (Priority) Override Register */
+
+int mv88e6xxx_port_disable_pri_override(struct mv88e6xxx_chip *chip, int port)
+{
+       return mv88e6xxx_port_write(chip, port, PORT_PRI_OVERRIDE, 0);
+}
+
 /* Offset 0x0f: Port Ether type */
 
 int mv88e6351_port_set_ether_type(struct mv88e6xxx_chip *chip, int port,