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 #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 #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 #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 #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_ */ 276