Line data Source code
1 1 : /**
2 : * @file
3 : * @brief Port / Endpoint Devicetree macro public API header file.
4 : */
5 :
6 : /*
7 : * Copyright 2024 NXP
8 : * Copyright (c) 2024 tinyVision.ai Inc
9 : *
10 : * SPDX-License-Identifier: Apache-2.0
11 : */
12 :
13 : #ifndef ZEPHYR_INCLUDE_DEVICETREE_PORT_ENDPOINT_H_
14 : #define ZEPHYR_INCLUDE_DEVICETREE_PORT_ENDPOINT_H_
15 :
16 : #ifdef __cplusplus
17 : extern "C" {
18 : #endif
19 :
20 : /**
21 : * @defgroup devicetree-port-endpoint Devicetree Port Endpoint API
22 : * @ingroup devicetree
23 : * @{
24 : */
25 :
26 : /**
27 : * @brief Helper for @ref DT_INST_PORT_BY_ID
28 : *
29 : * This behaves the same way as @ref DT_INST_PORT_BY_ID but does not work if there is only
30 : * a single port without address.
31 : *
32 : * @param inst instance number
33 : * @param pid port ID
34 : * @return port node associated with @p pid
35 : */
36 : #define _DT_INST_PORT_BY_ID(inst, pid) \
37 : COND_CODE_1(DT_NODE_EXISTS(DT_INST_CHILD(inst, ports)), \
38 : (DT_CHILD(DT_INST_CHILD(inst, ports), port_##pid)), (DT_INST_CHILD(inst, port_##pid)))
39 :
40 : /**
41 : * @brief Get a port node from its id
42 : *
43 : * Given a device instance number, return a port node specified by its ID.
44 : * It handles various ways of how a port could be defined.
45 : *
46 : * Example usage with DT_INST_PORT_BY_ID() to get the @c port@0 or @c port node:
47 : *
48 : * @code{.c}
49 : * DT_INST_PORT_BY_ID(inst, 0)
50 : * @endcode
51 : *
52 : * Example devicetree fragment:
53 : *
54 : * @code{.dts}
55 : * &device {
56 : * ports {
57 : * #address-cells = <1>;
58 : * #size-cells = <0>;
59 : * port@0 {
60 : * reg = <0x0>;
61 : * };
62 : * };
63 : * };
64 : * @endcode
65 : *
66 : * @code{.dts}
67 : * &device {
68 : * #address-cells = <1>;
69 : * #size-cells = <0>;
70 : * port@0 {
71 : * reg = <0x0>;
72 : * };
73 : * };
74 : * @endcode
75 : *
76 : * @code{.dts}
77 : * &device {
78 : * port {
79 : * };
80 : * };
81 : * @endcode
82 : *
83 : * @param inst instance number
84 : * @param pid port ID
85 : * @return port node associated with @p pid
86 : */
87 1 : #define DT_INST_PORT_BY_ID(inst, pid) \
88 : COND_CODE_1(DT_NODE_EXISTS(_DT_INST_PORT_BY_ID(inst, pid)), \
89 : (_DT_INST_PORT_BY_ID(inst, pid)), (DT_INST_CHILD(inst, port)))
90 :
91 : /**
92 : * @brief Helper for @ref DT_INST_ENDPOINT_BY_ID
93 : *
94 : * This behaves the same way as @ref DT_INST_PORT_BY_ID but does not work if there is only
95 : * a single endpoint without address.
96 : *
97 : * @param inst instance number
98 : * @param pid port ID
99 : * @param eid endpoint ID
100 : * @return endpoint node associated with @p eid and @p pid
101 : */
102 : #define _DT_INST_ENDPOINT_BY_ID(inst, pid, eid) \
103 : DT_CHILD(DT_INST_PORT_BY_ID(inst, pid), endpoint_##eid)
104 :
105 : /**
106 : * @brief Get an endpoint node from its id and its parent port id
107 : *
108 : * Given a device instance number, a port ID and an endpoint ID, return the endpoint node.
109 : * It handles various ways of how a port and an endpoint could be defined as described in
110 : * @ref DT_INST_PORT_BY_ID and below.
111 : *
112 : * Example usage with DT_INST_ENDPOINT_BY_ID() to get the @c endpoint or @c endpoint@0 node:
113 : *
114 : * @code{.c}
115 : * DT_INST_ENDPOINT_BY_ID(inst, 0, 0)
116 : * @endcode
117 : *
118 : * Example devicetree fragment:
119 : *
120 : * @code{.dts}
121 : * &device {
122 : * port {
123 : * endpoint {
124 : * };
125 : * };
126 : * };
127 : * @endcode
128 : *
129 : * @code{.dts}
130 : * &device {
131 : * port {
132 : * #address-cells = <1>;
133 : * #size-cells = <0>;
134 : * endpoint@0 {
135 : * reg = <0x0>;
136 : * };
137 : * };
138 : * };
139 : * @endcode
140 : *
141 : * @code{.dts}
142 : * &device {
143 : * ports {
144 : * #address-cells = <1>;
145 : * #size-cells = <0>;
146 : * port@0 {
147 : * reg = <0x0>;
148 : * #address-cells = <1>;
149 : * #size-cells = <0>;
150 : * endpoint@0 {
151 : * reg = <0x0>;
152 : * };
153 : * };
154 : * };
155 : * };
156 : * @endcode
157 : *
158 : * @param inst instance number
159 : * @param pid port ID
160 : * @param eid endpoint ID
161 : * @return endpoint node associated with @p eid and @p pid
162 : */
163 1 : #define DT_INST_ENDPOINT_BY_ID(inst, pid, eid) \
164 : COND_CODE_1(DT_NODE_EXISTS(_DT_INST_ENDPOINT_BY_ID(inst, pid, eid)), \
165 : (_DT_INST_ENDPOINT_BY_ID(inst, pid, eid)), \
166 : (DT_CHILD(DT_INST_PORT_BY_ID(inst, pid), endpoint)))
167 :
168 : /**
169 : * @brief Get the device node from its endpoint node.
170 : *
171 : * Given an endpoint node id, return its device node id.
172 : * This handles various ways of how a port and an endpoint could be defined as described in
173 : * @ref DT_NODE_BY_ENDPOINT.
174 : *
175 : * Example usage with DT_NODE_BY_ENDPOINT() to get the @c &device node from its @c ep0 node:
176 : *
177 : * @code{.c}
178 : * DT_NODE_BY_ENDPOINT(DT_NODELABEL(ep0))
179 : * @endcode
180 : *
181 : * Example devicetree fragment:
182 : *
183 : * @code{.dts}
184 : * &device {
185 : * port {
186 : * #address-cells = <1>;
187 : * #size-cells = <0>;
188 : * ep0: endpoint@0 {
189 : * reg = <0x0>;
190 : * };
191 : * };
192 : * };
193 : * @endcode
194 : *
195 : * @code{.dts}
196 : * &device {
197 : * ports {
198 : * #address-cells = <1>;
199 : * #size-cells = <0>;
200 : * port@0 {
201 : * reg = <0x0>;
202 : * #address-cells = <1>;
203 : * #size-cells = <0>;
204 : * ep0: endpoint@0 {
205 : * reg = <0x0>;
206 : * };
207 : * };
208 : * };
209 : * };
210 : * @endcode
211 : *
212 : * @param ep endpoint node
213 : * @return device node associated with @p ep
214 : */
215 1 : #define DT_NODE_BY_ENDPOINT(ep) \
216 : COND_CODE_1(DT_NODE_EXISTS(DT_CHILD(DT_PARENT(DT_GPARENT(ep)), ports)), \
217 : (DT_PARENT(DT_GPARENT(ep))), (DT_GPARENT(ep)))
218 :
219 : /**
220 : * @brief Get the remote device node from a local endpoint node.
221 : *
222 : * Given an endpoint node id, return the remote device node that connects to this device via this
223 : * local endpoint. This handles various ways of how a port and an endpoint could be defined as
224 : * described in @ref DT_INST_PORT_BY_ID and @ref DT_INST_ENDPOINT_BY_ID.
225 : *
226 : * Example usage with DT_NODE_REMOTE_DEVICE() to get the remote device node @c &device1 from the
227 : * local endpoint @c endpoint@0 node of the device @c &device0 node:
228 : *
229 : * @code{.c}
230 : * DT_NODE_REMOTE_DEVICE(DT_NODELABEL(device0_ep_out))
231 : * @endcode
232 : *
233 : * Example devicetree fragment:
234 : *
235 : * @code{.dts}
236 : * &device0 {
237 : * port {
238 : * #address-cells = <1>;
239 : * #size-cells = <0>;
240 : * device0_ep_out: endpoint@0 {
241 : * reg = <0x0>;
242 : * remote-endpoint-label = "device1_ep_in";
243 : * };
244 : * };
245 : * };
246 : *
247 : * &device1 {
248 : * ports {
249 : * #address-cells = <1>;
250 : * #size-cells = <0>;
251 : * port@0 {
252 : * reg = <0x0>;
253 : * device1_ep_in: endpoint {
254 : * remote-endpoint-label = "device0_ep_out";
255 : * };
256 : * };
257 : * };
258 : * };
259 : * @endcode
260 : *
261 : * @param ep endpoint node
262 : * @return remote device node that connects to this device via @p ep
263 : */
264 1 : #define DT_NODE_REMOTE_DEVICE(ep) \
265 : DT_NODE_BY_ENDPOINT(DT_NODELABEL(DT_STRING_TOKEN(ep, remote_endpoint_label)))
266 :
267 : /**
268 : * @}
269 : */
270 :
271 : #ifdef __cplusplus
272 : }
273 : #endif
274 :
275 : #endif /* ZEPHYR_INCLUDE_DEVICETREE_PORT_ENDPOINT_H_ */
|