#ifndef _TN40_H_
 #define _TN40_H_
 
+#include <linux/property.h>
 #include "tn40_regs.h"
 
 #define TN40_DRV_NAME "tn40xx"
 
+#define PCI_DEVICE_ID_TEHUTI_TN9510    0x4025
+
 #define TN40_MDIO_SPEED_1MHZ (1)
 #define TN40_MDIO_SPEED_6MHZ (6)
 
        int size; /* Number of elements in the db */
 };
 
+#define NODE_PROP(_NAME, _PROP)        (               \
+       (const struct software_node) {          \
+               .name = _NAME,                  \
+               .properties = _PROP,            \
+       })
+
+#define NODE_PAR_PROP(_NAME, _PAR, _PROP)      (       \
+       (const struct software_node) {          \
+               .name = _NAME,                  \
+               .parent = _PAR,                 \
+               .properties = _PROP,            \
+       })
+
+enum tn40_swnodes {
+       SWNODE_MDIO,
+       SWNODE_PHY,
+       SWNODE_MAX
+};
+
+struct tn40_nodes {
+       char phy_name[32];
+       char mdio_name[32];
+       struct property_entry phy_props[3];
+       struct software_node swnodes[SWNODE_MAX];
+       const struct software_node *group[SWNODE_MAX + 1];
+};
+
 struct tn40_priv {
        struct net_device *ndev;
        struct pci_dev *pdev;
 
+       struct tn40_nodes nodes;
+
        struct napi_struct napi;
        /* RX FIFOs: 1 for data (full) descs, and 2 for free descs */
        struct tn40_rxd_fifo rxd_fifo0;
 
 int tn40_set_link_speed(struct tn40_priv *priv, u32 speed);
 
+void tn40_swnodes_cleanup(struct tn40_priv *priv);
 int tn40_mdiobus_init(struct tn40_priv *priv);
 
 int tn40_phy_register(struct tn40_priv *priv);
 
         (FIELD_PREP(TN40_MDIO_PRTAD_MASK, (port))))
 #define TN40_MDIO_CMD_READ BIT(15)
 
+#define AQR105_FIRMWARE "tehuti/aqr105-tn40xx.cld"
+
 static void tn40_mdio_set_speed(struct tn40_priv *priv, u32 speed)
 {
        void __iomem *regs = priv->regs;
        return  tn40_mdio_write(mii_bus->priv, addr, devnum, regnum, val);
 }
 
+/* registers an mdio node and an aqr105 PHY at address 1
+ * tn40_mdio-%id {
+ *     ethernet-phy@1 {
+ *             compatible = "ethernet-phy-id03a1.b4a3";
+ *             reg = <1>;
+ *             firmware-name = AQR105_FIRMWARE;
+ *     };
+ * };
+ */
+static int tn40_swnodes_register(struct tn40_priv *priv)
+{
+       struct tn40_nodes *nodes = &priv->nodes;
+       struct pci_dev *pdev = priv->pdev;
+       struct software_node *swnodes;
+       u32 id;
+
+       id = pci_dev_id(pdev);
+
+       snprintf(nodes->phy_name, sizeof(nodes->phy_name), "ethernet-phy@1");
+       snprintf(nodes->mdio_name, sizeof(nodes->mdio_name), "tn40_mdio-%x",
+                id);
+
+       swnodes = nodes->swnodes;
+
+       swnodes[SWNODE_MDIO] = NODE_PROP(nodes->mdio_name, NULL);
+
+       nodes->phy_props[0] = PROPERTY_ENTRY_STRING("compatible",
+                                                   "ethernet-phy-id03a1.b4a3");
+       nodes->phy_props[1] = PROPERTY_ENTRY_U32("reg", 1);
+       nodes->phy_props[2] = PROPERTY_ENTRY_STRING("firmware-name",
+                                                   AQR105_FIRMWARE);
+       swnodes[SWNODE_PHY] = NODE_PAR_PROP(nodes->phy_name,
+                                           &swnodes[SWNODE_MDIO],
+                                           nodes->phy_props);
+
+       nodes->group[SWNODE_PHY] = &swnodes[SWNODE_PHY];
+       nodes->group[SWNODE_MDIO] = &swnodes[SWNODE_MDIO];
+       return software_node_register_node_group(nodes->group);
+}
+
+void tn40_swnodes_cleanup(struct tn40_priv *priv)
+{
+       /* cleanup of swnodes is only needed for AQR105-based cards */
+       if (priv->pdev->device == PCI_DEVICE_ID_TEHUTI_TN9510) {
+               fwnode_handle_put(dev_fwnode(&priv->mdio->dev));
+               device_remove_software_node(&priv->mdio->dev);
+               software_node_unregister_node_group(priv->nodes.group);
+       }
+}
+
 int tn40_mdiobus_init(struct tn40_priv *priv)
 {
        struct pci_dev *pdev = priv->pdev;
 
        bus->read_c45 = tn40_mdio_read_c45;
        bus->write_c45 = tn40_mdio_write_c45;
+       priv->mdio = bus;
+
+       /* provide swnodes for AQR105-based cards only */
+       if (pdev->device == PCI_DEVICE_ID_TEHUTI_TN9510) {
+               ret = tn40_swnodes_register(priv);
+               if (ret) {
+                       pr_err("swnodes failed\n");
+                       return ret;
+               }
+
+               ret = device_add_software_node(&bus->dev,
+                                              priv->nodes.group[SWNODE_MDIO]);
+               if (ret) {
+                       dev_err(&pdev->dev,
+                               "device_add_software_node failed: %d\n", ret);
+                       goto err_swnodes_unregister;
+               }
+       }
 
        ret = devm_mdiobus_register(&pdev->dev, bus);
        if (ret) {
                dev_err(&pdev->dev, "failed to register mdiobus %d %u %u\n",
                        ret, bus->state, MDIOBUS_UNREGISTERED);
-               return ret;
+               goto err_swnodes_cleanup;
        }
        tn40_mdio_set_speed(priv, TN40_MDIO_SPEED_6MHZ);
-       priv->mdio = bus;
        return 0;
+
+err_swnodes_unregister:
+       software_node_unregister_node_group(priv->nodes.group);
+       return ret;
+err_swnodes_cleanup:
+       tn40_swnodes_cleanup(priv);
+       return ret;
 }
+
+MODULE_FIRMWARE(AQR105_FIRMWARE);