Received: by 2002:a4f:b056:0:0:0:0:0 with SMTP id m22csp2676469ivi; Tue, 15 Sep 2020 16:30:05 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxc4wAE1AA8yI0ELQ3kI1LU1RIP9ZXKGwzNry+SITrUI1wTSaxz7g2BUbqV/3sdkB2OzWb+ X-Received: by 2002:a17:906:ecf1:: with SMTP id qt17mr23144814ejb.158.1600212605538; Tue, 15 Sep 2020 16:30:05 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1600212605; cv=none; d=google.com; s=arc-20160816; b=g+CTD+Ozt1eSaoEyRBW/3M4BYOKEsUOlFhF/37EwLGG28a2TtdoULWieaMPD5hNJ+l SJN6JV0oN+liJM3IeZxEvde+EqvEuZBfchr7aRL/4irUD/J3h8rc2UKTdLQY8KbjP71B wFnsTSSeFSVK/bymELsZuZF/Kg/6HvLcuTxNY+sZPARPJrQMvhSUpyAhOHJAd8z9HYVu wPUiQZOrfZ2bQDj7y062w9fi8yLYqdS01lkA1p9uPNg+q8GGxiIQ/M5RbLyQhAn0sbfy /JYMBaKD5On3B8fbR4/CWOFHvlot/0Ulkq6lQnh0e/S1Bj3urFrc25j4SZ0pKiI4OIGj Z8Xw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:date:subject:cc:to:from :dkim-signature; bh=wlMH8QuyjYR1doRko83qgCbVSL0B0yuQuD817gAzTi4=; b=sxYVIgB85eosdSEtPNlKbQkqpmzUcQJYUzSC0vd3izg18OJxvz83MazigOswrUq4XL /z6CtPy4lhWY8OIpS+fpm20y4dA6Y2wQvAKnR0SWMLGiNfkerAuEOvc9uZCPj1LOSn/z AhN18ujkgK7FHVQw8T0qvpNkEXz2D2AMwAgXe5mSx57PHYxJgL1uH0efHmuwjR12o0Cf DgNZEAjUJ2VFIOvQbssCxGhes1X6nrYuWpHo0QKtW0iqQ3h+gcXMzqmeVNKR7TdGwr7N sARWKGkV+WcWiZGckxNDvfp1ESkSiNo9KVyLcLABDoKpqbXURFUylWJVQAqo2Tk5HIAQ jEjg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=nCImKK7q; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id wn19si9459014ejb.625.2020.09.15.16.29.43; Tue, 15 Sep 2020 16:30:05 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=nCImKK7q; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727418AbgIOX3L (ORCPT + 99 others); Tue, 15 Sep 2020 19:29:11 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33962 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727309AbgIOX27 (ORCPT ); Tue, 15 Sep 2020 19:28:59 -0400 Received: from mail-wr1-x441.google.com (mail-wr1-x441.google.com [IPv6:2a00:1450:4864:20::441]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 45346C06178B; Tue, 15 Sep 2020 16:28:55 -0700 (PDT) Received: by mail-wr1-x441.google.com with SMTP id j2so4974495wrx.7; Tue, 15 Sep 2020 16:28:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=wlMH8QuyjYR1doRko83qgCbVSL0B0yuQuD817gAzTi4=; b=nCImKK7qVweclYFnPpSdKdNg5bCcq9ghNZnf9NG5qcxImcCnw8Deph43+A8rA1bSzu /oVYxBJEXGj8VU/iT5OC2kDswPCcUnC+ZOHAbpan4Zm9MGRPIBz7TkHwqR9AZpOc+9tp fodiasMqoFE9SUFolIdqz1rviK6j+tchlvq9RD/1txE/jA6OOyTvrPBShzeZ0aQGLjVv sqqqllcLZ/m8EdGuHPYB0UWxd0fT0UjJOX3vE6+5dvZQa4XvboFzmlOiht3Rg7Ft2WAY c8wGmbqpAtYFyBeitRqqN7n9JXZstndM28RuzV1GtyyNH67ognjIXxCQPjWAZ2bYD/tM NOKA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=wlMH8QuyjYR1doRko83qgCbVSL0B0yuQuD817gAzTi4=; b=c1/nhIAtkrNC6bgOkEN/eA7eXCWA8C4bXPbJX2n4Idcnx35qcuPxkUcky4HHofCxTw EDIeZ30njzhjkoVT31qrbJ5uAJOJQ81bv9Cyxa1iJTJzF+rFbusAXG/DAr9jn2YIl+ZP Fq7QzqTQbDhdZV2Dis5cyM6OHFEWEf1yvUNYthrIPZBrSZRzQAZIKWblOPpDLYyGBNi+ Vl8QnL42I+OpQjDHBeW0KnasXTbtdeU4EkngC8AD3W5NYuHQwuxsYxuKCQyp1EXhFTId Fmk/8bd2M4/gacJBuQ9fnxSbjr5REpZdYTtobfFqS6oTMPRlL5sS06PmULCYxucA1REI 2+Bw== X-Gm-Message-State: AOAM530AYaXKKs633C10ya0VtSaXXObEKRjmhbxer3ASujQ6ZsXGuVGK k9pkJBtYdNPMPutKS878ctf9dvY3ErAtH69C X-Received: by 2002:adf:e4c9:: with SMTP id v9mr23006769wrm.375.1600212533961; Tue, 15 Sep 2020 16:28:53 -0700 (PDT) Received: from djrscally-MIIX-510-12ISK.home ([2.29.208.34]) by smtp.gmail.com with ESMTPSA id f1sm28624374wrx.75.2020.09.15.16.28.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 15 Sep 2020 16:28:53 -0700 (PDT) From: Daniel Scally To: gregkh@linuxfoundation.org, rafael@kernel.org, linux-kernel@vger.kernel.org Cc: linux-media@vger.kernel.org, heikki.krogerus@linux.intel.com, andriy.shevchenko@linux.intel.com, kieran.bingham@ideasonboard.com, jorhand@linux.microsoft.com, kitakar@gmail.com Subject: [PATCH v2] software_node: Add support for fwnode_graph*() family of functions Date: Wed, 16 Sep 2020 00:28:27 +0100 Message-Id: <20200915232827.3416-1-djrscally@gmail.com> X-Mailer: git-send-email 2.17.1 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Heikki Krogerus This implements the remaining .graph_* callbacks in the fwnode operations vector for the software nodes. That makes the fwnode_graph*() functions available in the drivers also when software nodes are used. The implementation tries to mimic the "OF graph" as much as possible, but there is no support for the "reg" device property. The ports will need to have the index in their name which starts with "port" (for example "port0", "port1", ...) and endpoints will use the index of the software node that is given to them during creation. The port nodes can also be grouped under a specially named "ports" subnode, just like in DT, if necessary. The remote-endpoints are reference properties under the endpoint nodes that are named "remote-endpoint". Signed-off-by: Heikki Krogerus Co-developed-by: Daniel Scally Signed-off-by: Daniel Scally --- changes in v2: - added software_node_device_is_available - altered software_node_get_next_child to get references - altered software_node_get_next_endpoint to release references to ports and avoid passing invalid combinations of swnodes to software_node_get_next_child - altered swnode_graph_find_next_port to release port rather than old drivers/base/swnode.c | 129 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 127 insertions(+), 2 deletions(-) diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c index 010828fc785b..d69034b807e3 100644 --- a/drivers/base/swnode.c +++ b/drivers/base/swnode.c @@ -363,6 +363,11 @@ static void software_node_put(struct fwnode_handle *fwnode) kobject_put(&swnode->kobj); } +static bool software_node_device_is_available(const struct fwnode_handle *fwnode) +{ + return is_software_node(fwnode); +} + static bool software_node_property_present(const struct fwnode_handle *fwnode, const char *propname) { @@ -450,7 +455,7 @@ software_node_get_next_child(const struct fwnode_handle *fwnode, c = list_next_entry(c, entry); else c = list_first_entry(&p->children, struct swnode, entry); - return &c->fwnode; + return software_node_get(&c->fwnode); } static struct fwnode_handle * @@ -536,9 +541,125 @@ software_node_get_reference_args(const struct fwnode_handle *fwnode, 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))) { + if (!strncmp(to_swnode(port)->node->name, "port", 4)) + return port; + fwnode_handle_put(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 *old = endpoint; + struct fwnode_handle *parent_of_old; + 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)) { + + if (old) { + parent_of_old = software_node_get_parent(old); + + if (parent_of_old != port) + old = NULL; + + fwnode_handle_put(parent_of_old); + } + + endpoint = software_node_get_next_child(port, old); + fwnode_handle_put(old); + if (endpoint) + break; + + fwnode_handle_put(port); + } + + fwnode_handle_put(port); + software_node_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); + struct fwnode_handle *parent; + + if (!strcmp(swnode->parent->node->name, "ports")) + parent = &swnode->parent->parent->fwnode; + else + parent = &swnode->parent->fwnode; + + return software_node_get(parent); +} + +static int +software_node_graph_parse_endpoint(const struct fwnode_handle *fwnode, + struct fwnode_endpoint *endpoint) +{ + struct swnode *swnode = to_swnode(fwnode); + int ret; + + ret = kstrtou32(swnode->parent->node->name + 4, 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, + .device_is_available = software_node_device_is_available, .property_present = software_node_property_present, .property_read_int_array = software_node_read_int_array, .property_read_string_array = software_node_read_string_array, @@ -547,7 +668,11 @@ static const struct fwnode_operations software_node_ops = { .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, }; /* -------------------------------------------------------------------------- */ -- 2.17.1