Skip to content

Commit 871afee

Browse files
ydamigoskartben
authored andcommitted
edtlib: fix _raw_unit_addr() function
The '_raw_unit_addr()' function was incorrectly written a long time ago. It tries to look up and use the '#address-cells' of the node containing the 'interrupts' property itself, instead of using the '#address-cells' of the interrupt controller's node (or its parent). As a result, the mapping is successful only if the '#address-cells' value is the same in both the node and the interrupt controller, all other cases lead to random errors being generated by the 'gen_defines.py' script. Also, the function was trying to use the '#address-cells' value as a little-endian one, which led to unpredictable results as well. This problem has been fixed too. Fixes #77890, and probably #78020 Signed-off-by: Andrey VOLKOV <[email protected]> Signed-off-by: Ioannis Damigos <[email protected]>
1 parent 1b1bfc9 commit 871afee

File tree

1 file changed

+42
-13
lines changed
  • scripts/dts/python-devicetree/src/devicetree

1 file changed

+42
-13
lines changed

scripts/dts/python-devicetree/src/devicetree/edtlib.py

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2967,19 +2967,19 @@ def own_address_cells(node):
29672967
# _address_cells(), because it's the #address-cells property on 'node'
29682968
# itself that matters.
29692969

2970-
address_cells = node.props.get("#address-cells")
2971-
if not address_cells:
2970+
address_cells = _address_cells_self(node)
2971+
if address_cells is None:
29722972
_err(f"missing #address-cells on {node!r} "
29732973
"(while handling interrupt-map)")
2974-
return address_cells.to_num()
2974+
return address_cells
29752975

29762976
def spec_len_fn(node):
29772977
# Can't use _address_cells() here, because it's the #address-cells
29782978
# property on 'node' itself that matters
29792979
return own_address_cells(node) + _interrupt_cells(node)
29802980

29812981
parent, raw_spec = _map(
2982-
"interrupt", child, parent, _raw_unit_addr(child) + child_spec,
2982+
"interrupt", child, parent, _raw_unit_addr(child, parent) + child_spec,
29832983
spec_len_fn, require_controller=True)
29842984

29852985
# Strip the parent unit address part, if any
@@ -3143,22 +3143,42 @@ def _pass_thru(
31433143
return res[-len(parent_spec):]
31443144

31453145

3146-
def _raw_unit_addr(node: dtlib_Node) -> bytes:
3146+
def _raw_unit_addr(node: dtlib_Node, parent: dtlib_Node) -> bytes:
31473147
# _map_interrupt() helper. Returns the unit address (derived from 'reg' and
31483148
# #address-cells) as a raw 'bytes'
31493149

3150+
iparent: Optional[dtlib_Node] = parent
3151+
iparent_addr_len = _address_cells_self(iparent)
3152+
parent_addr_len = _address_cells(node)
3153+
3154+
if iparent_addr_len is None:
3155+
iparent_addr_len = 2 # Default value per DT spec.
3156+
3157+
if parent_addr_len is None:
3158+
parent_addr_len = 2 # Default value per DT spec.
3159+
3160+
if iparent_addr_len == 0:
3161+
return b''
3162+
31503163
if 'reg' not in node.props:
31513164
_err(f"{node!r} lacks 'reg' property "
31523165
"(needed for 'interrupt-map' unit address lookup)")
31533166

3154-
addr_len = 4*_address_cells(node)
3167+
iparent_addr_len *= 4
3168+
parent_addr_len *= 4
31553169

3156-
if len(node.props['reg'].value) < addr_len:
3157-
_err(f"{node!r} has too short 'reg' property "
3170+
prop_len = len(node.props['reg'].value)
3171+
if prop_len < iparent_addr_len or prop_len %4 != 0:
3172+
_err(f"{node!r} has too short or incorrectly defined 'reg' property "
31583173
"(while doing 'interrupt-map' unit address lookup)")
31593174

3160-
return node.props['reg'].value[:addr_len]
3175+
address = b''
3176+
if parent_addr_len > iparent_addr_len:
3177+
address = node.props['reg'].value[iparent_addr_len - parent_addr_len:parent_addr_len]
3178+
else:
3179+
address = node.props['reg'].value[:iparent_addr_len]
31613180

3181+
return address
31623182

31633183
def _and(b1: bytes, b2: bytes) -> bytes:
31643184
# Returns the bitwise AND of the two 'bytes' objects b1 and b2. Pads
@@ -3238,15 +3258,24 @@ def _phandle_val_list(
32383258
return res
32393259

32403260

3241-
def _address_cells(node: dtlib_Node) -> int:
3261+
def _address_cells_self(node: Optional[dtlib_Node]) -> Optional[int]:
32423262
# Returns the #address-cells setting for 'node', giving the number of <u32>
32433263
# cells used to encode the address in the 'reg' property
3264+
3265+
if node is not None and "#address-cells" in node.props:
3266+
return node.props["#address-cells"].to_num()
3267+
return None
3268+
3269+
def _address_cells(node: dtlib_Node) -> int:
3270+
# Returns the #address-cells setting for parent node of 'node', giving the number of <u32>
3271+
# cells used to encode the address in the 'reg' property
32443272
if TYPE_CHECKING:
32453273
assert node.parent
32463274

3247-
if "#address-cells" in node.parent.props:
3248-
return node.parent.props["#address-cells"].to_num()
3249-
return 2 # Default value per DT spec.
3275+
ret = _address_cells_self(node.parent)
3276+
if ret is None:
3277+
return 2 # Default value per DT spec.
3278+
return int(ret)
32503279

32513280

32523281
def _size_cells(node: dtlib_Node) -> int:

0 commit comments

Comments
 (0)