|
|
@@ -37,6 +37,7 @@
|
|
|
#include "mv88e6xxx.h"
|
|
|
#include "global1.h"
|
|
|
#include "global2.h"
|
|
|
+#include "port.h"
|
|
|
|
|
|
static void assert_reg_lock(struct mv88e6xxx_chip *chip)
|
|
|
{
|
|
|
@@ -221,22 +222,6 @@ int mv88e6xxx_write(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int mv88e6xxx_port_read(struct mv88e6xxx_chip *chip, int port, int reg,
|
|
|
- u16 *val)
|
|
|
-{
|
|
|
- int addr = chip->info->port_base_addr + port;
|
|
|
-
|
|
|
- return mv88e6xxx_read(chip, addr, reg, val);
|
|
|
-}
|
|
|
-
|
|
|
-static int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg,
|
|
|
- u16 val)
|
|
|
-{
|
|
|
- int addr = chip->info->port_base_addr + port;
|
|
|
-
|
|
|
- return mv88e6xxx_write(chip, addr, reg, val);
|
|
|
-}
|
|
|
-
|
|
|
static int mv88e6xxx_phy_read(struct mv88e6xxx_chip *chip, int phy,
|
|
|
int reg, u16 *val)
|
|
|
{
|
|
|
@@ -716,6 +701,47 @@ static bool mv88e6xxx_6352_family(struct mv88e6xxx_chip *chip)
|
|
|
return chip->info->family == MV88E6XXX_FAMILY_6352;
|
|
|
}
|
|
|
|
|
|
+static int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port,
|
|
|
+ int link, int speed, int duplex,
|
|
|
+ phy_interface_t mode)
|
|
|
+{
|
|
|
+ int err;
|
|
|
+
|
|
|
+ if (!chip->info->ops->port_set_link)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ /* Port's MAC control must not be changed unless the link is down */
|
|
|
+ err = chip->info->ops->port_set_link(chip, port, 0);
|
|
|
+ if (err)
|
|
|
+ return err;
|
|
|
+
|
|
|
+ if (chip->info->ops->port_set_speed) {
|
|
|
+ err = chip->info->ops->port_set_speed(chip, port, speed);
|
|
|
+ if (err && err != -EOPNOTSUPP)
|
|
|
+ goto restore_link;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (chip->info->ops->port_set_duplex) {
|
|
|
+ err = chip->info->ops->port_set_duplex(chip, port, duplex);
|
|
|
+ if (err && err != -EOPNOTSUPP)
|
|
|
+ goto restore_link;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (chip->info->ops->port_set_rgmii_delay) {
|
|
|
+ err = chip->info->ops->port_set_rgmii_delay(chip, port, mode);
|
|
|
+ if (err && err != -EOPNOTSUPP)
|
|
|
+ goto restore_link;
|
|
|
+ }
|
|
|
+
|
|
|
+ err = 0;
|
|
|
+restore_link:
|
|
|
+ if (chip->info->ops->port_set_link(chip, port, link))
|
|
|
+ netdev_err(chip->ds->ports[port].netdev,
|
|
|
+ "failed to restore MAC's link\n");
|
|
|
+
|
|
|
+ return err;
|
|
|
+}
|
|
|
+
|
|
|
/* We expect the switch to perform auto negotiation if there is a real
|
|
|
* phy. However, in the case of a fixed link phy, we force the port
|
|
|
* settings from the fixed link settings.
|
|
|
@@ -724,64 +750,18 @@ static void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port,
|
|
|
struct phy_device *phydev)
|
|
|
{
|
|
|
struct mv88e6xxx_chip *chip = ds->priv;
|
|
|
- u16 reg;
|
|
|
int err;
|
|
|
|
|
|
if (!phy_is_pseudo_fixed_link(phydev))
|
|
|
return;
|
|
|
|
|
|
mutex_lock(&chip->reg_lock);
|
|
|
-
|
|
|
- err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, ®);
|
|
|
- if (err)
|
|
|
- goto out;
|
|
|
-
|
|
|
- reg &= ~(PORT_PCS_CTRL_LINK_UP |
|
|
|
- PORT_PCS_CTRL_FORCE_LINK |
|
|
|
- PORT_PCS_CTRL_DUPLEX_FULL |
|
|
|
- PORT_PCS_CTRL_FORCE_DUPLEX |
|
|
|
- PORT_PCS_CTRL_UNFORCED);
|
|
|
-
|
|
|
- reg |= PORT_PCS_CTRL_FORCE_LINK;
|
|
|
- if (phydev->link)
|
|
|
- reg |= PORT_PCS_CTRL_LINK_UP;
|
|
|
-
|
|
|
- if (mv88e6xxx_6065_family(chip) && phydev->speed > SPEED_100)
|
|
|
- goto out;
|
|
|
-
|
|
|
- switch (phydev->speed) {
|
|
|
- case SPEED_1000:
|
|
|
- reg |= PORT_PCS_CTRL_1000;
|
|
|
- break;
|
|
|
- case SPEED_100:
|
|
|
- reg |= PORT_PCS_CTRL_100;
|
|
|
- break;
|
|
|
- case SPEED_10:
|
|
|
- reg |= PORT_PCS_CTRL_10;
|
|
|
- break;
|
|
|
- default:
|
|
|
- pr_info("Unknown speed");
|
|
|
- goto out;
|
|
|
- }
|
|
|
-
|
|
|
- reg |= PORT_PCS_CTRL_FORCE_DUPLEX;
|
|
|
- if (phydev->duplex == DUPLEX_FULL)
|
|
|
- reg |= PORT_PCS_CTRL_DUPLEX_FULL;
|
|
|
-
|
|
|
- if ((mv88e6xxx_6352_family(chip) || mv88e6xxx_6351_family(chip)) &&
|
|
|
- (port >= mv88e6xxx_num_ports(chip) - 2)) {
|
|
|
- if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
|
|
|
- reg |= PORT_PCS_CTRL_RGMII_DELAY_RXCLK;
|
|
|
- if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
|
|
|
- reg |= PORT_PCS_CTRL_RGMII_DELAY_TXCLK;
|
|
|
- if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
|
|
|
- reg |= (PORT_PCS_CTRL_RGMII_DELAY_RXCLK |
|
|
|
- PORT_PCS_CTRL_RGMII_DELAY_TXCLK);
|
|
|
- }
|
|
|
- mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg);
|
|
|
-
|
|
|
-out:
|
|
|
+ err = mv88e6xxx_port_setup_mac(chip, port, phydev->link, phydev->speed,
|
|
|
+ phydev->duplex, phydev->interface);
|
|
|
mutex_unlock(&chip->reg_lock);
|
|
|
+
|
|
|
+ if (err && err != -EOPNOTSUPP)
|
|
|
+ netdev_err(ds->ports[port].netdev, "failed to configure MAC\n");
|
|
|
}
|
|
|
|
|
|
static int _mv88e6xxx_stats_wait(struct mv88e6xxx_chip *chip)
|
|
|
@@ -1230,54 +1210,16 @@ static int _mv88e6xxx_atu_remove(struct mv88e6xxx_chip *chip, u16 fid,
|
|
|
return _mv88e6xxx_atu_move(chip, fid, port, 0x0f, static_too);
|
|
|
}
|
|
|
|
|
|
-static const char * const mv88e6xxx_port_state_names[] = {
|
|
|
- [PORT_CONTROL_STATE_DISABLED] = "Disabled",
|
|
|
- [PORT_CONTROL_STATE_BLOCKING] = "Blocking/Listening",
|
|
|
- [PORT_CONTROL_STATE_LEARNING] = "Learning",
|
|
|
- [PORT_CONTROL_STATE_FORWARDING] = "Forwarding",
|
|
|
-};
|
|
|
-
|
|
|
-static int _mv88e6xxx_port_state(struct mv88e6xxx_chip *chip, int port,
|
|
|
- u8 state)
|
|
|
-{
|
|
|
- struct dsa_switch *ds = chip->ds;
|
|
|
- u16 reg;
|
|
|
- int err;
|
|
|
- u8 oldstate;
|
|
|
-
|
|
|
- err = mv88e6xxx_port_read(chip, port, PORT_CONTROL, ®);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
-
|
|
|
- oldstate = reg & PORT_CONTROL_STATE_MASK;
|
|
|
-
|
|
|
- reg &= ~PORT_CONTROL_STATE_MASK;
|
|
|
- reg |= state;
|
|
|
-
|
|
|
- err = mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
-
|
|
|
- netdev_dbg(ds->ports[port].netdev, "PortState %s (was %s)\n",
|
|
|
- mv88e6xxx_port_state_names[state],
|
|
|
- mv88e6xxx_port_state_names[oldstate]);
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
static int _mv88e6xxx_port_based_vlan_map(struct mv88e6xxx_chip *chip, int port)
|
|
|
{
|
|
|
struct net_device *bridge = chip->ports[port].bridge_dev;
|
|
|
- const u16 mask = (1 << mv88e6xxx_num_ports(chip)) - 1;
|
|
|
struct dsa_switch *ds = chip->ds;
|
|
|
u16 output_ports = 0;
|
|
|
- u16 reg;
|
|
|
- int err;
|
|
|
int i;
|
|
|
|
|
|
/* allow CPU port or DSA link(s) to send frames to every port */
|
|
|
if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) {
|
|
|
- output_ports = mask;
|
|
|
+ output_ports = ~0;
|
|
|
} else {
|
|
|
for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
|
|
|
/* allow sending frames to every group member */
|
|
|
@@ -1293,14 +1235,7 @@ static int _mv88e6xxx_port_based_vlan_map(struct mv88e6xxx_chip *chip, int port)
|
|
|
/* prevent frames from going back out of the port they came in on */
|
|
|
output_ports &= ~BIT(port);
|
|
|
|
|
|
- err = mv88e6xxx_port_read(chip, port, PORT_BASE_VLAN, ®);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
-
|
|
|
- reg &= ~mask;
|
|
|
- reg |= output_ports & mask;
|
|
|
-
|
|
|
- return mv88e6xxx_port_write(chip, port, PORT_BASE_VLAN, reg);
|
|
|
+ return mv88e6xxx_port_set_vlan_map(chip, port, output_ports);
|
|
|
}
|
|
|
|
|
|
static void mv88e6xxx_port_stp_state_set(struct dsa_switch *ds, int port,
|
|
|
@@ -1328,13 +1263,11 @@ static void mv88e6xxx_port_stp_state_set(struct dsa_switch *ds, int port,
|
|
|
}
|
|
|
|
|
|
mutex_lock(&chip->reg_lock);
|
|
|
- err = _mv88e6xxx_port_state(chip, port, stp_state);
|
|
|
+ err = mv88e6xxx_port_set_state(chip, port, stp_state);
|
|
|
mutex_unlock(&chip->reg_lock);
|
|
|
|
|
|
if (err)
|
|
|
- netdev_err(ds->ports[port].netdev,
|
|
|
- "failed to update state to %s\n",
|
|
|
- mv88e6xxx_port_state_names[stp_state]);
|
|
|
+ netdev_err(ds->ports[port].netdev, "failed to update state\n");
|
|
|
}
|
|
|
|
|
|
static void mv88e6xxx_port_fast_age(struct dsa_switch *ds, int port)
|
|
|
@@ -1350,49 +1283,6 @@ static void mv88e6xxx_port_fast_age(struct dsa_switch *ds, int port)
|
|
|
netdev_err(ds->ports[port].netdev, "failed to flush ATU\n");
|
|
|
}
|
|
|
|
|
|
-static int _mv88e6xxx_port_pvid(struct mv88e6xxx_chip *chip, int port,
|
|
|
- u16 *new, u16 *old)
|
|
|
-{
|
|
|
- struct dsa_switch *ds = chip->ds;
|
|
|
- u16 pvid, reg;
|
|
|
- int err;
|
|
|
-
|
|
|
- err = mv88e6xxx_port_read(chip, port, PORT_DEFAULT_VLAN, ®);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
-
|
|
|
- pvid = reg & PORT_DEFAULT_VLAN_MASK;
|
|
|
-
|
|
|
- if (new) {
|
|
|
- reg &= ~PORT_DEFAULT_VLAN_MASK;
|
|
|
- reg |= *new & PORT_DEFAULT_VLAN_MASK;
|
|
|
-
|
|
|
- err = mv88e6xxx_port_write(chip, port, PORT_DEFAULT_VLAN, reg);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
-
|
|
|
- netdev_dbg(ds->ports[port].netdev,
|
|
|
- "DefaultVID %d (was %d)\n", *new, pvid);
|
|
|
- }
|
|
|
-
|
|
|
- if (old)
|
|
|
- *old = pvid;
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static int _mv88e6xxx_port_pvid_get(struct mv88e6xxx_chip *chip,
|
|
|
- int port, u16 *pvid)
|
|
|
-{
|
|
|
- return _mv88e6xxx_port_pvid(chip, port, NULL, pvid);
|
|
|
-}
|
|
|
-
|
|
|
-static int _mv88e6xxx_port_pvid_set(struct mv88e6xxx_chip *chip,
|
|
|
- int port, u16 pvid)
|
|
|
-{
|
|
|
- return _mv88e6xxx_port_pvid(chip, port, &pvid, NULL);
|
|
|
-}
|
|
|
-
|
|
|
static int _mv88e6xxx_vtu_wait(struct mv88e6xxx_chip *chip)
|
|
|
{
|
|
|
return mv88e6xxx_g1_wait(chip, GLOBAL_VTU_OP, GLOBAL_VTU_OP_BUSY);
|
|
|
@@ -1572,7 +1462,7 @@ static int mv88e6xxx_port_vlan_dump(struct dsa_switch *ds, int port,
|
|
|
|
|
|
mutex_lock(&chip->reg_lock);
|
|
|
|
|
|
- err = _mv88e6xxx_port_pvid_get(chip, port, &pvid);
|
|
|
+ err = mv88e6xxx_port_get_pvid(chip, port, &pvid);
|
|
|
if (err)
|
|
|
goto unlock;
|
|
|
|
|
|
@@ -1736,75 +1626,6 @@ loadpurge:
|
|
|
return _mv88e6xxx_vtu_cmd(chip, GLOBAL_VTU_OP_STU_LOAD_PURGE);
|
|
|
}
|
|
|
|
|
|
-static int _mv88e6xxx_port_fid(struct mv88e6xxx_chip *chip, int port,
|
|
|
- u16 *new, u16 *old)
|
|
|
-{
|
|
|
- struct dsa_switch *ds = chip->ds;
|
|
|
- u16 upper_mask;
|
|
|
- u16 fid;
|
|
|
- u16 reg;
|
|
|
- int err;
|
|
|
-
|
|
|
- if (mv88e6xxx_num_databases(chip) == 4096)
|
|
|
- upper_mask = 0xff;
|
|
|
- else if (mv88e6xxx_num_databases(chip) == 256)
|
|
|
- upper_mask = 0xf;
|
|
|
- else
|
|
|
- return -EOPNOTSUPP;
|
|
|
-
|
|
|
- /* Port's default FID bits 3:0 are located in reg 0x06, offset 12 */
|
|
|
- err = mv88e6xxx_port_read(chip, port, PORT_BASE_VLAN, ®);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
-
|
|
|
- fid = (reg & PORT_BASE_VLAN_FID_3_0_MASK) >> 12;
|
|
|
-
|
|
|
- if (new) {
|
|
|
- reg &= ~PORT_BASE_VLAN_FID_3_0_MASK;
|
|
|
- reg |= (*new << 12) & PORT_BASE_VLAN_FID_3_0_MASK;
|
|
|
-
|
|
|
- err = mv88e6xxx_port_write(chip, port, PORT_BASE_VLAN, reg);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
- }
|
|
|
-
|
|
|
- /* Port's default FID bits 11:4 are located in reg 0x05, offset 0 */
|
|
|
- err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_1, ®);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
-
|
|
|
- fid |= (reg & upper_mask) << 4;
|
|
|
-
|
|
|
- if (new) {
|
|
|
- reg &= ~upper_mask;
|
|
|
- reg |= (*new >> 4) & upper_mask;
|
|
|
-
|
|
|
- err = mv88e6xxx_port_write(chip, port, PORT_CONTROL_1, reg);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
-
|
|
|
- netdev_dbg(ds->ports[port].netdev,
|
|
|
- "FID %d (was %d)\n", *new, fid);
|
|
|
- }
|
|
|
-
|
|
|
- if (old)
|
|
|
- *old = fid;
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static int _mv88e6xxx_port_fid_get(struct mv88e6xxx_chip *chip,
|
|
|
- int port, u16 *fid)
|
|
|
-{
|
|
|
- return _mv88e6xxx_port_fid(chip, port, NULL, fid);
|
|
|
-}
|
|
|
-
|
|
|
-static int _mv88e6xxx_port_fid_set(struct mv88e6xxx_chip *chip,
|
|
|
- int port, u16 fid)
|
|
|
-{
|
|
|
- return _mv88e6xxx_port_fid(chip, port, &fid, NULL);
|
|
|
-}
|
|
|
-
|
|
|
static int _mv88e6xxx_fid_new(struct mv88e6xxx_chip *chip, u16 *fid)
|
|
|
{
|
|
|
DECLARE_BITMAP(fid_bitmap, MV88E6XXX_N_FID);
|
|
|
@@ -1815,7 +1636,7 @@ static int _mv88e6xxx_fid_new(struct mv88e6xxx_chip *chip, u16 *fid)
|
|
|
|
|
|
/* Set every FID bit used by the (un)bridged ports */
|
|
|
for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
|
|
|
- err = _mv88e6xxx_port_fid_get(chip, i, fid);
|
|
|
+ err = mv88e6xxx_port_get_fid(chip, i, fid);
|
|
|
if (err)
|
|
|
return err;
|
|
|
|
|
|
@@ -1980,48 +1801,19 @@ unlock:
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
-static const char * const mv88e6xxx_port_8021q_mode_names[] = {
|
|
|
- [PORT_CONTROL_2_8021Q_DISABLED] = "Disabled",
|
|
|
- [PORT_CONTROL_2_8021Q_FALLBACK] = "Fallback",
|
|
|
- [PORT_CONTROL_2_8021Q_CHECK] = "Check",
|
|
|
- [PORT_CONTROL_2_8021Q_SECURE] = "Secure",
|
|
|
-};
|
|
|
-
|
|
|
static int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port,
|
|
|
bool vlan_filtering)
|
|
|
{
|
|
|
struct mv88e6xxx_chip *chip = ds->priv;
|
|
|
- u16 old, new = vlan_filtering ? PORT_CONTROL_2_8021Q_SECURE :
|
|
|
+ u16 mode = vlan_filtering ? PORT_CONTROL_2_8021Q_SECURE :
|
|
|
PORT_CONTROL_2_8021Q_DISABLED;
|
|
|
- u16 reg;
|
|
|
int err;
|
|
|
|
|
|
if (!mv88e6xxx_has(chip, MV88E6XXX_FLAG_VTU))
|
|
|
return -EOPNOTSUPP;
|
|
|
|
|
|
mutex_lock(&chip->reg_lock);
|
|
|
-
|
|
|
- err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_2, ®);
|
|
|
- if (err)
|
|
|
- goto unlock;
|
|
|
-
|
|
|
- old = reg & PORT_CONTROL_2_8021Q_MASK;
|
|
|
-
|
|
|
- if (new != old) {
|
|
|
- reg &= ~PORT_CONTROL_2_8021Q_MASK;
|
|
|
- reg |= new & PORT_CONTROL_2_8021Q_MASK;
|
|
|
-
|
|
|
- err = mv88e6xxx_port_write(chip, port, PORT_CONTROL_2, reg);
|
|
|
- if (err)
|
|
|
- goto unlock;
|
|
|
-
|
|
|
- netdev_dbg(ds->ports[port].netdev, "802.1Q Mode %s (was %s)\n",
|
|
|
- mv88e6xxx_port_8021q_mode_names[new],
|
|
|
- mv88e6xxx_port_8021q_mode_names[old]);
|
|
|
- }
|
|
|
-
|
|
|
- err = 0;
|
|
|
-unlock:
|
|
|
+ err = mv88e6xxx_port_set_8021q_mode(chip, port, mode);
|
|
|
mutex_unlock(&chip->reg_lock);
|
|
|
|
|
|
return err;
|
|
|
@@ -2089,7 +1881,7 @@ static void mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port,
|
|
|
"failed to add VLAN %d%c\n",
|
|
|
vid, untagged ? 'u' : 't');
|
|
|
|
|
|
- if (pvid && _mv88e6xxx_port_pvid_set(chip, port, vlan->vid_end))
|
|
|
+ if (pvid && mv88e6xxx_port_set_pvid(chip, port, vlan->vid_end))
|
|
|
netdev_err(ds->ports[port].netdev, "failed to set PVID %d\n",
|
|
|
vlan->vid_end);
|
|
|
|
|
|
@@ -2144,7 +1936,7 @@ static int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port,
|
|
|
|
|
|
mutex_lock(&chip->reg_lock);
|
|
|
|
|
|
- err = _mv88e6xxx_port_pvid_get(chip, port, &pvid);
|
|
|
+ err = mv88e6xxx_port_get_pvid(chip, port, &pvid);
|
|
|
if (err)
|
|
|
goto unlock;
|
|
|
|
|
|
@@ -2154,7 +1946,7 @@ static int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port,
|
|
|
goto unlock;
|
|
|
|
|
|
if (vid == pvid) {
|
|
|
- err = _mv88e6xxx_port_pvid_set(chip, port, 0);
|
|
|
+ err = mv88e6xxx_port_set_pvid(chip, port, 0);
|
|
|
if (err)
|
|
|
goto unlock;
|
|
|
}
|
|
|
@@ -2265,7 +2057,7 @@ static int mv88e6xxx_port_db_load_purge(struct mv88e6xxx_chip *chip, int port,
|
|
|
|
|
|
/* Null VLAN ID corresponds to the port private database */
|
|
|
if (vid == 0)
|
|
|
- err = _mv88e6xxx_port_fid_get(chip, port, &vlan.fid);
|
|
|
+ err = mv88e6xxx_port_get_fid(chip, port, &vlan.fid);
|
|
|
else
|
|
|
err = _mv88e6xxx_vtu_get(chip, vid, &vlan, false);
|
|
|
if (err)
|
|
|
@@ -2441,7 +2233,7 @@ static int mv88e6xxx_port_db_dump(struct mv88e6xxx_chip *chip, int port,
|
|
|
int err;
|
|
|
|
|
|
/* Dump port's default Filtering Information Database (VLAN ID 0) */
|
|
|
- err = _mv88e6xxx_port_fid_get(chip, port, &fid);
|
|
|
+ err = mv88e6xxx_port_get_fid(chip, port, &fid);
|
|
|
if (err)
|
|
|
return err;
|
|
|
|
|
|
@@ -2541,12 +2333,8 @@ static int mv88e6xxx_switch_reset(struct mv88e6xxx_chip *chip)
|
|
|
|
|
|
/* Set all ports to the disabled state. */
|
|
|
for (i = 0; i < mv88e6xxx_num_ports(chip); i++) {
|
|
|
- err = mv88e6xxx_port_read(chip, i, PORT_CONTROL, ®);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
-
|
|
|
- err = mv88e6xxx_port_write(chip, i, PORT_CONTROL,
|
|
|
- reg & 0xfffc);
|
|
|
+ err = mv88e6xxx_port_set_state(chip, i,
|
|
|
+ PORT_CONTROL_STATE_DISABLED);
|
|
|
if (err)
|
|
|
return err;
|
|
|
}
|
|
|
@@ -2616,35 +2404,20 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
|
|
|
int err;
|
|
|
u16 reg;
|
|
|
|
|
|
- if (mv88e6xxx_6352_family(chip) || mv88e6xxx_6351_family(chip) ||
|
|
|
- mv88e6xxx_6165_family(chip) || mv88e6xxx_6097_family(chip) ||
|
|
|
- mv88e6xxx_6185_family(chip) || mv88e6xxx_6095_family(chip) ||
|
|
|
- mv88e6xxx_6065_family(chip) || mv88e6xxx_6320_family(chip)) {
|
|
|
- /* MAC Forcing register: don't force link, speed,
|
|
|
- * duplex or flow control state to any particular
|
|
|
- * values on physical ports, but force the CPU port
|
|
|
- * and all DSA ports to their maximum bandwidth and
|
|
|
- * full duplex.
|
|
|
- */
|
|
|
- err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, ®);
|
|
|
- if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) {
|
|
|
- reg &= ~PORT_PCS_CTRL_UNFORCED;
|
|
|
- reg |= PORT_PCS_CTRL_FORCE_LINK |
|
|
|
- PORT_PCS_CTRL_LINK_UP |
|
|
|
- PORT_PCS_CTRL_DUPLEX_FULL |
|
|
|
- PORT_PCS_CTRL_FORCE_DUPLEX;
|
|
|
- if (mv88e6xxx_6065_family(chip))
|
|
|
- reg |= PORT_PCS_CTRL_100;
|
|
|
- else
|
|
|
- reg |= PORT_PCS_CTRL_1000;
|
|
|
- } else {
|
|
|
- reg |= PORT_PCS_CTRL_UNFORCED;
|
|
|
- }
|
|
|
-
|
|
|
- err = mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
- }
|
|
|
+ /* MAC Forcing register: don't force link, speed, duplex or flow control
|
|
|
+ * state to any particular values on physical ports, but force the CPU
|
|
|
+ * port and all DSA ports to their maximum bandwidth and full duplex.
|
|
|
+ */
|
|
|
+ if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port))
|
|
|
+ err = mv88e6xxx_port_setup_mac(chip, port, LINK_FORCED_UP,
|
|
|
+ SPEED_MAX, DUPLEX_FULL,
|
|
|
+ PHY_INTERFACE_MODE_NA);
|
|
|
+ else
|
|
|
+ err = mv88e6xxx_port_setup_mac(chip, port, LINK_UNFORCED,
|
|
|
+ SPEED_UNFORCED, DUPLEX_UNFORCED,
|
|
|
+ PHY_INTERFACE_MODE_NA);
|
|
|
+ if (err)
|
|
|
+ return err;
|
|
|
|
|
|
/* Port Control: disable Drop-on-Unlock, disable Drop-on-Lock,
|
|
|
* disable Header mode, enable IGMP/MLD snooping, disable VLAN
|
|
|
@@ -2848,7 +2621,7 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
|
|
|
* database, and allow bidirectional communication between the
|
|
|
* CPU and DSA port(s), and the other ports.
|
|
|
*/
|
|
|
- err = _mv88e6xxx_port_fid_set(chip, port, 0);
|
|
|
+ err = mv88e6xxx_port_set_fid(chip, port, 0);
|
|
|
if (err)
|
|
|
return err;
|
|
|
|
|
|
@@ -3367,42 +3140,63 @@ static const struct mv88e6xxx_ops mv88e6085_ops = {
|
|
|
.set_switch_mac = mv88e6xxx_g1_set_switch_mac,
|
|
|
.phy_read = mv88e6xxx_phy_ppu_read,
|
|
|
.phy_write = mv88e6xxx_phy_ppu_write,
|
|
|
+ .port_set_link = mv88e6xxx_port_set_link,
|
|
|
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
|
|
|
+ .port_set_speed = mv88e6185_port_set_speed,
|
|
|
};
|
|
|
|
|
|
static const struct mv88e6xxx_ops mv88e6095_ops = {
|
|
|
.set_switch_mac = mv88e6xxx_g1_set_switch_mac,
|
|
|
.phy_read = mv88e6xxx_phy_ppu_read,
|
|
|
.phy_write = mv88e6xxx_phy_ppu_write,
|
|
|
+ .port_set_link = mv88e6xxx_port_set_link,
|
|
|
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
|
|
|
+ .port_set_speed = mv88e6185_port_set_speed,
|
|
|
};
|
|
|
|
|
|
static const struct mv88e6xxx_ops mv88e6123_ops = {
|
|
|
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
|
|
|
.phy_read = mv88e6xxx_read,
|
|
|
.phy_write = mv88e6xxx_write,
|
|
|
+ .port_set_link = mv88e6xxx_port_set_link,
|
|
|
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
|
|
|
+ .port_set_speed = mv88e6185_port_set_speed,
|
|
|
};
|
|
|
|
|
|
static const struct mv88e6xxx_ops mv88e6131_ops = {
|
|
|
.set_switch_mac = mv88e6xxx_g1_set_switch_mac,
|
|
|
.phy_read = mv88e6xxx_phy_ppu_read,
|
|
|
.phy_write = mv88e6xxx_phy_ppu_write,
|
|
|
+ .port_set_link = mv88e6xxx_port_set_link,
|
|
|
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
|
|
|
+ .port_set_speed = mv88e6185_port_set_speed,
|
|
|
};
|
|
|
|
|
|
static const struct mv88e6xxx_ops mv88e6161_ops = {
|
|
|
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
|
|
|
.phy_read = mv88e6xxx_read,
|
|
|
.phy_write = mv88e6xxx_write,
|
|
|
+ .port_set_link = mv88e6xxx_port_set_link,
|
|
|
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
|
|
|
+ .port_set_speed = mv88e6185_port_set_speed,
|
|
|
};
|
|
|
|
|
|
static const struct mv88e6xxx_ops mv88e6165_ops = {
|
|
|
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
|
|
|
.phy_read = mv88e6xxx_read,
|
|
|
.phy_write = mv88e6xxx_write,
|
|
|
+ .port_set_link = mv88e6xxx_port_set_link,
|
|
|
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
|
|
|
+ .port_set_speed = mv88e6185_port_set_speed,
|
|
|
};
|
|
|
|
|
|
static const struct mv88e6xxx_ops mv88e6171_ops = {
|
|
|
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
|
|
|
.phy_read = mv88e6xxx_g2_smi_phy_read,
|
|
|
.phy_write = mv88e6xxx_g2_smi_phy_write,
|
|
|
+ .port_set_link = mv88e6xxx_port_set_link,
|
|
|
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
|
|
|
+ .port_set_speed = mv88e6185_port_set_speed,
|
|
|
};
|
|
|
|
|
|
static const struct mv88e6xxx_ops mv88e6172_ops = {
|
|
|
@@ -3411,12 +3205,19 @@ static const struct mv88e6xxx_ops mv88e6172_ops = {
|
|
|
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
|
|
|
.phy_read = mv88e6xxx_g2_smi_phy_read,
|
|
|
.phy_write = mv88e6xxx_g2_smi_phy_write,
|
|
|
+ .port_set_link = mv88e6xxx_port_set_link,
|
|
|
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
|
|
|
+ .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
|
|
|
+ .port_set_speed = mv88e6352_port_set_speed,
|
|
|
};
|
|
|
|
|
|
static const struct mv88e6xxx_ops mv88e6175_ops = {
|
|
|
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
|
|
|
.phy_read = mv88e6xxx_g2_smi_phy_read,
|
|
|
.phy_write = mv88e6xxx_g2_smi_phy_write,
|
|
|
+ .port_set_link = mv88e6xxx_port_set_link,
|
|
|
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
|
|
|
+ .port_set_speed = mv88e6185_port_set_speed,
|
|
|
};
|
|
|
|
|
|
static const struct mv88e6xxx_ops mv88e6176_ops = {
|
|
|
@@ -3425,12 +3226,19 @@ static const struct mv88e6xxx_ops mv88e6176_ops = {
|
|
|
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
|
|
|
.phy_read = mv88e6xxx_g2_smi_phy_read,
|
|
|
.phy_write = mv88e6xxx_g2_smi_phy_write,
|
|
|
+ .port_set_link = mv88e6xxx_port_set_link,
|
|
|
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
|
|
|
+ .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
|
|
|
+ .port_set_speed = mv88e6352_port_set_speed,
|
|
|
};
|
|
|
|
|
|
static const struct mv88e6xxx_ops mv88e6185_ops = {
|
|
|
.set_switch_mac = mv88e6xxx_g1_set_switch_mac,
|
|
|
.phy_read = mv88e6xxx_phy_ppu_read,
|
|
|
.phy_write = mv88e6xxx_phy_ppu_write,
|
|
|
+ .port_set_link = mv88e6xxx_port_set_link,
|
|
|
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
|
|
|
+ .port_set_speed = mv88e6185_port_set_speed,
|
|
|
};
|
|
|
|
|
|
static const struct mv88e6xxx_ops mv88e6240_ops = {
|
|
|
@@ -3439,6 +3247,10 @@ static const struct mv88e6xxx_ops mv88e6240_ops = {
|
|
|
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
|
|
|
.phy_read = mv88e6xxx_g2_smi_phy_read,
|
|
|
.phy_write = mv88e6xxx_g2_smi_phy_write,
|
|
|
+ .port_set_link = mv88e6xxx_port_set_link,
|
|
|
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
|
|
|
+ .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
|
|
|
+ .port_set_speed = mv88e6352_port_set_speed,
|
|
|
};
|
|
|
|
|
|
static const struct mv88e6xxx_ops mv88e6320_ops = {
|
|
|
@@ -3447,6 +3259,9 @@ static const struct mv88e6xxx_ops mv88e6320_ops = {
|
|
|
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
|
|
|
.phy_read = mv88e6xxx_g2_smi_phy_read,
|
|
|
.phy_write = mv88e6xxx_g2_smi_phy_write,
|
|
|
+ .port_set_link = mv88e6xxx_port_set_link,
|
|
|
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
|
|
|
+ .port_set_speed = mv88e6185_port_set_speed,
|
|
|
};
|
|
|
|
|
|
static const struct mv88e6xxx_ops mv88e6321_ops = {
|
|
|
@@ -3455,18 +3270,27 @@ static const struct mv88e6xxx_ops mv88e6321_ops = {
|
|
|
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
|
|
|
.phy_read = mv88e6xxx_g2_smi_phy_read,
|
|
|
.phy_write = mv88e6xxx_g2_smi_phy_write,
|
|
|
+ .port_set_link = mv88e6xxx_port_set_link,
|
|
|
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
|
|
|
+ .port_set_speed = mv88e6185_port_set_speed,
|
|
|
};
|
|
|
|
|
|
static const struct mv88e6xxx_ops mv88e6350_ops = {
|
|
|
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
|
|
|
.phy_read = mv88e6xxx_g2_smi_phy_read,
|
|
|
.phy_write = mv88e6xxx_g2_smi_phy_write,
|
|
|
+ .port_set_link = mv88e6xxx_port_set_link,
|
|
|
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
|
|
|
+ .port_set_speed = mv88e6185_port_set_speed,
|
|
|
};
|
|
|
|
|
|
static const struct mv88e6xxx_ops mv88e6351_ops = {
|
|
|
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
|
|
|
.phy_read = mv88e6xxx_g2_smi_phy_read,
|
|
|
.phy_write = mv88e6xxx_g2_smi_phy_write,
|
|
|
+ .port_set_link = mv88e6xxx_port_set_link,
|
|
|
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
|
|
|
+ .port_set_speed = mv88e6185_port_set_speed,
|
|
|
};
|
|
|
|
|
|
static const struct mv88e6xxx_ops mv88e6352_ops = {
|
|
|
@@ -3475,6 +3299,10 @@ static const struct mv88e6xxx_ops mv88e6352_ops = {
|
|
|
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
|
|
|
.phy_read = mv88e6xxx_g2_smi_phy_read,
|
|
|
.phy_write = mv88e6xxx_g2_smi_phy_write,
|
|
|
+ .port_set_link = mv88e6xxx_port_set_link,
|
|
|
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
|
|
|
+ .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
|
|
|
+ .port_set_speed = mv88e6352_port_set_speed,
|
|
|
};
|
|
|
|
|
|
static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|