-
Notifications
You must be signed in to change notification settings - Fork 8.3k
scripts/dts: globals: parse gpio-map nodes #15861
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
Conversation
|
@mike-scott, I had a try on a (former) modified version of your PR and it worked. Can you have a try when you have some time? EDIT: Here is a branch making it working on top of #14057. Remaining detail is the change of a _0 to _1. Otherwise it, at least, compiles. I haven't been able to test though. |
scripts/dts/extract/globals.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused import
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oversight, txs!
scripts/dts/extract/globals.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using .get('gpio-map') instead of ['gpio-map'] here isn't safer, because if raw_map ever ends up as None, then len(raw_map) below will crash.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, so using ['gpio-map'], then.
This should not end up as None since function is called only if gpio-map in reduced....
scripts/dts/extract/globals.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto here, re. .get() vs. [].
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ack
scripts/dts/extract/globals.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto here, re. .get() vs. [].
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ack
scripts/dts/extract/globals.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A bare try: ... except: is usually a bad idea, because it will hide stuff like references to undefined Python variables as well (those throw exceptions).
Catch Exception instead, or (better) do a more explicit check for whatever this is checking, without using exceptions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, so actually this is the result of a late refactoring and this not chacking anything good anymore. Let me rework that.
EDIT: Actually it was catching stuff, but edited wrt your review
scripts/dts/extract/globals.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto here.
|
@ulfalizer, thanks for the review. Updated. |
ulfalizer
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think the function could have some x_to_y()-like name btw, so you can tell from the name what it maps to what? From the current name, you can only tell that it's doing some kind of mapping somehow related to GPIO.
scripts/dts/extract/globals.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does the : mean that cell_parent is a gpio-map? Might be clearer to write it out in that case ("cell_parent, which is a gpio-map").
"From the object provided" is a bit confusing since the function takes two arguments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reworked
scripts/dts/extract/globals.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These two are only used at the end of the function. Might be clearer to move them there, right before where they're used.
Then the documentation for the function ends up at the top too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
scripts/dts/extract/globals.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe gpio_map_lookup() could return None or something instead if the controller isn't found. Reading this quickly, you wonder if the IndexError is there to guard the elem[1] lookup or the like.
Exceptions for control flow often gets confusing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I reworked a bit, I'm not finding that much better in terms of exception, but seems more coherent in the dt object type handling. Let me know.
Absolutely. Thank you for working on this. I'll respond back once I kick the tires a bit and look through this. |
|
@erwango Actually, I don't see the branch based on the shield changes? Did I miss a link? |
|
@mike-scott, you didn't miss anything, I omited the paste operation. Here it is: https://github.com/erwango/zephyr/tree/test_14057_gpio_map EDIT: It does not contain the last changes of current PR, but this should not change the global behavior. |
scripts/dts/extract/globals.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could reflow this paragraph so that the lines are about the same length (with e.g. gq in Vim).
scripts/dts/extract/globals.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Accidental period in the middle of the sentence?
scripts/dts/extract/globals.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't immediately tell which of the [gpio_index], [child_specifier_size], and [controller_phandle] lookups are meant to be able to generate the IndexError under "normal" operation of the program here.
Better to do something like this, and avoid try/except completely:
if gpio_index not in map_array:
return None
...That makes the intention clear, and means that errors in the code won't be eaten by the except IndexError:.
scripts/dts/extract/globals.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be is not None, not is not 'None'. Just if not gpio_controller: should work though.
Something like this:
if not gpio_controller:
raise Exception("GPIO controller not found")
cell_parent = gpio_controller
scripts/dts/extract/globals.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto here.
|
@erwango I tested this tonight and noticed that the values for the PINs was the index of the gpio-map used (example is for Sara R4 modem -- see header pins 12 and 11): Example: To fix this, I used this hacky code which updates the prop_values based on the content of the gpio-map: And ended up with: |
|
@Hashcode, Txs for the info, it worked initially, but it seems I've not tested the refactoring enough. Let me rework that. |
|
@ulfalizer, here is the last batch, which has the merit of fixing bug reported by @Hashcode (so slightly more complex treatment) and I hope fixing your comments (hence somewhat more readable). |
scripts/dts/extract/globals.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Call it _ instead of unused. That's common in Python, and pylint knows not to flag it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, thanks for the hint.
scripts/dts/extract/globals.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is "v0.3" a typo? Can't find that version online.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's available here: https://github.com/devicetree-org/devicetree-specification/blob/4b1dac80eaca45b4babf5299452a951008a5d864/source/devicetree-basics.rst#nexus-nodes-and-specifier-mapping.
"Soon to be released" according to maintainer.
EDIT: I omitted to mention that this is already supported by zephyr dtc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure it'll be called v0.3?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Current one is v0.2, so I guess this is a reasonable assumption (https://www.devicetree.org/)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bad idea to refer to a v0.3 version that's not out and not sure to be called v0.3 I think. Could say something like "in the upcoming (presumably v0.3) Device Tree specification" instead.
Small typo: devide -> device
scripts/dts/extract/globals.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
More of a comment, but instead of "aim of this function...", it might be better to say what the function does.
"This function takes a foo and a bar and returns a (baz, qaz) tuple. If foo can't be found, this other value is returned instead", etc.
scripts/dts/extract/globals.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't get this part. How is child_specifier_size ("The number of 32-bit cells required to specify this component", according to the DT spec) related to phandles?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gpio-map is encoded in the following way:
gpio-map = <0 0 &soc_gpio1 1 0>,
<1 0 &soc_gpio2 4 0>,
<2 0 &soc_gpio1 3 0>,
<3 0 &soc_gpio2 2 0>;
Taking the first line:
0 0: Child specifier (pin number, pin flag)
&soc_gpio2: GPIO controller phandle
1 0: Parent specifier (pin number, pin flag)
At this point we're looking for GPIO controller phandle which is the element number 'child_specifier_size+1' in the line.
About gpio-map pin flags (does not relates directly to your question, but this might be required for the full comprehension of the change):
Assuming optional params gpio-map-mask and gpio-map-pass-thru are omitted, child and parent specifier pin flags are not taken into account and pin flag used is the one provided in calling node (typically used in shield overlay file), which is the behavior we expect, at least in current shield use case. This is "Assumption 2".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAICS, this is looking at #gpio-cells though. It's saying "the number of GPIO cells + 1 is a phandle". Seems weird to me.
Sorry if I'm missing something.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So:
0 0: Child specifier (pin number, pin flag) -> length provided by current node's #gpio-cell
&soc_gpio2: GPIO controller phandle
1 0: Parent specifier (pin number, pin flag) -> length provided by GPIO controller's #gpio-cell
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're never indexing into gpio-map though. You're taking #gpio-cells + 1 and directly treating that as a phandle.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, Txs!
scripts/dts/extract/globals.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Now that the length of each entry in 'gpio-map' is known..." maybe.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
scripts/dts/extract/globals.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think this could be called gpio_map_entries or the like?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
scripts/dts/extract/globals.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think this could be called gpio_map?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It could
scripts/dts/extract/globals.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
...then this would read as
gpio_map_entries.append(gpio_map[index:index+array_cell_size])
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yup
scripts/dts/extract/globals.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this looking up the right element?
Note that it's not comparing gpio_index against item[0] for each item in map_array, unlike the code above it.
Could maybe do something like this:
for entry in gpio_map_entries:
if entry[0] == gpio_index:
parent_controller_phandle = entry[child_specifier_size]
...
return phandles[...]
# gpio_index does not appear in gpio-map
return None, NoneThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, I kinda assumed first cell of each raw would be same as raw index.
This is indeed a shortcut, as it could be designed otherwise.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
scripts/dts/extract/globals.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could get rid of gpio_map_entries at this point, and do this:
for i in range(0, len(gpio_map), array_cell_size):
entry = gpio_map[i:i+array_cell_size]
if entry[0] == gpio_index:
...
return ...
# gpio_index did not match any entry in gpio-map
return None, NoneThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, and reworked comments
scripts/dts/extract/globals.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
*optional
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed, txs
scripts/dts/extract/globals.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Forgot to update this comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, fixed
scripts/dts/extract/globals.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still says "raws". Could say "the size of each entry in 'gpio-map'" or the like.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ohh... maybe 'raws' is a typo for 'rows'. I kept reading it as something "raw".
"Before parsing, we need to know the row size in 'gpio-map'", maybe.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, fixed
gpio-map is a property of "nexus node", defined in dts v0.3. It allows to describe a pin connector so it can be referenced through phandles and hence used in expansion device nodes like a shield header (typically implemented through overlays). This change implements gpio controller resolution through these maps. Few assumptions were taken in order to simplify the implementation. These assumptions bring some limitations to the use of gpio-map but my understanding is that this should still allow to cover most use cases. Assumptions: -gpio-size is the same for all gpio-controllers referenced in a map -optional properties gpio-map-mask and gpio-map-pass-thru are supposed to be omitted The understanding of this last assumption is that flags provided in the expansion device node will overwrite the connector flags. In a latter stage, when need happen, these limitations can be revisited to unlock fully fledged gpio-map usage. Fixes zephyrproject-rtos#15637 Signed-off-by: Erwan Gouriou <[email protected]>
| gpio_map = reduced[cell_parent]['props']['gpio-map'] | ||
|
|
||
| # Before parsing, we need to know 'gpio-map' row size | ||
| # gpio-map raws are encoded as follows: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
*rows
ulfalizer
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code nits fixed (except one raws -> rows typo).
Not an expert on how this is actually used, so someone else also ought to check.
Thanks for putting up with the nitting.
|
|
||
| return ret_array | ||
|
|
||
| def child_to_parent_unmap(cell_parent, gpio_index): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Unmap"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I felt child_to_parent was not enough specific.
map_extract?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gpio_map_index_to_controller or something maybe (wonder if _index_ could be _id_ too).
Maybe cell_parent could just be called node_path, since it's not important to the function itself that it's a parent of something that you're passing in.
Just random ideas though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gpio_map_child_to_parent ?
Thanks for the in deep review |
|
@mike-scott, updated https://github.com/erwango/zephyr/tree/test_14057_gpio_map with latest changes |
Thanks! I'll try again in a bit. |
|
@erwango nice job, newest change fixes the pin assignment. |
|
@MaureenHelm Can you take a look as I believe MCR20A and possibly other NXP boards have the potential to be used as shields including GPIO pin header assignments. |
Yes, MCR20A needs this feature to be converted to a shield (#7462). There is also an NXP sensor shield (#10198). I haven't studied this PR in detail yet, but at first glance it looks great. |
mike-scott
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
gpio-map is defined in dts v0.3 as "nexus node".
It allows to describe a pin connector so it can be referenced
through phandles and hence used in expansion device nodes
(typically implemented through overlays).
This change implements gpio controller resolution through these maps.
Few assumptions were taken in order to simplify the implementation.
These assumptions enforce some limitations to the use of gpio-map
but my understanding is that this should still allow to cover most
use cases.
Assumptions:
-gpio-size is the same for all gpio-controllers referenced in a map
-optional properties gpio-map-mask and gpio-map-pass-thru are
supposed to be omitted
The understanding of this last assumption is that flags provided in
the expansion device node will overwrite the connector flags
Fixes #15637
Signed-off-by: Erwan Gouriou [email protected]