From 464e59e1d31b1e707a79f13ccfa35aed7cbf1362 Mon Sep 17 00:00:00 2001 From: Josuah Demangeon Date: Fri, 18 Oct 2024 09:38:18 +0000 Subject: [PATCH] devicetree: add macros to deal with endpoints Add macros to access the port/endpoint constructs from drivers and application. Devicetrees currently use "port { endpoint { ... }; };" to describe interconnection between devices. With introduction of the "remote-endpoint-label = string" syntax, it is now possible to describe circular dependencies until #57708 is addressed. Signed-off-by: Josuah Demangeon --- dts/bindings/test/vnd,video.yaml | 10 +++++ include/zephyr/devicetree.h | 64 ++++++++++++++++++++++++++++ tests/lib/devicetree/api/app.overlay | 20 +++++++++ tests/lib/devicetree/api/src/main.c | 16 +++++++ 4 files changed, 110 insertions(+) create mode 100644 dts/bindings/test/vnd,video.yaml diff --git a/dts/bindings/test/vnd,video.yaml b/dts/bindings/test/vnd,video.yaml new file mode 100644 index 00000000000000..f9282ee934185b --- /dev/null +++ b/dts/bindings/test/vnd,video.yaml @@ -0,0 +1,10 @@ +# Copyright (c) 2024 tinyVision.ai Inc. +# SPDX-License-Identifier: Apache-2.0 + +description: Test Video device + +compatible: "vnd,video" + +child-binding: + child-binding: + include: video-interfaces.yaml diff --git a/include/zephyr/devicetree.h b/include/zephyr/devicetree.h index aba28c0ab63255..32c56e3e69f1c9 100644 --- a/include/zephyr/devicetree.h +++ b/include/zephyr/devicetree.h @@ -3787,6 +3787,70 @@ */ #define DT_ON_BUS(node_id, bus) IS_ENABLED(DT_CAT3(node_id, _BUS_, bus)) +/** + * @} + */ + +/** + * @defgroup devicetree-generic-endpoint Endpoint helpers + * @ingroup devicetree + * @{ + */ + +/** + * @brief Get the remote endpoint node connected to a local endpoint. + * + * Devices can be interconnected through ports and endpoints. + * + * Example devicetree overlay: + * + * @code{.dts} + * &source { + * port { + * source_out: endpoint { + * remote-endpoint-label = "sink_in"; + * source-property = <1>; + * }; + * }; + * }; + * + * &sink { + * port { + * sink_in: endpoint { + * remote-endpoint-label = "source_out"; + * sink-property = <2>; + * }; + * }; + * }; + * @endcode + * + * @c DT_REMOTE_ENDPOINT(endpoint_node) permits to access the other endpoint + * connected to @c endpoint_node. + * + * Example usage: starting from the sink, access the source endpoint connected + * to the @c sink_in endpoint: + * + * @code{.c} + * DT_PROP(DT_REMOTE_ENDPOINT(DT_NODELABEL(sink_in)), source_property) + * @endcode + * + * Example usage, starting from the source, to access the sink endpoint + * connected to the @c source_out endpoint: + * + * @code{.c} + * DT_PROP(DT_REMOTE_ENDPOINT(DT_NODELABEL(source_out)), sink_property) + * @endcode + * + * @note Once circular phandle references are supported in Zephyr devicetree, + * @c remote-endpoint-label (string) may be changed into + * @c remote-endpoint (phandle). + * + * @param node The local endpoint node to use. + * + * @return The remote endpoint node connected to @p node. + */ +#define DT_REMOTE_ENDPOINT(node) DT_NODELABEL(DT_STRING_TOKEN(node, remote_endpoint_label)) + /** * @} */ diff --git a/tests/lib/devicetree/api/app.overlay b/tests/lib/devicetree/api/app.overlay index 359f17066a2d7b..989f93613535c4 100644 --- a/tests/lib/devicetree/api/app.overlay +++ b/tests/lib/devicetree/api/app.overlay @@ -506,6 +506,26 @@ status = "okay"; }; + test_video_source: video_source { + compatible = "vnd,video"; + + port { + test_video_source_out: endpoint { + remote-endpoint-label = "test_video_sink_in"; + }; + }; + }; + + test_video_sink: video_sink { + compatible = "vnd,video"; + + port { + test_video_sink_in: endpoint { + remote-endpoint-label = "test_video_source_out"; + }; + }; + }; + test_pwm1: pwm@55551111 { compatible = "vnd,pwm"; #pwm-cells = <3>; diff --git a/tests/lib/devicetree/api/src/main.c b/tests/lib/devicetree/api/src/main.c index d4dd12cf733bef..fc6dfc77aba8e8 100644 --- a/tests/lib/devicetree/api/src/main.c +++ b/tests/lib/devicetree/api/src/main.c @@ -76,6 +76,9 @@ #define TEST_DMA_CTLR_1 DT_NODELABEL(test_dma1) #define TEST_DMA_CTLR_2 DT_NODELABEL(test_dma2) +#define TEST_VIDEO_SOURCE_OUT DT_NODELABEL(test_video_source_out) +#define TEST_VIDEO_SINK_IN DT_NODELABEL(test_video_sink_in) + #define TEST_IO_CHANNEL_CTLR_1 DT_NODELABEL(test_adc_1) #define TEST_IO_CHANNEL_CTLR_2 DT_NODELABEL(test_adc_2) @@ -1278,6 +1281,19 @@ ZTEST(devicetree_api, test_dma) zassert_false(DT_INST_DMAS_HAS_IDX(0, 2), ""); } +#undef DT_DRV_COMPAT +#define DT_DRV_COMPAT vnd_video_device +ZTEST(devicetree_api, test_video) +{ + /* DT_REMOTE_ENDPOINT(source) */ + zassert_true(DT_SAME_NODE(DT_REMOTE_ENDPOINT(TEST_VIDEO_SOURCE_OUT), + TEST_VIDEO_SINK_IN), ""); + + /* DT_REMOTE_ENDPOINT(sink) */ + zassert_true(DT_SAME_NODE(DT_REMOTE_ENDPOINT(TEST_VIDEO_SINK_IN), + TEST_VIDEO_SOURCE_OUT), ""); +} + #undef DT_DRV_COMPAT #define DT_DRV_COMPAT vnd_phandle_holder ZTEST(devicetree_api, test_pwms)