Skip to content

include: devicetree: Generate defines for map property #87595

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

soburi
Copy link
Member

@soburi soburi commented Mar 24, 2025

This change introduces generating definitions corresponding to
*-map property, which was currently discarded.

The *-map data is like a two-dimensional array, so it is difficult to
handle with the existing APIs, so we will also provide new APIs.


Common utilities have been separated into a separate PR.
Please take a look at this first. #84190


I noticed this problem while developing https://github.com/zephyrproject-rtos/gsoc-2022-arduino-core.

Since map is used to associate with the physical layout, there is a need to know the "physical pin names".

Since the mapping process is performed during the generation of devicetree-generated.h, I don't think there are many cases where information about the mapping source is needed. However, there are such cases, however rare, and it is not desirable for the information written in the devicetree to be discarded, so I would like to introduce this.

@soburi soburi force-pushed the dt_map_properties branch 10 times, most recently from 32aac28 to 6f69749 Compare March 26, 2025 05:03
@soburi soburi changed the title include: devicetree: Generate defines for map-related properties include: devicetree: Generate defines for map property Mar 26, 2025
@soburi soburi force-pushed the dt_map_properties branch from 6f69749 to 812c000 Compare March 26, 2025 05:16
@soburi soburi marked this pull request as ready for review March 26, 2025 06:02
@github-actions github-actions bot added area: Testsuite Testsuite area: ADC Analog-to-Digital Converter (ADC) area: Base OS Base OS Library (lib/os) area: GPIO area: Interrupt Controller area: Devicetree area: PCI Peripheral Component Interconnect labels Mar 26, 2025
Copy link
Contributor

@mbolivar mbolivar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR, @soburi . The first 5/8 patches look good to me, with one minor comment.

I have some concerns about the last 3/8 patches. I think I understand the goal and exposing the map properties as first-class citizens makes sense to me. However, the approach using to_compound() feels a little bit error-prone and I want to discuss the implementation.

Devicetree Specification v0.4 section 2.5, "Nexus Nodes and Specifier Mapping" is where the semantics are defined. There, it says:

A nexus node shall have a #<specifier>-cells property, where <specifier> is some specifier space such as ‘gpio’, ‘clock’, ‘reset’, etc

The description of the <specifier>-map property then says:

child specifier

The specifier of the child node being mapped. The number of 32-bit cells required to specify this component is described by the #<specifier>-cells property of this node—the nexus node containing the <specifier>-map property

It also says:

parent specifier

The specifier in the parent domain. The number of 32-bit cells required to specify this component is described by the #<specifier>-cells property of the specifier parent node.

Combining these, I think that we should be able to decode each <specifier>-map property without needing to_compound(). We can make a loop like this:

  1. Read #<specifier>-cells * 4 bytes from the current position in the <specifier>-map property. This is the child specifier. We can convert it to <u32> cells using existing dtlib features.
  2. Read the next 4 bytes. This is the "specifier parent" phandle from section 2.5 of the specification. We can convert it to a "specifier parent node" using phandle2node.
  3. Read the #<specifier>-cells property from the specifier parent node. This is the number of <u32> cells after the phandle which makes the "parent specifier"
  4. Read the parent specifier bytes and convert them to cells.

What I mean is, by using the #<specifier>-cells properties in the parent and child nodes, we can iterate through the <specifier>-map property and convert it into a lookup table without to_compound().

I am concerned that to_compound() is:

  • not checking the proper #<specifier>-cells values we expect to find, and instead just uses the source encoding to guess where the table entry elements are in <specifier>-map
  • adding a feature for strings that does not seem to be needed to handle <speciifer>-map properties -- this feels like it might be trying to do more than it needs to, and might have to be revisited over time as we add more heuristics

I'd be more comfortable with an approach that relied on the strict definitions in section 2.5 of the specification to decode the values of <specifier>-map properties. We can be sure that this will not change and the code will stand the test of time.

"#io-channel-cells":
type: int
required: true
description: Number of items to expect in a ADC specifier
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think, strictly speaking, that these are derived from the Linux iio bindings. The iio bindings are useful for ADCs but are not limited to ADCs. So perhaps this should be moved to dts/bindings/iio, and this "ADC specifier" portion should be changed to "channel specifier, e.g. ADC channel" or something similar?

Copy link
Member Author

@soburi soburi Apr 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's correct. I've taken care of that.

@soburi soburi force-pushed the dt_map_properties branch from e5f0587 to 5db662b Compare April 2, 2025 00:57
soburi added 4 commits April 2, 2025 10:19
Gets the specified number of elements from the beginning of the list.
This is the symmetircal operation as `GET_ARGS_LESS_N`.

Signed-off-by: TOKITA Hiroshi <[email protected]>
Add `GET_ARGS_FIRST_N` tests.

Signed-off-by: TOKITA Hiroshi <[email protected]>
They must be `array` type to match the existing `interrupt-map-mask`
and `interrupt-map-pass-thru`.

Signed-off-by: TOKITA Hiroshi <[email protected]>
Add a base binding for interrupt and io-channel nexus nodes.
This makes the implicit definitions explicit.
Replace existing individual map definitions with this.

This file does not define a specific `compatible` on its own,
So you should include this file before using it practically.

Signed-off-by: TOKITA Hiroshi <[email protected]>
@soburi soburi force-pushed the dt_map_properties branch from 5db662b to d069f45 Compare April 2, 2025 01:21
@soburi
Copy link
Member Author

soburi commented Apr 2, 2025

@mbolivar

Thanks for the PR, @soburi . The first 5/8 patches look good to me, with one minor comment.

I have some concerns about the last 3/8 patches. I think I understand the goal and exposing the map properties as first-class citizens makes sense to me. However, the approach using to_compound() feels a little bit error-prone and I want to discuss the implementation.

Devicetree Specification v0.4 section 2.5, "Nexus Nodes and Specifier Mapping" is where the semantics are defined. There, it says:

Thank you for your review.

I was also thinking about the implementation policy here, so
I would be happy to discuss it.

Before going into the implementation details, let me discuss a design-level topic.

I understand that the current implementation is designed as follows:

  • dtlib.py: Responsible for grammar processing
  • edtlib.py: Responsible for semantic interpretation

IMO, In this division of roles, the number of parameters specified in #gpio-cells is an issue in the "semantic" domain, so I think it would be better to implement the check in edtlib.py.

In that case, in the domain of dtlib.py, this is 'compound' as a syntax element, and even if string handling is left as 'not implemented', I think there should be a 'to_compound' method here.

I believe that once this division of roles is made clear, the implementation will become clear naturally, so I would like to get this issue resolved first.

@soburi soburi force-pushed the dt_map_properties branch from d069f45 to 1c94fcb Compare April 2, 2025 02:25
@soburi soburi requested a review from mbolivar April 2, 2025 02:43
@mbolivar
Copy link
Contributor

mbolivar commented Apr 2, 2025

@soburi thanks for your update. I agree we should discuss this design-level issue first.

The "compound" concept appears in both edtlib and dtlib:

  • in edtlib, we have the "compound" type in the bindings syntax, which I believe historically was added mainly to document and capture complex cases that we couldn't express in our existing syntax
  • in dtlib, the "compound" type in the DTS syntax parser exists as a catch-all for properties that we don't have special-case support for. It's important to remember that from the perspective of the DT specification, all properties are just byte arrays, and the source encoding was ignored by the consumer of the DTB as defined in chapter 5 of the specification. Zephyr is unique among operating systems in that it reads the DTS directly, of course. The dtlib parser has several special case "types" encoded in the dtlib.Type enum. For properties that don't fit in any special case, we can still access the byte array value, and the property is exposed as type dtlib.Type.COMPOUND.

I will try to be clear about which case I am talking about when we think about nexus nodes:

  • in edtlib, our existing bindings syntax doesn't have a concept of a nexus node and so the only way we can name such properties as <specifier>-map in the bindings is with type 'compound' in the bindings syntax

  • in dtlib, we are specifically concerned with the properties defined in section 2.5 of the specification, whose format and syntax fits into these dtlib types:

    • <specifier>-map: the specification describes properties of dtlib.Type.PHANDLES_AND_NUMS, not dtlib.Type.COMPOUND
    • <specifier>-map-mask: dtlib.Type.NUMS
    • <specifier>-map-pass-thru: dtlib.Type.NUMS
    • #<specifier>-cells: dtlib.Type.NUM

I think that since our dtlib parser already seems to have the right dtlib.Type special cases to handle nexus nodes, we probably don't need any dtlib changes to handle these. However, since the edtlib library doesn't have support for this pattern in its bindings syntax, I think we have two choices:

  1. extend the bindings syntax to add new special case types for <specifier>-map
  2. add special-case handling for this chapter of the devicetree specification, similarly to how we handled GPIO hogs

I think choice 2 is best, because this is a special case that is defined directly in the specification. We already allow edtlib to handle these types of special cases for things like the interrupt tree (DT specification section 2.4), major properties like reg and compatible (specification section 2.3), etc.

I outlined a way that I think we can implement option 2 that checks that the user's devicetree matches the requirements of specification section 2.5, Nexus Nodes and Specifier Mapping, in my previous review comment.

Does it make sense? What are your thoughts?

@soburi
Copy link
Member Author

soburi commented Apr 4, 2025

@mbolivar

Thank you for getting back to me.

Indeed, if I do it like this, I can use dtlib.py as it is.

diff --git a/dts/bindings/gpio/gpio-nexus.yaml b/dts/bindings/gpio/gpio-nexus.yaml
index de8153b0f9a..311e4cfb1cd 100644
--- a/dts/bindings/gpio/gpio-nexus.yaml
+++ b/dts/bindings/gpio/gpio-nexus.yaml
@@ -5,7 +5,7 @@

properties:
gpio-map:
- type: compound
+ type: phandle-array
required: true

gpio-map-mask:

It seems like it would be good to follow your suggestion in general,
but I will reconsider it based on this. Thanks.

@soburi soburi force-pushed the dt_map_properties branch from 1c94fcb to 7d636f4 Compare April 13, 2025 12:50
@github-actions github-actions bot requested a review from andyross April 13, 2025 12:51
@soburi soburi force-pushed the dt_map_properties branch 4 times, most recently from a4375ee to 5cff840 Compare April 13, 2025 18:06
@soburi
Copy link
Member Author

soburi commented Apr 13, 2025

@mbolivar

I finally solved the problem by adding a maps @Property to edtlib.
Could you review again, please?

@soburi soburi force-pushed the dt_map_properties branch from 5cff840 to f2abd03 Compare April 13, 2025 23:11
soburi added 2 commits April 14, 2025 08:30
This change introduces generating definitions corresponding to
`*-map` property, which was currently discarded.

For `*-map` properties are made able to be treated as a variation
of phandle-array, assign sequential cell names for each group of
specifiers (child_specifier_0, child_specifier_1, ...,
parent_specifier_0, ...).

The `*-map` data is like a two-dimensional array, so it is difficult to
handle with the existing APIs, so we will also provide new APIs.

Signed-off-by: TOKITA Hiroshi <[email protected]>
Add tests for map property related macros

Signed-off-by: TOKITA Hiroshi <[email protected]>
@soburi soburi force-pushed the dt_map_properties branch from f2abd03 to 15b948d Compare April 13, 2025 23:30
@soburi
Copy link
Member Author

soburi commented Apr 22, 2025

@mbolivar
ping

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: ADC Analog-to-Digital Converter (ADC) area: Base OS Base OS Library (lib/os) area: Devicetree area: GPIO area: Interrupt Controller area: PCI Peripheral Component Interconnect area: Testsuite Testsuite
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants