#endif
        .get_regs_len           = mv88e6xxx_get_regs_len,
        .get_regs               = mv88e6xxx_get_regs,
+       .port_join_bridge       = mv88e6xxx_port_bridge_join,
+       .port_leave_bridge      = mv88e6xxx_port_bridge_leave,
        .port_stp_update        = mv88e6xxx_port_stp_update,
        .port_pvid_get          = mv88e6xxx_port_pvid_get,
        .port_vlan_prepare      = mv88e6xxx_port_vlan_prepare,
 
        .set_eeprom             = mv88e6352_set_eeprom,
        .get_regs_len           = mv88e6xxx_get_regs_len,
        .get_regs               = mv88e6xxx_get_regs,
+       .port_join_bridge       = mv88e6xxx_port_bridge_join,
+       .port_leave_bridge      = mv88e6xxx_port_bridge_leave,
        .port_stp_update        = mv88e6xxx_port_stp_update,
        .port_pvid_get          = mv88e6xxx_port_pvid_get,
        .port_vlan_prepare      = mv88e6xxx_port_vlan_prepare,
 
                                const struct switchdev_obj_port_vlan *vlan,
                                struct switchdev_trans *trans)
 {
+       /* We reserve a few VLANs to isolate unbridged ports */
+       if (vlan->vid_end >= 4000)
+               return -EOPNOTSUPP;
+
        /* We don't need any dynamic resource from the kernel (yet),
         * so skip the prepare phase.
         */
        return err;
 }
 
+int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port, u32 members)
+{
+       struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+       const u16 pvid = 4000 + ds->index * DSA_MAX_PORTS + port;
+       int err;
+
+       /* The port joined a bridge, so leave its reserved VLAN */
+       mutex_lock(&ps->smi_mutex);
+       err = _mv88e6xxx_port_vlan_del(ds, port, pvid);
+       if (!err)
+               err = _mv88e6xxx_port_pvid_set(ds, port, 0);
+       mutex_unlock(&ps->smi_mutex);
+       return err;
+}
+
+int mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port, u32 members)
+{
+       struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+       const u16 pvid = 4000 + ds->index * DSA_MAX_PORTS + port;
+       int err;
+
+       /* The port left the bridge, so join its reserved VLAN */
+       mutex_lock(&ps->smi_mutex);
+       err = _mv88e6xxx_port_vlan_add(ds, port, pvid, true);
+       if (!err)
+               err = _mv88e6xxx_port_pvid_set(ds, port, pvid);
+       mutex_unlock(&ps->smi_mutex);
+       return err;
+}
+
 static void mv88e6xxx_bridge_work(struct work_struct *work)
 {
        struct mv88e6xxx_priv_state *ps;
                ret = mv88e6xxx_setup_port(ds, i);
                if (ret < 0)
                        return ret;
+
+               if (dsa_is_cpu_port(ds, i) || dsa_is_dsa_port(ds, i))
+                       continue;
+
+               /* setup the unbridged state */
+               ret = mv88e6xxx_port_bridge_leave(ds, i, 0);
+               if (ret < 0)
+                       return ret;
        }
        return 0;
 }
 
 int mv88e6xxx_get_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e);
 int mv88e6xxx_set_eee(struct dsa_switch *ds, int port,
                      struct phy_device *phydev, struct ethtool_eee *e);
+int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port, u32 members);
+int mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port, u32 members);
 int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state);
 int mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port,
                                const struct switchdev_obj_port_vlan *vlan,