From patchwork Tue Jun 22 01:14:13 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kuninori Morimoto X-Patchwork-Id: 465206 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B79C6C4743C for ; Tue, 22 Jun 2021 01:15:39 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 0D7896124B for ; Tue, 22 Jun 2021 01:15:39 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 0D7896124B Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=renesas.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id A14751690; Tue, 22 Jun 2021 03:14:47 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz A14751690 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1624324537; bh=InqjXSZJtpDc9Wlwd3mEbY1Ow1SAP/WJDfFGtniMb50=; h=Date:From:Subject:To:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=qDm0iVBGwif4hNGAV2wa99DtklFyoc/1uRIut3wy78hS5gGdISzjQJCtqk19Lkwgg Qs4qQwuVBF5OjStc+xx2t7ukKYgfsa1hWUJtZnsNT/Vv5S6wkijtoadZTYNdXpvg3M qoCeIWfkaeOWSPXZtRgUSz/ccP/sUNPIEwvFL79s= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 97D9BF80245; Tue, 22 Jun 2021 03:14:23 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 0925AF80245; Tue, 22 Jun 2021 03:14:22 +0200 (CEST) Received: from relmlie5.idc.renesas.com (relmlor1.renesas.com [210.160.252.171]) by alsa1.perex.cz (Postfix) with ESMTP id 4138FF80111 for ; Tue, 22 Jun 2021 03:14:15 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 4138FF80111 Date: 22 Jun 2021 10:14:13 +0900 X-IronPort-AV: E=Sophos;i="5.83,290,1616425200"; d="scan'208";a="85109211" Received: from unknown (HELO relmlir6.idc.renesas.com) ([10.200.68.152]) by relmlie5.idc.renesas.com with ESMTP; 22 Jun 2021 10:14:13 +0900 Received: from mercury.renesas.com (unknown [10.166.252.133]) by relmlir6.idc.renesas.com (Postfix) with ESMTP id D6B264148A7D; Tue, 22 Jun 2021 10:14:13 +0900 (JST) Message-ID: <87zgvi3dlm.wl-kuninori.morimoto.gx@renesas.com> From: Kuninori Morimoto Subject: [PATCH RFC 01/15] of: property: add port base loop User-Agent: Wanderlust/2.15.9 Emacs/26.3 Mule/6.0 To: Mark Brown , Rob Herring In-Reply-To: <871r8u4s6q.wl-kuninori.morimoto.gx@renesas.com> References: <871r8u4s6q.wl-kuninori.morimoto.gx@renesas.com> MIME-Version: 1.0 (generated by SEMI-EPG 1.14.7 - "Harue") Cc: Linux-ALSA X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" From: Kuninori Morimoto We have endpoint base functions - of_graph_get_next_endpoint() - of_graph_get_endpoint_count() - for_each_endpoint_of_node() for_each_endpoint_of_node() loop finds endpoint. ports { port@0 { (1) endpoint {...}; }; port@1 { (2) endpoint {...}; }; ... }; In above case, for_each_endpoint_of_node() loop finds endpoint as (1) -> (2) -> ... If we want to get port@0 -> port@1 -> ... instead of endpoint, we need do like below for_each_endpoint_of_node(node, endpoint) { port = of_get_parent(endpoint); ... } But port might have multi endpoints. ports { port@0 { (1) endpoint@0 {...}; (2) endpoint@1 {...}; }; port@1 { (3) endpoint {...}; }; ... }; In such case, people want to have "port base" loop instead of "endpoints base" loop. This patch adds such functions/macros. Link: https://lore.kernel.org/r/87pn29pc5w.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Kuninori Morimoto --- drivers/of/property.c | 69 ++++++++++++++++++++++++++++++++++------ include/linux/of_graph.h | 14 ++++++++ 2 files changed, 73 insertions(+), 10 deletions(-) diff --git a/drivers/of/property.c b/drivers/of/property.c index 6c028632f425..bf3bdeeba2f9 100644 --- a/drivers/of/property.c +++ b/drivers/of/property.c @@ -650,15 +650,7 @@ struct device_node *of_graph_get_next_endpoint(const struct device_node *parent, * parent port node. */ if (!prev) { - struct device_node *node; - - node = of_get_child_by_name(parent, "ports"); - if (node) - parent = node; - - port = of_get_child_by_name(parent, "port"); - of_node_put(node); - + port = of_graph_get_next_port(parent, NULL); if (!port) { pr_err("graph: no port node found in %pOF\n", parent); return NULL; @@ -685,14 +677,59 @@ struct device_node *of_graph_get_next_endpoint(const struct device_node *parent, /* No more endpoints under this port, try the next one. */ prev = NULL; + port = of_graph_get_next_port(parent, port); + if (!port) + return NULL; + } +} +EXPORT_SYMBOL(of_graph_get_next_endpoint); + +/** + * of_graph_get_next_port() - get next port node + * @parent: pointer to the parent device node + * @prev: previous port node, or NULL to get first + * + * Return: An 'port' node pointer with refcount incremented. Refcount + * of the passed @prev node is decremented. + */ +struct device_node *of_graph_get_next_port(const struct device_node *parent, + struct device_node *prev) +{ + struct device_node *port = prev; + + if (!parent) + return NULL; + + /* + * Start by locating the port node. If no previous endpoint is specified + * search for the first port node, otherwise get the previous endpoint + * parent port node. + */ + if (!port) { + struct device_node *node; + + node = of_get_child_by_name(parent, "ports"); + if (node) + parent = node; + + port = of_get_child_by_name(parent, "port"); + of_node_put(node); + + if (!port) { + pr_err("graph: no port node found in %pOF\n", parent); + return NULL; + } + } else { do { port = of_get_next_child(parent, port); if (!port) return NULL; } while (!of_node_name_eq(port, "port")); } + + return port; } -EXPORT_SYMBOL(of_graph_get_next_endpoint); +EXPORT_SYMBOL(of_graph_get_next_port); /** * of_graph_get_endpoint_by_regs() - get endpoint node of specific identifiers @@ -819,6 +856,18 @@ int of_graph_get_endpoint_count(const struct device_node *np) } EXPORT_SYMBOL(of_graph_get_endpoint_count); +int of_graph_get_port_count(const struct device_node *np) +{ + struct device_node *port; + int num = 0; + + for_each_port_of_node(np, port) + num++; + + return num; +} +EXPORT_SYMBOL(of_graph_get_port_count); + /** * of_graph_get_remote_node() - get remote parent device_node for given port/endpoint * @node: pointer to parent device_node containing graph port/endpoint diff --git a/include/linux/of_graph.h b/include/linux/of_graph.h index 4d7756087b6b..8cd3bd674ebd 100644 --- a/include/linux/of_graph.h +++ b/include/linux/of_graph.h @@ -26,6 +26,17 @@ struct of_endpoint { const struct device_node *local_node; }; +/** + * for_each_port_of_node - iterate over every port in a device node + * @parent: parent device node containing ports and port + * @child: loop variable pointing to the current port node + * + * When breaking out of the loop, of_node_put(child) has to be called manually. + */ +#define for_each_port_of_node(parent, child) \ + for (child = of_graph_get_next_port(parent, NULL); child != NULL; \ + child = of_graph_get_next_port(parent, child)) + /** * for_each_endpoint_of_node - iterate over every endpoint in a device node * @parent: parent device node containing ports and endpoints @@ -41,8 +52,11 @@ struct of_endpoint { bool of_graph_is_present(const struct device_node *node); int of_graph_parse_endpoint(const struct device_node *node, struct of_endpoint *endpoint); +int of_graph_get_port_count(const struct device_node *np); int of_graph_get_endpoint_count(const struct device_node *np); struct device_node *of_graph_get_port_by_id(struct device_node *node, u32 id); +struct device_node *of_graph_get_next_port(const struct device_node *parent, + struct device_node *previous); struct device_node *of_graph_get_next_endpoint(const struct device_node *parent, struct device_node *previous); struct device_node *of_graph_get_endpoint_by_regs(