.pcs_link_up = xpcs_link_up,
 };
 
-static struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev,
-                                  phy_interface_t interface)
+static struct dw_xpcs *xpcs_create_data(struct mdio_device *mdiodev)
 {
        struct dw_xpcs *xpcs;
-       u32 xpcs_id;
-       int i, ret;
 
        xpcs = kzalloc(sizeof(*xpcs), GFP_KERNEL);
        if (!xpcs)
 
        mdio_device_get(mdiodev);
        xpcs->mdiodev = mdiodev;
+       xpcs->pcs.ops = &xpcs_phylink_ops;
+       xpcs->pcs.neg_mode = true;
+       xpcs->pcs.poll = true;
+
+       return xpcs;
+}
+
+static void xpcs_free_data(struct dw_xpcs *xpcs)
+{
+       mdio_device_put(xpcs->mdiodev);
+       kfree(xpcs);
+}
+
+static int xpcs_init_id(struct dw_xpcs *xpcs)
+{
+       u32 xpcs_id;
+       int i, ret;
 
        xpcs_id = xpcs_get_id(xpcs);
 
        for (i = 0; i < ARRAY_SIZE(xpcs_id_list); i++) {
                const struct xpcs_id *entry = &xpcs_id_list[i];
-               const struct xpcs_compat *compat;
 
                if ((xpcs_id & entry->mask) != entry->id)
                        continue;
 
                xpcs->id = entry;
 
-               compat = xpcs_find_compat(entry, interface);
-               if (!compat) {
-                       ret = -ENODEV;
-                       goto out;
-               }
+               break;
+       }
 
-               ret = xpcs_dev_flag(xpcs);
-               if (ret)
-                       goto out;
+       if (!xpcs->id)
+               return -ENODEV;
 
-               xpcs->pcs.ops = &xpcs_phylink_ops;
-               xpcs->pcs.neg_mode = true;
+       ret = xpcs_dev_flag(xpcs);
+       if (ret < 0)
+               return ret;
 
-               if (xpcs->dev_flag != DW_DEV_TXGBE) {
-                       xpcs->pcs.poll = true;
+       return 0;
+}
 
-                       ret = xpcs_soft_reset(xpcs, compat);
-                       if (ret)
-                               goto out;
-               }
+static int xpcs_init_iface(struct dw_xpcs *xpcs, phy_interface_t interface)
+{
+       const struct xpcs_compat *compat;
 
-               return xpcs;
+       compat = xpcs_find_compat(xpcs->id, interface);
+       if (!compat)
+               return -EINVAL;
+
+       if (xpcs->dev_flag == DW_DEV_TXGBE) {
+               xpcs->pcs.poll = false;
+               return 0;
        }
 
-       ret = -ENODEV;
+       return xpcs_soft_reset(xpcs, compat);
+}
+
+static struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev,
+                                  phy_interface_t interface)
+{
+       struct dw_xpcs *xpcs;
+       int ret;
+
+       xpcs = xpcs_create_data(mdiodev);
+       if (IS_ERR(xpcs))
+               return xpcs;
+
+       ret = xpcs_init_id(xpcs);
+       if (ret)
+               goto out;
+
+       ret = xpcs_init_iface(xpcs, interface);
+       if (ret)
+               goto out;
+
+       return xpcs;
 
 out:
-       mdio_device_put(mdiodev);
-       kfree(xpcs);
+       xpcs_free_data(xpcs);
 
        return ERR_PTR(ret);
 }
 
-void xpcs_destroy(struct dw_xpcs *xpcs)
-{
-       if (xpcs)
-               mdio_device_put(xpcs->mdiodev);
-       kfree(xpcs);
-}
-EXPORT_SYMBOL_GPL(xpcs_destroy);
-
 struct dw_xpcs *xpcs_create_mdiodev(struct mii_bus *bus, int addr,
                                    phy_interface_t interface)
 {
 }
 EXPORT_SYMBOL_GPL(xpcs_create_mdiodev);
 
+void xpcs_destroy(struct dw_xpcs *xpcs)
+{
+       if (!xpcs)
+               return;
+
+       xpcs_free_data(xpcs);
+}
+EXPORT_SYMBOL_GPL(xpcs_destroy);
+
 MODULE_DESCRIPTION("Synopsys DesignWare XPCS library");
 MODULE_LICENSE("GPL v2");