return 0;
 }
 
+static struct fwnode_handle *
+swnode_graph_find_next_port(const struct fwnode_handle *parent,
+                           struct fwnode_handle *port)
+{
+       struct fwnode_handle *old = port;
+
+       while ((port = software_node_get_next_child(parent, old))) {
+               /*
+                * fwnode ports have naming style "port@", so we search for any
+                * children that follow that convention.
+                */
+               if (!strncmp(to_swnode(port)->node->name, "port@",
+                            strlen("port@")))
+                       return port;
+               old = port;
+       }
+
+       return NULL;
+}
+
+static struct fwnode_handle *
+software_node_graph_get_next_endpoint(const struct fwnode_handle *fwnode,
+                                     struct fwnode_handle *endpoint)
+{
+       struct swnode *swnode = to_swnode(fwnode);
+       struct fwnode_handle *parent;
+       struct fwnode_handle *port;
+
+       if (!swnode)
+               return NULL;
+
+       if (endpoint) {
+               port = software_node_get_parent(endpoint);
+               parent = software_node_get_parent(port);
+       } else {
+               parent = software_node_get_named_child_node(fwnode, "ports");
+               if (!parent)
+                       parent = software_node_get(&swnode->fwnode);
+
+               port = swnode_graph_find_next_port(parent, NULL);
+       }
+
+       for (; port; port = swnode_graph_find_next_port(parent, port)) {
+               endpoint = software_node_get_next_child(port, endpoint);
+               if (endpoint) {
+                       fwnode_handle_put(port);
+                       break;
+               }
+       }
+
+       fwnode_handle_put(parent);
+
+       return endpoint;
+}
+
+static struct fwnode_handle *
+software_node_graph_get_remote_endpoint(const struct fwnode_handle *fwnode)
+{
+       struct swnode *swnode = to_swnode(fwnode);
+       const struct software_node_ref_args *ref;
+       const struct property_entry *prop;
+
+       if (!swnode)
+               return NULL;
+
+       prop = property_entry_get(swnode->node->properties, "remote-endpoint");
+       if (!prop || prop->type != DEV_PROP_REF || prop->is_inline)
+               return NULL;
+
+       ref = prop->pointer;
+
+       return software_node_get(software_node_fwnode(ref[0].node));
+}
+
+static struct fwnode_handle *
+software_node_graph_get_port_parent(struct fwnode_handle *fwnode)
+{
+       struct swnode *swnode = to_swnode(fwnode);
+
+       swnode = swnode->parent;
+       if (swnode && !strcmp(swnode->node->name, "ports"))
+               swnode = swnode->parent;
+
+       return swnode ? software_node_get(&swnode->fwnode) : NULL;
+}
+
+static int
+software_node_graph_parse_endpoint(const struct fwnode_handle *fwnode,
+                                  struct fwnode_endpoint *endpoint)
+{
+       struct swnode *swnode = to_swnode(fwnode);
+       const char *parent_name = swnode->parent->node->name;
+       int ret;
+
+       if (strlen("port@") >= strlen(parent_name) ||
+           strncmp(parent_name, "port@", strlen("port@")))
+               return -EINVAL;
+
+       /* Ports have naming style "port@n", we need to select the n */
+       ret = kstrtou32(parent_name + strlen("port@"), 10, &endpoint->port);
+       if (ret)
+               return ret;
+
+       endpoint->id = swnode->id;
+       endpoint->local_fwnode = fwnode;
+
+       return 0;
+}
+
 static const struct fwnode_operations software_node_ops = {
        .get = software_node_get,
        .put = software_node_put,
        .get_parent = software_node_get_parent,
        .get_next_child_node = software_node_get_next_child,
        .get_named_child_node = software_node_get_named_child_node,
-       .get_reference_args = software_node_get_reference_args
+       .get_reference_args = software_node_get_reference_args,
+       .graph_get_next_endpoint = software_node_graph_get_next_endpoint,
+       .graph_get_remote_endpoint = software_node_graph_get_remote_endpoint,
+       .graph_get_port_parent = software_node_graph_get_port_parent,
+       .graph_parse_endpoint = software_node_graph_parse_endpoint,
 };
 
 /* -------------------------------------------------------------------------- */