Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

of: property: add of_graph_get_next_port()

We have endpoint base functions
- of_graph_get_next_endpoint()
- of_graph_get_endpoint_count()
- for_each_endpoint_of_node()

Here, for_each_endpoint_of_node() loop finds each endpoints

ports {
port@0 {
(1) endpoint {...};
};
port@1 {
(2) endpoint {...};
};
...
};

In above case, it finds endpoint as (1) -> (2) -> ...

Basically, user/driver knows which port is used for what, but not in
all cases. For example on flexible/generic driver case, how many ports
are used is not fixed.

For example Sound Generic Card driver which is very flexible/generic and
used from many venders can't know how many ports are used, and used for
what, because it depends on each vender SoC and/or its used board.

And more, the port can have multi endpoints. For example Generic Sound
Card case, it supports many type of connection between CPU / Codec, and
some of them uses multi endpoint in one port. see below.

ports {
(A) port@0 {
(1) endpoint@0 {...};
(2) endpoint@1 {...};
};
(B) port@1 {
(3) endpoint {...};
};
...
};

Generic Sound Card want to handle each connection via "port" base instead
of "endpoint" base. But, it is very difficult to handle each "port" via
existing for_each_endpoint_of_node(). Because getting each "port" via
of_get_parent() from each "endpoint" doesn't work. For example in above
case, both (1) (2) endpoint has same "port" (= A).

Add "port" base functions.

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Link: https://lore.kernel.org/r/87ldyeb5t9.wl-kuninori.morimoto.gx@renesas.com
Signed-off-by: Rob Herring (Arm) <robh@kernel.org>

authored by

Kuninori Morimoto and committed by
Rob Herring (Arm)
02ac5f9d 2e030910

+82
+54
drivers/of/property.c
··· 631 631 EXPORT_SYMBOL(of_graph_get_port_by_id); 632 632 633 633 /** 634 + * of_graph_get_next_port() - get next port node. 635 + * @parent: pointer to the parent device node, or parent ports node 636 + * @prev: previous port node, or NULL to get first 637 + * 638 + * Parent device node can be used as @parent whether device node has ports node 639 + * or not. It will work same as ports@0 node. 640 + * 641 + * Return: A 'port' node pointer with refcount incremented. Refcount 642 + * of the passed @prev node is decremented. 643 + */ 644 + struct device_node *of_graph_get_next_port(const struct device_node *parent, 645 + struct device_node *prev) 646 + { 647 + if (!parent) 648 + return NULL; 649 + 650 + if (!prev) { 651 + struct device_node *node __free(device_node) = 652 + of_get_child_by_name(parent, "ports"); 653 + 654 + if (node) 655 + parent = node; 656 + 657 + return of_get_child_by_name(parent, "port"); 658 + } 659 + 660 + do { 661 + prev = of_get_next_child(parent, prev); 662 + if (!prev) 663 + break; 664 + } while (!of_node_name_eq(prev, "port")); 665 + 666 + return prev; 667 + } 668 + EXPORT_SYMBOL(of_graph_get_next_port); 669 + 670 + /** 634 671 * of_graph_get_next_endpoint() - get next endpoint node 635 672 * @parent: pointer to the parent device node 636 673 * @prev: previous endpoint node, or NULL to get first ··· 859 822 return num; 860 823 } 861 824 EXPORT_SYMBOL(of_graph_get_endpoint_count); 825 + 826 + /** 827 + * of_graph_get_port_count() - get the number of port in a device or ports node 828 + * @np: pointer to the device or ports node 829 + * 830 + * Return: count of port of this device or ports node 831 + */ 832 + unsigned int of_graph_get_port_count(struct device_node *np) 833 + { 834 + unsigned int num = 0; 835 + 836 + for_each_of_graph_port(np, port) 837 + num++; 838 + 839 + return num; 840 + } 841 + EXPORT_SYMBOL(of_graph_get_port_count); 862 842 863 843 /** 864 844 * of_graph_get_remote_node() - get remote parent device_node for given port/endpoint
+28
include/linux/of_graph.h
··· 11 11 #ifndef __LINUX_OF_GRAPH_H 12 12 #define __LINUX_OF_GRAPH_H 13 13 14 + #include <linux/cleanup.h> 14 15 #include <linux/types.h> 15 16 #include <linux/errno.h> 16 17 ··· 38 37 for (child = of_graph_get_next_endpoint(parent, NULL); child != NULL; \ 39 38 child = of_graph_get_next_endpoint(parent, child)) 40 39 40 + /** 41 + * for_each_of_graph_port - iterate over every port in a device or ports node 42 + * @parent: parent device or ports node containing port 43 + * @child: loop variable pointing to the current port node 44 + * 45 + * When breaking out of the loop, and continue to use the @child, you need to 46 + * use return_ptr(@child) or no_free_ptr(@child) not to call __free() for it. 47 + */ 48 + #define for_each_of_graph_port(parent, child) \ 49 + for (struct device_node *child __free(device_node) = of_graph_get_next_port(parent, NULL);\ 50 + child != NULL; child = of_graph_get_next_port(parent, child)) 51 + 41 52 #ifdef CONFIG_OF 42 53 bool of_graph_is_present(const struct device_node *node); 43 54 int of_graph_parse_endpoint(const struct device_node *node, 44 55 struct of_endpoint *endpoint); 45 56 unsigned int of_graph_get_endpoint_count(const struct device_node *np); 57 + unsigned int of_graph_get_port_count(struct device_node *np); 46 58 struct device_node *of_graph_get_port_by_id(struct device_node *node, u32 id); 47 59 struct device_node *of_graph_get_next_endpoint(const struct device_node *parent, 48 60 struct device_node *previous); 61 + struct device_node *of_graph_get_next_port(const struct device_node *parent, 62 + struct device_node *port); 49 63 struct device_node *of_graph_get_endpoint_by_regs( 50 64 const struct device_node *parent, int port_reg, int reg); 51 65 struct device_node *of_graph_get_remote_endpoint( ··· 89 73 return 0; 90 74 } 91 75 76 + static inline unsigned int of_graph_get_port_count(struct device_node *np) 77 + { 78 + return 0; 79 + } 80 + 92 81 static inline struct device_node *of_graph_get_port_by_id( 93 82 struct device_node *node, u32 id) 94 83 { ··· 101 80 } 102 81 103 82 static inline struct device_node *of_graph_get_next_endpoint( 83 + const struct device_node *parent, 84 + struct device_node *previous) 85 + { 86 + return NULL; 87 + } 88 + 89 + static inline struct device_node *of_graph_get_next_port( 104 90 const struct device_node *parent, 105 91 struct device_node *previous) 106 92 {